api-ts-utils
Advanced tools
Sorry, the diff of this file is not supported yet
| /// <reference types="node" /> | ||
| import { DecoratedFunction, Controller, Router } from "./types"; | ||
| /** | ||
| * Generate the express routes fron the router, controller, and method declarations. Make | ||
| * use of the fact that the generated file '__check.js' will always be located in the same | ||
| * directory as the routes file '__routes.js'. Make use of supporting files from this package | ||
| * to create instances of the controller classes. The form of this file when used as a target | ||
| * to require is to export a single function that takes a single argument of type RouterBase | ||
| * (which the class annotated with @router should derive from), and when invoked will create | ||
| * all of the controllers, and add them to the the router, and then connect the controllers | ||
| * to express app; it is assumed that the router class will have a reference to app at the time, | ||
| * but it should since this is a required parameter to RouterBase constructor. Generate | ||
| * a app.{get,post,put,...} for each method of a controller an analogous annotation. | ||
| * | ||
| * @param {DecoratedFunction[]} endpoints A array of all of the methods decorated with REST verbs. | ||
| * @param {Router} top level router class. | ||
| * @param {Controller[]} controllers array of method controllers | ||
| * @param {NodeJS.ReadWriteStream} routesFile reference to the routes output file. | ||
| */ | ||
| export declare function genExpressRoutes(endpoints: DecoratedFunction[], router: Router, controllers: Controller[], srcRoot: string, routesFile: NodeJS.ReadWriteStream): string; |
| "use strict"; | ||
| Object.defineProperty(exports, "__esModule", { value: true }); | ||
| var ts = require("typescript"); | ||
| var path = require("path"); | ||
| var tsany = ts; | ||
| var symtab_1 = require("./symtab"); | ||
| var traverse_1 = require("./traverse"); | ||
| function genAssignment1(id, dataSource, kind, typeSpec, content) { | ||
| var output = ""; | ||
| var type = typeSpec.type; | ||
| if (content != "flat" && (type == "object" || type == null || type == "array")) { | ||
| if (type == "array") { | ||
| if (typeSpec.items.type == "object" || typeSpec.items['$ref'] != null) { | ||
| output = " let " + id + ";\n"; | ||
| } | ||
| else { | ||
| if (kind == "urlParam") | ||
| output = " let " + id + " = req.params." + id + ";\n"; | ||
| else | ||
| output = " let " + id + " = req." + dataSource + "." + id + ";\n"; | ||
| } | ||
| } | ||
| else { | ||
| output = " let " + id + ";\n"; | ||
| } | ||
| } | ||
| else { | ||
| if (kind == "urlParam") | ||
| output = " let " + id + " = req.params." + id + ";\n"; | ||
| else | ||
| output = " let " + id + " = req." + dataSource + "." + id + ";\n"; | ||
| } | ||
| return output; | ||
| } | ||
| function genAssignment2(id, dataSource, kind, typeSpec, content) { | ||
| var output = ""; | ||
| var type = typeSpec.type; | ||
| if (content != "flat" && (type == "object" || type == null || type == "array")) { | ||
| if (type == "array") { | ||
| if (typeSpec.items.type == "object" || typeSpec.items['$ref'] != null) { | ||
| if (kind == "urlParam") | ||
| output = " try { " + id + " = (typeof req.params." + id + " == \"string\")?JSON.parse(req.params." + id + "):req.params." + id + "; } catch(e) {};\n"; | ||
| else | ||
| output = " try { " + id + " = (typeof req." + dataSource + "." + id + " == \"string\")?JSON.parse(req." + dataSource + "." + id + "):req." + dataSource + "." + id + "; } catch(e) {};\n"; | ||
| } | ||
| } | ||
| else { | ||
| if (kind == "urlParam") | ||
| output = " try { " + id + " = (typeof req.params." + id + " == \"string\")?JSON.parse(req.params." + id + "):req.params." + id + "; } catch(e) {};\n"; | ||
| else | ||
| output = " try { " + id + " = (typeof req." + dataSource + "." + id + " == \"string\")?JSON.parse(req." + dataSource + "." + id + "):req." + dataSource + "." + id + "; } catch(e) {};\n"; | ||
| } | ||
| } | ||
| return output; | ||
| } | ||
| function genAssignment3(id, dataSource, kind, typeSpec, content) { | ||
| var output = ""; | ||
| var type = typeSpec.type; | ||
| if (type == "array") { | ||
| output += " if(" + id + " != null) {\n"; | ||
| output += " if(!Array.isArray(" + id + ")) " + id + " = [" + id + "];\n"; | ||
| output += " }\n"; | ||
| } | ||
| return output; | ||
| } | ||
| function genControllerArgAssignmentsA(dataSource, params, endpointName, genFunc) { | ||
| var output = ""; | ||
| for (var i = 0; i < params.length; i++) | ||
| output += genFunc(params[i].id, dataSource, params[i].kind, params[i].type, params[i].type.content); | ||
| return output; | ||
| } | ||
| function genControllerArgAssignmentsB(dataSource, params, endpointName, genFunc, argListFormal) { | ||
| var output = ""; | ||
| for (var i = 0; i < params.length; i++) { | ||
| if (params[i].kind == "urlParam") { | ||
| output += genFunc(params[i].id, dataSource, params[i].kind, params[i].type, params[i].type.content); | ||
| if (argListFormal != null) | ||
| argListFormal.push(params[i].id); | ||
| } | ||
| else { | ||
| if (params[i].type.type == "object") { | ||
| var properties = params[i].type.properties; | ||
| var objArgs = []; | ||
| for (var propertyName in properties) { | ||
| output += genFunc(propertyName, dataSource, "regular", properties[propertyName], properties[propertyName].content); | ||
| objArgs.push(propertyName); | ||
| } | ||
| if (argListFormal != null) | ||
| argListFormal.push(objArgs); | ||
| } | ||
| else { | ||
| output += genFunc(params[i].id, dataSource, params[i].kind, params[i].type, params[i].type.content); | ||
| if (argListFormal != null) | ||
| argListFormal.push(params[i].id); | ||
| } | ||
| } | ||
| } | ||
| return output; | ||
| } | ||
| function genControllerArgListA(dataSource, params, endpointName) { | ||
| var output = ""; | ||
| var assignments1 = genControllerArgAssignmentsA(dataSource, params, endpointName, genAssignment1); | ||
| var assignments2 = genControllerArgAssignmentsA(dataSource, params, endpointName, genAssignment2); | ||
| var assignments3 = genControllerArgAssignmentsA(dataSource, params, endpointName, genAssignment3); | ||
| if (assignments1 != "") | ||
| output += "" + assignments1; | ||
| if (assignments2 != "") | ||
| output += "\n" + assignments2 + "\n"; | ||
| if (assignments3 != "") | ||
| output += "\n" + assignments3 + "\n"; | ||
| output += " const __res = await controller." + endpointName + "("; | ||
| for (var i = 0; i < params.length; i++) { | ||
| if (i != 0) | ||
| output += ','; | ||
| output += "" + params[i].id; | ||
| } | ||
| output += ");\n\n"; | ||
| return output; | ||
| } | ||
| function genControllerArgListB(dataSource, params, endpointName) { | ||
| var output = ""; | ||
| var argListFormal = []; | ||
| var assignments1 = genControllerArgAssignmentsB(dataSource, params, endpointName, genAssignment1, argListFormal); | ||
| var assignments2 = genControllerArgAssignmentsB(dataSource, params, endpointName, genAssignment2, null); | ||
| var assignments3 = genControllerArgAssignmentsB(dataSource, params, endpointName, genAssignment3, null); | ||
| var anum; | ||
| if (assignments1 != "") | ||
| output += "" + assignments1; | ||
| if (assignments2 != "") | ||
| output += "\n" + assignments2 + "\n"; | ||
| if (assignments3 != "") | ||
| output += "\n" + assignments3 + "\n"; | ||
| for (var i = 0; i < argListFormal.length; i++) { | ||
| if (typeof argListFormal[i] != "string") { | ||
| if (anum == null) | ||
| anum = 0; | ||
| output += " let __arg" + anum++ + " = {};\n"; | ||
| } | ||
| } | ||
| if (anum != null) { | ||
| anum = 0; | ||
| for (var i = 0; i < argListFormal.length; i++) { | ||
| if (typeof argListFormal[i] != "string") { | ||
| for (var j = 0; j < argListFormal[i].length; j++) { | ||
| output += " if(" + argListFormal[i][j] + " != null) __arg" + anum + "." + argListFormal[i][j] + " = " + argListFormal[i][j] + ";\n"; | ||
| } | ||
| anum++; | ||
| } | ||
| } | ||
| } | ||
| if (anum != null) | ||
| anum = 0; | ||
| output += " const __res = await controller." + endpointName + "("; | ||
| for (var i = 0; i < argListFormal.length; i++) { | ||
| if (i != 0) | ||
| output += ','; | ||
| if (typeof argListFormal[i] == "string") | ||
| output += "" + argListFormal[i]; | ||
| else | ||
| output += "__arg" + anum++; | ||
| } | ||
| output += ");\n\n"; | ||
| return output; | ||
| } | ||
| /** | ||
| * Generate the express routes fron the router, controller, and method declarations. Make | ||
| * use of the fact that the generated file '__check.js' will always be located in the same | ||
| * directory as the routes file '__routes.js'. Make use of supporting files from this package | ||
| * to create instances of the controller classes. The form of this file when used as a target | ||
| * to require is to export a single function that takes a single argument of type RouterBase | ||
| * (which the class annotated with @router should derive from), and when invoked will create | ||
| * all of the controllers, and add them to the the router, and then connect the controllers | ||
| * to express app; it is assumed that the router class will have a reference to app at the time, | ||
| * but it should since this is a required parameter to RouterBase constructor. Generate | ||
| * a app.{get,post,put,...} for each method of a controller an analogous annotation. | ||
| * | ||
| * @param {DecoratedFunction[]} endpoints A array of all of the methods decorated with REST verbs. | ||
| * @param {Router} top level router class. | ||
| * @param {Controller[]} controllers array of method controllers | ||
| * @param {NodeJS.ReadWriteStream} routesFile reference to the routes output file. | ||
| */ | ||
| function genExpressRoutes(endpoints, router, controllers, srcRoot, routesFile) { | ||
| var output = "\"use strict\";\n\n"; | ||
| var resolvedRoot; | ||
| var controllerIndex = {}; | ||
| if (srcRoot != null) | ||
| resolvedRoot = path.resolve(srcRoot).replace(/\\/g, '/'); | ||
| output += "const express = require('express');\n"; | ||
| output += "const api = require('ts-api');\n"; | ||
| output += "const EndpointCheckBinding = api.EndpointCheckBinding;\n"; | ||
| output += "const ControllerProperties = api.ControllerProperties;\n"; | ||
| output += "const error_response = api.response.error;\n"; | ||
| output += "const success_response = api.response.success;\n"; | ||
| // Generate requires for controller classes. Use parser support for | ||
| // the file they are defined in to provide the parameter for require. | ||
| for (var i = 0; i < controllers.length; i++) { | ||
| var fileName = path.resolve(controllers[i].fileName).replace(/\\/g, '/'); | ||
| if (srcRoot != null) { | ||
| fileName = fileName.replace(resolvedRoot + '/', ''); | ||
| fileName = fileName.replace(path.extname(fileName), ""); | ||
| output += "const " + controllers[i].classRef + "Module = require('./" + fileName + "');\n"; | ||
| } | ||
| else | ||
| output += "const " + controllers[i].classRef + "Module = require('./" + path.basename(fileName) + "');\n"; | ||
| controllerIndex[controllers[i].classRef] = controllers[i]; | ||
| } | ||
| // include support for automatic swagger document display endpoint. Avoid | ||
| // requiring that package directory by proxying the require through ts-api. | ||
| // make use of the guaranteed location of the swagger doc that is generated | ||
| // relative to the routes file. | ||
| output += "const swaggerUi = api.swaggerUi;\n"; | ||
| output += "const swaggerDocument = require('./docs/swagger.json');\n"; | ||
| output += "\nlet binding = new EndpointCheckBinding(require('./__check'));\n"; | ||
| output += "\nmodule.exports = function(root) {\n"; | ||
| var routerPath = traverse_1.decompositionToPath(router.decomposition, "express"); | ||
| for (var i = 0; i < controllers.length; i++) { | ||
| var path_1 = '/' + traverse_1.decompositionToPath(controllers[i].decomposition, "express"); | ||
| if (routerPath != "") | ||
| path_1 = "/" + routerPath + path_1; | ||
| output += " root.addRouter('" + path_1 + "','" + controllers[i].classRef + "',{ mergeParams:true });\n"; | ||
| } | ||
| for (var i = 0; i < endpoints.length; i++) { | ||
| var rfunc = endpoints[i].type; | ||
| var endpointName = endpoints[i].name; | ||
| var path_2 = endpointName; | ||
| var dataSource = "query"; | ||
| if (endpoints[i].decoratorArgs.length != 0) | ||
| path_2 = endpoints[i].decoratorArgs[0]; | ||
| var endpointPathDecomposition = traverse_1.decomposePath(path_2); | ||
| var endpointPath = traverse_1.decompositionToPath(endpointPathDecomposition, "express"); | ||
| // For each method, tie everything together by creating the right controller instance, | ||
| // collecting the express REST parameters, converting it to the method parameters, and then | ||
| // invoking the method with those parameters. Assume coordiation with the | ||
| // express verb decorator defined in this package. | ||
| output += "\n"; | ||
| output += " root.getExpressRouter('" + endpoints[i].classRef + "')." + rfunc + "('/" + endpointPath + "', async(req,res,next) => {\n"; | ||
| output += " try {\n"; | ||
| if (rfunc != 'get') { | ||
| output += " if(req.body == null) throw(\"body is null (possible missing body parser)\")\n"; | ||
| dataSource = "body"; | ||
| } | ||
| output += " const properties = new ControllerProperties(binding,root.context,req,res,next);\n"; | ||
| output += " const controller = new " + endpoints[i].classRef + "Module.default(properties);\n"; | ||
| var params = []; | ||
| var numURLParam = 0; | ||
| // Gather parameter metadata prior to output | ||
| for (var j = 0; j < endpoints[i].methodParameters.length; j++) { | ||
| var parm = endpoints[i].methodParameters[j]; | ||
| var jsDoc = traverse_1.synthesizeParameterJSDoc(endpoints[i].methodParameters[j]); | ||
| var parmType = symtab_1.typeToJSON(parm.type, jsDoc, { expandRefs: true, firstclassIntermediates: true, schemaNamespace: "swagger", docRoot: "#/definitions" }); | ||
| if (parm.decorators != null) { | ||
| var isURLDecorated = false; | ||
| for (var decoratorName in parm.decorators) { | ||
| if (decoratorName == 'urlParam') { | ||
| var decoratorArgs = parm.decorators[decoratorName]; | ||
| if (decoratorArgs.length) | ||
| params.push({ id: decoratorArgs[0], kind: "urlParam" }); | ||
| else | ||
| params.push({ id: parm.id, kind: "urlParam", type: parmType }); | ||
| numURLParam += 1; | ||
| } | ||
| } | ||
| if (!isURLDecorated) { | ||
| if (traverse_1.isURLParam(parm.id, router, controllerIndex[endpoints[i].classRef], endpointPathDecomposition)) { | ||
| params.push({ id: parm.id, kind: "urlParam", type: parmType }); | ||
| numURLParam += 1; | ||
| } | ||
| else | ||
| params.push({ id: parm.id, kind: "regular", type: parmType }); | ||
| } | ||
| } | ||
| else if (traverse_1.isURLParam(parm.id, router, controllerIndex[endpoints[i].classRef], endpointPathDecomposition)) { | ||
| params.push({ id: parm.id, kind: "urlParam", type: parmType }); | ||
| numURLParam += 1; | ||
| } | ||
| else | ||
| params.push({ id: parm.id, kind: "regular", type: parmType }); | ||
| } | ||
| if (params.length - numURLParam > 1) | ||
| output += genControllerArgListA(dataSource, params, endpointName); | ||
| else | ||
| output += genControllerArgListB(dataSource, params, endpointName); | ||
| output += " success_response(__res,req,res,next);\n"; | ||
| output += " }\n"; | ||
| output += " catch(e) { error_response(e,req,res,next); }\n"; | ||
| output += " });\n"; | ||
| } | ||
| var docPath = '/docs'; | ||
| var redocPath = '/redoc'; | ||
| var staticPath = '/doc-static'; | ||
| var swaggerPath = '/doc-static/swagger.json'; | ||
| if (routerPath != "") { | ||
| docPath = "/" + routerPath + docPath; | ||
| redocPath = "/" + routerPath + redocPath; | ||
| staticPath = "/" + routerPath + staticPath; | ||
| swaggerPath = "/" + routerPath + swaggerPath; | ||
| } | ||
| output += " root.getExpressRouter().use('" + docPath + "',swaggerUi.serve,swaggerUi.setup(swaggerDocument));\n"; | ||
| output += " root.getExpressRouter().get('" + redocPath + "',function(req,res,next) {\n "; | ||
| output += " res.sendFile(__dirname + '/docs/redoc.html');\n"; | ||
| output += " });\n"; | ||
| output += " root.getExpressRouter().use('" + staticPath + "',express.static(__dirname + '/docs'));\n"; | ||
| output += " return root.getExpressRouter();\n"; | ||
| output += "}\n"; | ||
| routesFile.write(output); | ||
| return swaggerPath; | ||
| } | ||
| exports.genExpressRoutes = genExpressRoutes; | ||
| //# sourceMappingURL=express_routes.js.map |
| {"version":3,"file":"express_routes.js","sourceRoot":"","sources":["../../src/analyzer/express_routes.ts"],"names":[],"mappings":";;AAAA,+BAAiC;AACjC,2BAA6B;AAE7B,IAAM,KAAK,GAAG,EAAS,CAAC;AAGxB,mCAAsC;AACtC,uCAAsG;AAEtG,SAAS,cAAc,CAAC,EAAS,EAAC,UAAiB,EAAC,IAAW,EAAC,QAAY,EAAC,OAAc;IACzF,IAAI,MAAM,GAAG,EAAE,CAAC;IAChB,IAAI,IAAI,GAAG,QAAQ,CAAC,IAAI,CAAC;IAEzB,IAAG,OAAO,IAAI,MAAM,IAAI,CAAC,IAAI,IAAI,QAAQ,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,OAAO,CAAC,EAAE;QAC7E,IAAG,IAAI,IAAI,OAAO,EAAE;YAClB,IAAG,QAAQ,CAAC,KAAK,CAAC,IAAI,IAAI,QAAQ,IAAI,QAAQ,CAAC,KAAK,CAAC,MAAM,CAAC,IAAI,IAAI,EAAE;gBACpE,MAAM,GAAG,eAAa,EAAE,QAAK,CAAC;aAC/B;iBACI;gBACH,IAAG,IAAI,IAAI,UAAU;oBACnB,MAAM,GAAG,eAAa,EAAE,sBAAiB,EAAE,QAAK,CAAC;;oBAEjD,MAAM,GAAG,eAAa,EAAE,eAAU,UAAU,SAAI,EAAE,QAAK,CAAC;aAC3D;SACF;aACI;YACH,MAAM,GAAG,eAAa,EAAE,QAAK,CAAC;SAC/B;KACF;SACI;QACH,IAAG,IAAI,IAAI,UAAU;YACnB,MAAM,GAAG,eAAa,EAAE,sBAAiB,EAAE,QAAK,CAAC;;YAEjD,MAAM,GAAG,eAAa,EAAE,eAAU,UAAU,SAAI,EAAE,QAAK,CAAC;KAC3D;IACD,OAAO,MAAM,CAAC;AAChB,CAAC;AAED,SAAS,cAAc,CAAC,EAAS,EAAC,UAAiB,EAAC,IAAW,EAAC,QAAY,EAAC,OAAc;IACzF,IAAI,MAAM,GAAG,EAAE,CAAC;IAChB,IAAI,IAAI,GAAG,QAAQ,CAAC,IAAI,CAAC;IAEzB,IAAG,OAAO,IAAI,MAAM,IAAI,CAAC,IAAI,IAAI,QAAQ,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,OAAO,CAAC,EAAE;QAC7E,IAAG,IAAI,IAAI,OAAO,EAAE;YAClB,IAAG,QAAQ,CAAC,KAAK,CAAC,IAAI,IAAI,QAAQ,IAAI,QAAQ,CAAC,KAAK,CAAC,MAAM,CAAC,IAAI,IAAI,EAAE;gBACpE,IAAG,IAAI,IAAI,UAAU;oBACnB,MAAM,GAAG,iBAAe,EAAE,8BAAyB,EAAE,8CAAuC,EAAE,qBAAgB,EAAE,uBAAoB,CAAC;;oBAErI,MAAM,GAAI,iBAAe,EAAE,uBAAkB,UAAU,SAAI,EAAE,uCAAgC,UAAU,SAAI,EAAE,cAAS,UAAU,SAAI,EAAE,uBAAoB,CAAC;aAC9J;SACF;aACI;YACH,IAAG,IAAI,IAAI,UAAU;gBACnB,MAAM,GAAG,iBAAe,EAAE,8BAAyB,EAAE,8CAAuC,EAAE,qBAAgB,EAAE,uBAAoB,CAAC;;gBAErI,MAAM,GAAI,iBAAe,EAAE,uBAAkB,UAAU,SAAI,EAAE,uCAAgC,UAAU,SAAI,EAAE,cAAS,UAAU,SAAI,EAAE,uBAAoB,CAAC;SAC9J;KACF;IACD,OAAO,MAAM,CAAC;AAChB,CAAC;AAED,SAAS,cAAc,CAAC,EAAS,EAAC,UAAiB,EAAC,IAAW,EAAC,QAAY,EAAC,OAAc;IACzF,IAAI,MAAM,GAAG,EAAE,CAAC;IAChB,IAAI,IAAI,GAAG,QAAQ,CAAC,IAAI,CAAC;IAEzB,IAAG,IAAI,IAAI,OAAO,EAAE;QAClB,MAAM,IAAI,cAAY,EAAE,kBAAe,CAAC;QACxC,MAAM,IAAI,+BAA6B,EAAE,WAAM,EAAE,YAAO,EAAE,SAAM,CAAC;QACjE,MAAM,IAAI,WAAW,CAAC;KACvB;IACD,OAAO,MAAM,CAAC;AAChB,CAAC;AAED,SAAS,4BAA4B,CAAC,UAAiB,EAAC,MAAY,EAAC,YAAmB,EAAC,OAAgB;IACvG,IAAI,MAAM,GAAG,EAAE,CAAC;IAEhB,KAAI,IAAI,CAAC,GAAG,CAAC,EAAC,CAAC,GAAG,MAAM,CAAC,MAAM,EAAC,CAAC,EAAE;QACjC,MAAM,IAAI,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,EAAE,EAAC,UAAU,EAAC,MAAM,CAAC,CAAC,CAAC,CAAC,IAAI,EAAC,MAAM,CAAC,CAAC,CAAC,CAAC,IAAI,EAAC,MAAM,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;IAClG,OAAO,MAAM,CAAC;AAChB,CAAC;AAED,SAAS,4BAA4B,CAAC,UAAiB,EAAC,MAAY,EAAC,YAAmB,EAAC,OAAgB,EAAC,aAAwB;IAChI,IAAI,MAAM,GAAG,EAAE,CAAC;IAEhB,KAAI,IAAI,CAAC,GAAG,CAAC,EAAC,CAAC,GAAG,MAAM,CAAC,MAAM,EAAC,CAAC,EAAE,EAAE;QACnC,IAAG,MAAM,CAAC,CAAC,CAAC,CAAC,IAAI,IAAI,UAAU,EAAE;YAC/B,MAAM,IAAI,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,EAAE,EAAC,UAAU,EAAC,MAAM,CAAC,CAAC,CAAC,CAAC,IAAI,EAAC,MAAM,CAAC,CAAC,CAAC,CAAC,IAAI,EAAC,MAAM,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;YAChG,IAAG,aAAa,IAAI,IAAI;gBAAE,aAAa,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC;SAC5D;aACI;YACH,IAAG,MAAM,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,IAAI,QAAQ,EAAE;gBAClC,IAAI,UAAU,GAAG,MAAM,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,UAAU,CAAC;gBAC3C,IAAI,OAAO,GAAG,EAAE,CAAC;gBAEjB,KAAI,IAAI,YAAY,IAAI,UAAU,EAAE;oBAClC,MAAM,IAAI,OAAO,CAAC,YAAY,EAAC,UAAU,EAAC,SAAS,EAAC,UAAU,CAAC,YAAY,CAAC,EAAC,UAAU,CAAC,YAAY,CAAC,CAAC,OAAO,CAAC,CAAC;oBAC/G,OAAO,CAAC,IAAI,CAAC,YAAY,CAAC,CAAC;iBAC5B;gBACD,IAAG,aAAa,IAAI,IAAI;oBAAE,aAAa,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;aACvD;iBACI;gBACH,MAAM,IAAI,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,EAAE,EAAC,UAAU,EAAC,MAAM,CAAC,CAAC,CAAC,CAAC,IAAI,EAAC,MAAM,CAAC,CAAC,CAAC,CAAC,IAAI,EAAC,MAAM,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;gBAChG,IAAG,aAAa,IAAI,IAAI;oBAAE,aAAa,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC;aAC5D;SACF;KACF;IACD,OAAO,MAAM,CAAC;AAChB,CAAC;AAED,SAAS,qBAAqB,CAAC,UAAiB,EAAC,MAAY,EAAC,YAAmB;IAC/E,IAAI,MAAM,GAAG,EAAE,CAAC;IAChB,IAAI,YAAY,GAAG,4BAA4B,CAAC,UAAU,EAAC,MAAM,EAAC,YAAY,EAAC,cAAc,CAAC,CAAC;IAC/F,IAAI,YAAY,GAAG,4BAA4B,CAAC,UAAU,EAAC,MAAM,EAAC,YAAY,EAAC,cAAc,CAAC,CAAC;IAC/F,IAAI,YAAY,GAAG,4BAA4B,CAAC,UAAU,EAAC,MAAM,EAAC,YAAY,EAAC,cAAc,CAAC,CAAC;IAE/F,IAAG,YAAY,IAAI,EAAE;QAAE,MAAM,IAAI,KAAG,YAAc,CAAC;IACnD,IAAG,YAAY,IAAI,EAAE;QAAE,MAAM,IAAI,OAAK,YAAY,OAAI,CAAC;IACvD,IAAG,YAAY,IAAI,EAAE;QAAE,MAAM,IAAI,OAAK,YAAY,OAAI,CAAC;IACvD,MAAM,IAAI,0CAAwC,YAAY,MAAG,CAAC;IAClE,KAAI,IAAI,CAAC,GAAG,CAAC,EAAC,CAAC,GAAG,MAAM,CAAC,MAAM,EAAC,CAAC,EAAE,EAAE;QACnC,IAAG,CAAC,IAAI,CAAC;YAAE,MAAM,IAAI,GAAG,CAAC;QACzB,MAAM,IAAI,KAAG,MAAM,CAAC,CAAC,CAAC,CAAC,EAAI,CAAC;KAC7B;IACD,MAAM,IAAI,QAAQ,CAAC;IACnB,OAAO,MAAM,CAAC;AAChB,CAAC;AAED,SAAS,qBAAqB,CAAC,UAAiB,EAAC,MAAY,EAAC,YAAmB;IAC/E,IAAI,MAAM,GAAG,EAAE,CAAC;IAChB,IAAI,aAAa,GAAG,EAAE,CAAC;IACvB,IAAI,YAAY,GAAG,4BAA4B,CAAC,UAAU,EAAC,MAAM,EAAC,YAAY,EAAC,cAAc,EAAC,aAAa,CAAC,CAAC;IAC7G,IAAI,YAAY,GAAG,4BAA4B,CAAC,UAAU,EAAC,MAAM,EAAC,YAAY,EAAC,cAAc,EAAC,IAAI,CAAC,CAAC;IACpG,IAAI,YAAY,GAAG,4BAA4B,CAAC,UAAU,EAAC,MAAM,EAAC,YAAY,EAAC,cAAc,EAAC,IAAI,CAAC,CAAC;IACpG,IAAI,IAAI,CAAC;IAET,IAAG,YAAY,IAAI,EAAE;QAAE,MAAM,IAAI,KAAG,YAAc,CAAC;IACnD,IAAG,YAAY,IAAI,EAAE;QAAE,MAAM,IAAI,OAAK,YAAY,OAAI,CAAC;IACvD,IAAG,YAAY,IAAI,EAAE;QAAE,MAAM,IAAI,OAAK,YAAY,OAAI,CAAC;IACvD,KAAI,IAAI,CAAC,GAAG,CAAC,EAAC,CAAC,GAAG,aAAa,CAAC,MAAM,EAAC,CAAC,EAAE,EAAE;QAC1C,IAAG,OAAO,aAAa,CAAC,CAAC,CAAC,IAAI,QAAQ,EAAE;YACtC,IAAG,IAAI,IAAI,IAAI;gBAAE,IAAI,GAAG,CAAC,CAAC;YAC1B,MAAM,IAAI,oBAAkB,IAAI,EAAE,aAAU,CAAC;SAC9C;KACF;IACD,IAAG,IAAI,IAAI,IAAI,EAAE;QACf,IAAI,GAAG,CAAC,CAAC;QAET,KAAI,IAAI,CAAC,GAAG,CAAC,EAAC,CAAC,GAAG,aAAa,CAAC,MAAM,EAAC,CAAC,EAAE,EAAE;YAC1C,IAAG,OAAO,aAAa,CAAC,CAAC,CAAC,IAAI,QAAQ,EAAE;gBACtC,KAAI,IAAI,CAAC,GAAG,CAAC,EAAC,CAAC,GAAG,aAAa,CAAC,CAAC,CAAC,CAAC,MAAM,EAAC,CAAC,EAAE,EAAE;oBAC7C,MAAM,IAAI,cAAY,aAAa,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,uBAAkB,IAAI,SAAI,aAAa,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,WAAM,aAAa,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,QAAK,CAAC;iBACtH;gBACD,IAAI,EAAE,CAAC;aACR;SACF;KACF;IACD,IAAG,IAAI,IAAI,IAAI;QAAE,IAAI,GAAG,CAAC,CAAC;IAC1B,MAAM,IAAI,0CAAwC,YAAY,MAAG,CAAC;IAClE,KAAI,IAAI,CAAC,GAAG,CAAC,EAAC,CAAC,GAAG,aAAa,CAAC,MAAM,EAAC,CAAC,EAAE,EAAE;QAC1C,IAAG,CAAC,IAAI,CAAC;YAAE,MAAM,IAAI,GAAG,CAAC;QACzB,IAAG,OAAO,aAAa,CAAC,CAAC,CAAC,IAAI,QAAQ;YAAE,MAAM,IAAI,KAAG,aAAa,CAAC,CAAC,CAAG,CAAC;;YACnE,MAAM,IAAI,UAAQ,IAAI,EAAI,CAAC;KACjC;IACD,MAAM,IAAI,QAAQ,CAAC;IACnB,OAAO,MAAM,CAAC;AAChB,CAAC;AAED;;;;;;;;;;;;;;;;GAgBG;AACH,SAAgB,gBAAgB,CAAC,SAA6B,EAAC,MAAa,EAAC,WAAwB,EAAC,OAAe,EAAC,UAAkC;IACtJ,IAAI,MAAM,GAAG,qBAAmB,CAAC;IACjC,IAAI,YAAY,CAAC;IACjB,IAAI,eAAe,GAAG,EAAE,CAAC;IAEzB,IAAG,OAAO,IAAI,IAAI;QAAE,YAAY,GAAG,IAAI,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC,OAAO,CAAC,KAAK,EAAE,GAAG,CAAC,CAAC;IAE7E,MAAM,IAAI,uCAAuC,CAAC;IAClD,MAAM,IAAI,kCAAkC,CAAC;IAC7C,MAAM,IAAI,0DAA0D,CAAC;IACrE,MAAM,IAAI,0DAA0D,CAAC;IACrE,MAAM,IAAI,8CAA8C,CAAC;IACzD,MAAM,IAAI,kDAAkD,CAAC;IAE7D,oEAAoE;IACpE,qEAAqE;IACrE,KAAI,IAAI,CAAC,GAAG,CAAC,EAAC,CAAC,GAAG,WAAW,CAAC,MAAM,EAAC,CAAC,EAAE,EAAE;QACxC,IAAI,QAAQ,GAAG,IAAI,CAAC,OAAO,CAAC,WAAW,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,OAAO,CAAC,KAAK,EAAE,GAAG,CAAC,CAAC;QAEzE,IAAG,OAAO,IAAI,IAAI,EAAE;YAClB,QAAQ,GAAG,QAAQ,CAAC,OAAO,CAAC,YAAY,GAAG,GAAG,EAAC,EAAE,CAAC,CAAC;YACnD,QAAQ,GAAG,QAAQ,CAAC,OAAO,CAAC,IAAI,CAAC,OAAO,CAAC,QAAQ,CAAC,EAAC,EAAE,CAAC,CAAC;YACvD,MAAM,IAAI,WAAS,WAAW,CAAC,CAAC,CAAC,CAAC,QAAQ,4BAAuB,QAAQ,UAAO,CAAC;SAClF;;YACI,MAAM,IAAI,WAAS,WAAW,CAAC,CAAC,CAAC,CAAC,QAAQ,4BAAuB,IAAI,CAAC,QAAQ,CAAC,QAAQ,CAAC,UAAO,CAAC;QACrG,eAAe,CAAC,WAAW,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,GAAG,WAAW,CAAC,CAAC,CAAC,CAAC;KAC3D;IAED,0EAA0E;IAC1E,2EAA2E;IAC3E,2EAA2E;IAC3E,+BAA+B;IAC/B,MAAM,IAAI,oCAAoC,CAAC;IAC/C,MAAM,IAAI,2DAA2D,CAAC;IACtE,MAAM,IAAI,mEAAmE,CAAC;IAC9E,MAAM,IAAI,uCAAuC,CAAC;IAElD,IAAI,UAAU,GAAG,8BAAmB,CAAC,MAAM,CAAC,aAAa,EAAC,SAAS,CAAC,CAAC;IAErE,KAAI,IAAI,CAAC,GAAG,CAAC,EAAC,CAAC,GAAG,WAAW,CAAC,MAAM,EAAC,CAAC,EAAE,EAAE;QACxC,IAAI,MAAI,GAAG,GAAG,GAAG,8BAAmB,CAAC,WAAW,CAAC,CAAC,CAAC,CAAC,aAAa,EAAC,SAAS,CAAC,CAAC;QAE7E,IAAG,UAAU,IAAI,EAAE;YAAE,MAAI,GAAG,MAAI,UAAU,GAAG,MAAM,CAAC;QACpD,MAAM,IAAI,uBAAqB,MAAI,WAAM,WAAW,CAAC,CAAC,CAAC,CAAC,QAAQ,+BAA4B,CAAC;KAC9F;IAED,KAAI,IAAI,CAAC,GAAG,CAAC,EAAC,CAAC,GAAG,SAAS,CAAC,MAAM,EAAC,CAAC,EAAE,EAAE;QACtC,IAAI,KAAK,GAAG,SAAS,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC;QAC9B,IAAI,YAAY,GAAG,SAAS,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC;QACrC,IAAI,MAAI,GAAG,YAAY,CAAC;QACxB,IAAI,UAAU,GAAG,OAAO,CAAC;QAEzB,IAAG,SAAS,CAAC,CAAC,CAAC,CAAC,aAAa,CAAC,MAAM,IAAI,CAAC;YAAE,MAAI,GAAG,SAAS,CAAC,CAAC,CAAC,CAAC,aAAa,CAAC,CAAC,CAAC,CAAC;QAEhF,IAAI,yBAAyB,GAAG,wBAAa,CAAC,MAAI,CAAC,CAAC;QACpD,IAAI,YAAY,GAAG,8BAAmB,CAAC,yBAAyB,EAAC,SAAS,CAAC,CAAC;QAE5E,sFAAsF;QACtF,2FAA2F;QAC3F,2EAA2E;QAC3E,kDAAkD;QAClD,MAAM,IAAI,IAAI,CAAC;QACf,MAAM,IAAI,8BAA4B,SAAS,CAAC,CAAC,CAAC,CAAC,QAAQ,WAAM,KAAK,WAAM,YAAY,kCAA+B,CAAC;QACxH,MAAM,IAAI,aAAa,CAAC;QACxB,IAAG,KAAK,IAAI,KAAK,EAAE;YACjB,MAAM,IAAI,qFAAmF,CAAC;YAC9F,UAAU,GAAG,MAAM,CAAC;SACrB;QACD,MAAM,IAAI,yFAAyF,CAAA;QACnG,MAAM,IAAI,kCAAgC,SAAS,CAAC,CAAC,CAAC,CAAC,QAAQ,kCAA+B,CAAA;QAE9F,IAAI,MAAM,GAAG,EAAE,CAAC;QAChB,IAAI,WAAW,GAAG,CAAC,CAAC;QAEpB,4CAA4C;QAC5C,KAAI,IAAI,CAAC,GAAG,CAAC,EAAC,CAAC,GAAG,SAAS,CAAC,CAAC,CAAC,CAAC,gBAAgB,CAAC,MAAM,EAAC,CAAC,EAAE,EAAE;YAC1D,IAAI,IAAI,GAAG,SAAS,CAAC,CAAC,CAAC,CAAC,gBAAgB,CAAC,CAAC,CAAC,CAAC;YAC5C,IAAI,KAAK,GAAG,mCAAwB,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC,gBAAgB,CAAC,CAAC,CAAC,CAAC,CAAC;YACvE,IAAI,QAAQ,GAAG,mBAAU,CAAC,IAAI,CAAC,IAAI,EAAC,KAAK,EAAC,EAAE,UAAU,EAAC,IAAI,EAAE,uBAAuB,EAAC,IAAI,EAAE,eAAe,EAAC,SAAS,EAAE,OAAO,EAAC,eAAe,EAAE,CAAC,CAAA;YAEhJ,IAAG,IAAI,CAAC,UAAU,IAAI,IAAI,EAAE;gBAC1B,IAAI,cAAc,GAAG,KAAK,CAAC;gBAE3B,KAAI,IAAI,aAAa,IAAI,IAAI,CAAC,UAAU,EAAE;oBACxC,IAAG,aAAa,IAAI,UAAU,EAAE;wBAC9B,IAAI,aAAa,GAAG,IAAI,CAAC,UAAU,CAAC,aAAa,CAAC,CAAC;wBAEnD,IAAG,aAAa,CAAC,MAAM;4BAAE,MAAM,CAAC,IAAI,CAAC,EAAE,EAAE,EAAC,aAAa,CAAC,CAAC,CAAC,EAAE,IAAI,EAAC,UAAU,EAAE,CAAC,CAAC;;4BAC1E,MAAM,CAAC,IAAI,CAAC,EAAE,EAAE,EAAC,IAAI,CAAC,EAAE,EAAE,IAAI,EAAE,UAAU,EAAE,IAAI,EAAC,QAAQ,EAAE,CAAC,CAAC;wBAClE,WAAW,IAAI,CAAC,CAAC;qBAClB;iBACF;gBACD,IAAG,CAAC,cAAc,EAAE;oBAClB,IAAG,qBAAU,CAAC,IAAI,CAAC,EAAE,EAAC,MAAM,EAAC,eAAe,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,EAAC,yBAAyB,CAAC,EAAE;wBAC9F,MAAM,CAAC,IAAI,CAAC,EAAE,EAAE,EAAC,IAAI,CAAC,EAAE,EAAE,IAAI,EAAE,UAAU,EAAE,IAAI,EAAC,QAAQ,EAAE,CAAC,CAAC;wBAC7D,WAAW,IAAI,CAAC,CAAC;qBAClB;;wBACI,MAAM,CAAC,IAAI,CAAC,EAAE,EAAE,EAAC,IAAI,CAAC,EAAE,EAAE,IAAI,EAAE,SAAS,EAAE,IAAI,EAAC,QAAQ,EAAE,CAAC,CAAC;iBAClE;aACF;iBACI,IAAG,qBAAU,CAAC,IAAI,CAAC,EAAE,EAAC,MAAM,EAAC,eAAe,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,EAAC,yBAAyB,CAAC,EAAE;gBACnG,MAAM,CAAC,IAAI,CAAC,EAAE,EAAE,EAAC,IAAI,CAAC,EAAE,EAAE,IAAI,EAAE,UAAU,EAAE,IAAI,EAAC,QAAQ,EAAE,CAAC,CAAC;gBAC7D,WAAW,IAAI,CAAC,CAAC;aAClB;;gBAEC,MAAM,CAAC,IAAI,CAAC,EAAE,EAAE,EAAC,IAAI,CAAC,EAAE,EAAE,IAAI,EAAE,SAAS,EAAE,IAAI,EAAC,QAAQ,EAAE,CAAC,CAAC;SAC/D;QACD,IAAG,MAAM,CAAC,MAAM,GAAG,WAAW,GAAG,CAAC;YAAE,MAAM,IAAI,qBAAqB,CAAC,UAAU,EAAC,MAAM,EAAC,YAAY,CAAC,CAAC;;YAC/F,MAAM,IAAI,qBAAqB,CAAC,UAAU,EAAC,MAAM,EAAC,YAAY,CAAC,CAAC;QACrE,MAAM,IAAI,+CAA+C,CAAC;QAC1D,MAAM,IAAI,SAAS,CAAC;QACpB,MAAM,IAAI,oDAAoD,CAAC;QAC/D,MAAM,IAAI,SAAS,CAAC;KACrB;IAED,IAAI,OAAO,GAAG,OAAO,CAAC;IACtB,IAAI,SAAS,GAAG,QAAQ,CAAC;IACzB,IAAI,UAAU,GAAG,aAAa,CAAC;IAC/B,IAAI,WAAW,GAAG,0BAA0B,CAAC;IAE7C,IAAG,UAAU,IAAI,EAAE,EAAE;QACnB,OAAO,GAAG,MAAI,UAAU,GAAG,OAAS,CAAC;QACrC,SAAS,GAAG,MAAI,UAAU,GAAG,SAAW,CAAC;QACzC,UAAU,GAAG,MAAI,UAAU,GAAG,UAAY,CAAC;QAC3C,WAAW,GAAG,MAAI,UAAU,GAAG,WAAa,CAAC;KAC9C;IACD,MAAM,IAAI,oCAAkC,OAAO,2DAAwD,CAAC;IAC5G,MAAM,IAAI,oCAAkC,SAAS,kCAA+B,CAAC;IACrF,MAAM,IAAI,qDAAqD,CAAC;IAChE,MAAM,IAAI,SAAS,CAAC;IACpB,MAAM,IAAI,oCAAkC,UAAU,8CAA2C,CAAC;IAClG,MAAM,IAAI,qCAAqC,CAAC;IAChD,MAAM,IAAI,KAAK,CAAC;IAEhB,UAAU,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC;IACzB,OAAO,WAAW,CAAC;AACrB,CAAC;AAxID,4CAwIC"} |
| export {}; |
| "use strict"; | ||
| Object.defineProperty(exports, "__esModule", { value: true }); | ||
| var ts = require("typescript"); | ||
| var main_1 = require("./main"); | ||
| module.exports = { | ||
| generate: function (env, checkFile, swaggerFile, redocFile, routesFile) { | ||
| var src = env.programArgs.slice(2); | ||
| if (src.length == 0) | ||
| src = env.tsInclude; | ||
| main_1.generate(src, { target: ts.ScriptTarget.ES5, module: ts.ModuleKind.CommonJS, experimentalDecorators: true }, env.packageName, env.srcRoot, checkFile, swaggerFile, redocFile, routesFile, env.debug); | ||
| } | ||
| }; | ||
| //# sourceMappingURL=index.js.map |
| {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/analyzer/index.ts"],"names":[],"mappings":";;AAAA,+BAAiC;AAEjC,+BAAkC;AAElC,MAAM,CAAC,OAAO,GAAG;IACf,QAAQ,EAAC,UAAS,GAAG,EAAC,SAAS,EAAC,WAAW,EAAC,SAAS,EAAC,UAAU;QAC9D,IAAI,GAAG,GAAG,GAAG,CAAC,WAAW,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;QAEnC,IAAG,GAAG,CAAC,MAAM,IAAI,CAAC;YAAE,GAAG,GAAG,GAAG,CAAC,SAAS,CAAC;QACxC,eAAQ,CACN,GAAG,EACH,EAAE,MAAM,EAAC,EAAE,CAAC,YAAY,CAAC,GAAG,EAAE,MAAM,EAAE,EAAE,CAAC,UAAU,CAAC,QAAQ,EAAE,sBAAsB,EAAC,IAAI,EAAE,EAC3F,GAAG,CAAC,WAAW,EACf,GAAG,CAAC,OAAO,EACX,SAAS,EACT,WAAW,EACX,SAAS,EACT,UAAU,EACV,GAAG,CAAC,KAAK,CACV,CAAC;IACJ,CAAC;CACF,CAAA"} |
| /// <reference types="node" /> | ||
| import * as ts from "typescript"; | ||
| /** | ||
| * Main entry point for static analysis of a list of typescript files. Given the list | ||
| * of files, invokes the typescript parser and typechecker APIs, and then using the | ||
| * resulting AST from that pass, generate file appropriate for the following objectives | ||
| * | ||
| * 1. Creation of runtime checking routines. Construct a JSON schema for each appropriatedly | ||
| * annotated method and a function that will apply a schema check to that argument list. | ||
| * Place these functions in __check.js | ||
| * | ||
| * 2. Assembly of express type routes. Generate a file __routes that will create appropriate | ||
| * objects and connect them to express using one or more express Router classes. Apply | ||
| * runtime checking in 1. as part of that route. | ||
| * | ||
| * 3. Generate analogous Swagger doc. Create a swagger document that corresponds to the | ||
| * routes created by 2. | ||
| * | ||
| * @param {string[]} patterns list of source file patters to analyze. | ||
| * @param {ts.CompilerOptions} options options controlling behavior of the typescript parser | ||
| * and type checker | ||
| * @param {string} packageName derived from package.json of the input project. Use for top level naming. | ||
| * @param {string} srcRoot root of the source directory (derived form tsconfig.json by default). | ||
| * @param {NodeJS.ReadWriteStream} checkFile reference to the generated file __check.js | ||
| * @param {NodeJS.ReadWriteStream} swaggerFile reference to the generated file docs/swagger.json | ||
| * @param {NodeJS.ReadWriteStream} routesFile reference to the generated file __routes.js | ||
| */ | ||
| export declare function generate(patterns: string[], options: ts.CompilerOptions, packageName: string, srcRoot: string, checkFile: NodeJS.ReadWriteStream, swaggerFile: NodeJS.ReadWriteStream, redocFile: NodeJS.ReadWriteStream, routesFile: NodeJS.ReadWriteStream, debugMode: boolean): void; |
| "use strict"; | ||
| Object.defineProperty(exports, "__esModule", { value: true }); | ||
| var ts = require("typescript"); | ||
| var glob = require("glob"); | ||
| var doctrine = require("doctrine"); | ||
| var tsany = ts; | ||
| var symtab_1 = require("./symtab"); | ||
| var traverse_1 = require("./traverse"); | ||
| var swagger_1 = require("./swagger"); | ||
| var express_routes_1 = require("./express_routes"); | ||
| var redoc_1 = require("./redoc"); | ||
| /** | ||
| * Generate source given the definitions inicated by annotations in the source code. These | ||
| * sources include __router.js __check.js and docs/swagger.json. By default these files will | ||
| * be created in the destination directory as defined by the tsconfig file. | ||
| * | ||
| * @param {DecoratedFunction[]} items array of endpoint methods that correspond to express routes | ||
| * and swagger paths. | ||
| * @param {string} packageName name of the package (from package.json). This will be converted to | ||
| * the swagger title. | ||
| * @param {string} srcRoot location of the source code (from tsconfig.json). | ||
| * @param {NodeJS.ReadWriteStream} checkFile reference to the file __check.js | ||
| * @param {NodeJS.ReadWriteStream} swaggerFile reference to the file docs/swagger.json | ||
| * @param {NodeJS.ReadWriteStream} routesFiles reference to the file __routes.js | ||
| */ | ||
| function genSources(items, packageName, srcRoot, checkFile, swaggerFile, redocFile, routesFile) { | ||
| var controllers = traverse_1.symtabToControllerDefinitions(); | ||
| var routers = traverse_1.symtabToRouterDefinitions(); | ||
| var swaggerDefinitions = {}; | ||
| var contents_part1 = ''; | ||
| var contents_part2 = ''; | ||
| var contents_part3 = ''; | ||
| if (routers.length == 0) | ||
| throw ("No Router Definitions Found"); | ||
| if (routers.length > 1) | ||
| throw ("Multiple Router Definitions Found"); | ||
| contents_part1 += "const Ajv = require('ajv');\n"; | ||
| contents_part1 += "\nlet ajv = new Ajv({ coerceTypes: true });\n\n"; | ||
| contents_part1 += "ajv.addKeyword('toDate', {\n"; | ||
| contents_part1 += " modifying: true,\n"; | ||
| contents_part1 += " schema: false, \n"; | ||
| contents_part1 += " valid: true, \n"; | ||
| contents_part1 += " validate: function(data,dataPath,parentData,parentDataProperty) {\n"; | ||
| contents_part1 += " if(typeof data == \"string\" && parentData != null) parentData[parentDataProperty] = new Date(data);\n"; | ||
| contents_part1 += " }\n"; | ||
| contents_part1 += "});\n\n"; | ||
| contents_part1 += "ajv.addKeyword('precision', {\n"; | ||
| contents_part1 += " schema: true,\n"; | ||
| contents_part1 += " validate: function(schema,data) {\n"; | ||
| contents_part1 += " let x = data - Math.floor(data);\n"; | ||
| contents_part1 += " let m = Math.pow(10,schema);\n"; | ||
| contents_part1 += " let y = x*m;\n"; | ||
| contents_part1 += " \n"; | ||
| contents_part1 += " return y == Math.floor(y);\n"; | ||
| contents_part1 += " }\n"; | ||
| contents_part1 += "});\n"; | ||
| contents_part3 += "\nfunction compositeWithDefinitions(schema) { schema.definitions = definitions; return schema; }\n"; | ||
| contents_part3 += "function validate(schema) { try { return ajv.compile(compositeWithDefinitions(schema)); } catch(e) { throw new Error(e); } }\n"; | ||
| for (var i = 0; i < items.length; i++) | ||
| traverse_1.findRelevant(items[i]); | ||
| var definitions1 = traverse_1.symtabToSchemaDefinitions("check", "#/definitions"); | ||
| var definitions2 = traverse_1.symtabToSchemaDefinitions("swagger", "#/components/schemas", { firstclassIntermediates: true }); | ||
| var synthesizedTypes = {}; | ||
| for (var i = 0; i < items.length; i++) { | ||
| var x = traverse_1.parameterListToJSON(items[i]); | ||
| if (x.parameterNames) | ||
| x.schema.required = x.required; | ||
| contents_part3 += traverse_1.genMethodEntry(x.classRef, x.method, x.parameterNames, x.schema, x.passthrough); | ||
| } | ||
| contents_part2 += "\n\nlet definitions = " + JSON.stringify(definitions1, null, 2) + "\n"; | ||
| checkFile.write(contents_part1); | ||
| checkFile.write(contents_part2); | ||
| checkFile.write(contents_part3); | ||
| swagger_1.genSwaggerPreamble(swaggerDefinitions, packageName, routers[0], controllers); | ||
| swagger_1.genSwaggerRootTags(swaggerDefinitions, routers[0], controllers); | ||
| swagger_1.genSwaggerRoutes(swaggerDefinitions, synthesizedTypes, routers[0], controllers); | ||
| for (var synthesizedTypename in synthesizedTypes) | ||
| definitions2[synthesizedTypename] = synthesizedTypes[synthesizedTypename]; | ||
| swaggerDefinitions.components = { schemas: definitions2 }; | ||
| swaggerFile.write(JSON.stringify(swaggerDefinitions, null, 2) + "\n"); | ||
| var swaggerPath = express_routes_1.genExpressRoutes(items, routers[0], controllers, srcRoot, routesFile); | ||
| redoc_1.genRedoc(swaggerPath, redocFile); | ||
| } | ||
| /** | ||
| * Use glob to contruct the list of input files to scan given a list of glob-type | ||
| * patterns. | ||
| * | ||
| * @param {string[]} patterns array of glob-patterns describing the list of files. | ||
| */ | ||
| function getFilenames(patterns) { | ||
| var fa = []; | ||
| for (var i = 0; i < patterns.length; i++) { | ||
| var filenames = glob.sync(patterns[i]); | ||
| for (var j = 0; j < filenames.length; j++) | ||
| fa.push(filenames[j]); | ||
| } | ||
| return fa; | ||
| } | ||
| /** | ||
| * Extract arguments of relevant decorators for static analysis. Some arguments | ||
| * to decorators are needed at compile time for file generation (e.g. @controller | ||
| * path). This function finds these values for use later on in the 2nd pass. | ||
| * Literal values can be used, but arguements only usable at runtime are ignored. | ||
| * | ||
| * @param {ts.CallExpression} cexpr AST subtree rooted with decorator type node. | ||
| */ | ||
| function genArgumentList(cexpr) { | ||
| var argList = []; | ||
| for (var _i = 0, _a = cexpr.arguments; _i < _a.length; _i++) { | ||
| var arg = _a[_i]; | ||
| switch (arg.kind) { | ||
| case ts.SyntaxKind.StringLiteral: | ||
| { | ||
| var text = tsany.getTextOfNode(arg); | ||
| var s = text.replace(/^["']|["']$/g, ''); | ||
| argList.push(s); | ||
| } | ||
| break; | ||
| case ts.SyntaxKind.NumericLiteral: | ||
| { | ||
| argList.push(parseFloat(tsany.getTextOfNode(arg))); | ||
| } | ||
| break; | ||
| case ts.SyntaxKind.Identifier: | ||
| { | ||
| argList.push(tsany.getTextOfNode(arg)); | ||
| } | ||
| break; | ||
| case ts.SyntaxKind.FunctionExpression: | ||
| console.log(" ignoring function in decorator argument list"); | ||
| break; | ||
| default: throw ("unknown type (" + arg.kind + ") in decorator argument list"); | ||
| } | ||
| } | ||
| return argList; | ||
| } | ||
| /** | ||
| * Main entry point for static analysis of a list of typescript files. Given the list | ||
| * of files, invokes the typescript parser and typechecker APIs, and then using the | ||
| * resulting AST from that pass, generate file appropriate for the following objectives | ||
| * | ||
| * 1. Creation of runtime checking routines. Construct a JSON schema for each appropriatedly | ||
| * annotated method and a function that will apply a schema check to that argument list. | ||
| * Place these functions in __check.js | ||
| * | ||
| * 2. Assembly of express type routes. Generate a file __routes that will create appropriate | ||
| * objects and connect them to express using one or more express Router classes. Apply | ||
| * runtime checking in 1. as part of that route. | ||
| * | ||
| * 3. Generate analogous Swagger doc. Create a swagger document that corresponds to the | ||
| * routes created by 2. | ||
| * | ||
| * @param {string[]} patterns list of source file patters to analyze. | ||
| * @param {ts.CompilerOptions} options options controlling behavior of the typescript parser | ||
| * and type checker | ||
| * @param {string} packageName derived from package.json of the input project. Use for top level naming. | ||
| * @param {string} srcRoot root of the source directory (derived form tsconfig.json by default). | ||
| * @param {NodeJS.ReadWriteStream} checkFile reference to the generated file __check.js | ||
| * @param {NodeJS.ReadWriteStream} swaggerFile reference to the generated file docs/swagger.json | ||
| * @param {NodeJS.ReadWriteStream} routesFile reference to the generated file __routes.js | ||
| */ | ||
| function generate(patterns, options, packageName, srcRoot, checkFile, swaggerFile, redocFile, routesFile, debugMode) { | ||
| var fa = getFilenames(patterns); | ||
| var program = ts.createProgram(fa, options); | ||
| var endpoints = []; | ||
| var x = {}; | ||
| var defComp = []; | ||
| symtab_1.setChecker(program); | ||
| function isNodeExported(node) { | ||
| return (node.flags & ts.ModifierFlags.Export) !== 0 || (node.parent && node.parent.kind === ts.SyntaxKind.SourceFile); | ||
| } | ||
| // Recurse over all of the decorated functions, classes, etc and extract | ||
| // relevant information and place that in a symbol table for later processing. | ||
| function visitDecorator(node) { | ||
| if (ts.isDecorator(node)) { | ||
| var expr = node.expression; | ||
| var dsym = symtab_1.checker.getSymbolAtLocation(expr.getFirstToken()); | ||
| var dname = dsym.getName(); | ||
| var parentIndex = "unknown"; | ||
| var methodParameters = []; | ||
| var doRuntimeCheck = false; | ||
| var doDecoratedClass = false; | ||
| var functionName = void 0; | ||
| var returnType = void 0; | ||
| var comment = void 0; | ||
| switch (node.parent.kind) { | ||
| case ts.SyntaxKind.FunctionDeclaration: | ||
| { | ||
| var parent_1 = node.parent; | ||
| if (parent_1.name != null) { | ||
| var symbol = symtab_1.checker.getSymbolAtLocation(parent_1.name); | ||
| comment = ts.displayPartsToString(symbol.getDocumentationComment(symtab_1.checker)); | ||
| } | ||
| returnType = parent_1.type; | ||
| functionName = parent_1.name.text; | ||
| doRuntimeCheck = true; | ||
| } | ||
| break; | ||
| case ts.SyntaxKind.MethodDeclaration: | ||
| { | ||
| if (dname == "get" || dname == "post" || dname == "put" || dname == "del" || dname == "all") { | ||
| var parent_2 = node.parent; | ||
| var symbol = symtab_1.checker.getSymbolAtLocation(parent_2.name); | ||
| parentIndex = symtab_1.getIndex(symbol); | ||
| var type = symtab_1.checker.getTypeOfSymbolAtLocation(symbol, symbol.valueDeclaration); | ||
| var typeNode = symtab_1.checker.typeToTypeNode(type, node.parent, ts.NodeBuilderFlags.IgnoreErrors | ts.NodeBuilderFlags.WriteTypeParametersInQualifiedName); | ||
| var parameterContext = parent_2.parameters; | ||
| comment = ts.displayPartsToString(symbol.getDocumentationComment(symtab_1.checker)); | ||
| returnType = parent_2.type; | ||
| var parms = typeNode.parameters; | ||
| var parmContext = parent_2.parameters; | ||
| var decoratorMeta = {}; | ||
| for (var i = 0; i < parmContext.length; i++) { | ||
| if (parmContext[i].decorators != null) { | ||
| for (var j = 0; j < parmContext[i].decorators.length; j++) { | ||
| var dec = parmContext[i].decorators[j].expression; | ||
| var dsym_1 = symtab_1.checker.getSymbolAtLocation(dec.getFirstToken()); | ||
| var dname_1 = dsym_1.getName(); | ||
| var parmDecl = dec.parent; | ||
| var psym = symtab_1.checker.getSymbolAtLocation(parmDecl.parent.name); | ||
| var pname = psym.getName(); | ||
| var decArgList = void 0; | ||
| if (ts.isCallExpression(dec)) { | ||
| decArgList = genArgumentList(dec); | ||
| } | ||
| if (decArgList == null) | ||
| decArgList = []; | ||
| if (decoratorMeta[pname] == null) | ||
| decoratorMeta[pname] = {}; | ||
| decoratorMeta[pname][dname_1] = decArgList; | ||
| } | ||
| } | ||
| } | ||
| methodParameters = traverse_1.traverseParameterList(typeNode.parameters, decoratorMeta); | ||
| functionName = parent_2.name.text; | ||
| doRuntimeCheck = true; | ||
| } | ||
| } | ||
| break; | ||
| case ts.SyntaxKind.ClassDeclaration: | ||
| { | ||
| var parent_3 = node.parent; | ||
| var symbol = symtab_1.checker.getSymbolAtLocation(parent_3.name); | ||
| var source = (parent_3.parent); | ||
| parentIndex = symtab_1.getIndex(symbol); | ||
| comment = ts.displayPartsToString(symbol.getDocumentationComment(symtab_1.checker)); | ||
| if (dname == "controller") { | ||
| traverse_1.addController(parentIndex, source.fileName, comment); | ||
| doDecoratedClass = true; | ||
| } | ||
| else if (dname == "router") { | ||
| traverse_1.addRouter(parentIndex, source.fileName, comment); | ||
| doDecoratedClass = true; | ||
| } | ||
| ts.forEachChild(parent_3, visit); | ||
| } | ||
| break; | ||
| default: { | ||
| var parent_4 = node.parent; | ||
| throw ("unknown decorated type (" + parent_4.kind + ")"); | ||
| } | ||
| } | ||
| if (ts.isCallExpression(expr)) { | ||
| var cexpr = expr; | ||
| var id = cexpr.expression; | ||
| var type = id.text; | ||
| if (type == "del") | ||
| type = "delete"; | ||
| if (doRuntimeCheck) { | ||
| var symbol = symtab_1.checker.getSymbolAtLocation(id.parent.parent.parent.parent.name); | ||
| var index = symtab_1.getIndex(symbol); | ||
| var decoratorArgs = genArgumentList(cexpr); | ||
| var sentry = symtab_1.symtabGet(index); | ||
| var item = { | ||
| index: index, | ||
| classRef: sentry.schemaRefId, | ||
| comment: comment, | ||
| name: functionName, | ||
| decoratorArgs: decoratorArgs, | ||
| methodParameters: methodParameters, | ||
| returnType: returnType, | ||
| type: type | ||
| }; | ||
| endpoints.push(item); | ||
| } | ||
| else if (doDecoratedClass) { | ||
| var entry = symtab_1.symtabGet(parentIndex); | ||
| entry.args = genArgumentList(cexpr); | ||
| } | ||
| } | ||
| } | ||
| } | ||
| function saveObjectProperty(parentIndex, name, typeDesc, optional) { | ||
| var symbol = symtab_1.checker.getSymbolAtLocation(name); | ||
| var propertyName = tsany.getTextOfNode(name); | ||
| if (propertyName != null && typeDesc != null) { | ||
| var jsDoc = []; | ||
| var tags = symbol.getJsDocTags(); | ||
| var comment = ts.displayPartsToString(symbol.getDocumentationComment(symtab_1.checker)); | ||
| if (tags.length != 0) { | ||
| var tagSrc = ["/**", " *"]; | ||
| for (var i = 0; i < tags.length; i++) { | ||
| if (tags[i].name == "integer") | ||
| tagSrc.push(" * @type {integer}"); | ||
| else | ||
| tagSrc.push(" * @" + tags[i].name + " " + tags[i].text); | ||
| } | ||
| tagSrc.push(" */"); | ||
| try { | ||
| //checkFile.write(tagSrc.join('\n')); | ||
| jsDoc.push(doctrine.parse(tagSrc.join('\n'), { unwrap: true })); | ||
| } | ||
| catch (e) { | ||
| throw ("invalid JSDoc: " + e); | ||
| } | ||
| } | ||
| // Create and save the JSON schema definition for a property for later use | ||
| // Save the args to invoke the call later. This is necessary due to out | ||
| // of order definitions of child member types. | ||
| defComp.push({ | ||
| sentry: symtab_1.symtabGet(parentIndex), | ||
| propertyName: propertyName, | ||
| type: typeDesc, | ||
| jsDoc: jsDoc, | ||
| check: { schemaNamespace: "check", docRoot: "#/definitions" }, | ||
| swagger: { enclosedBy: parentIndex, options: { schemaNamespace: "swagger", docRoot: "#/components/schemas", firstclassIntermediates: true } }, | ||
| optional: optional | ||
| }); | ||
| } | ||
| } | ||
| // Analyze the contents of a an interface or class declaration collect typing information | ||
| // and JSDoc style comments. | ||
| function visit2(node) { | ||
| var parent = node.parent; | ||
| var x; | ||
| if (parent.kind == ts.SyntaxKind.InterfaceDeclaration) | ||
| x = parent.name; | ||
| else if (parent.kind == ts.SyntaxKind.ClassDeclaration) | ||
| x = parent.name; | ||
| if (x != null) { | ||
| var parentSymbol = symtab_1.checker.getSymbolAtLocation(x); | ||
| var index = symtab_1.getIndex(parentSymbol); | ||
| switch (node.kind) { | ||
| case ts.SyntaxKind.PropertySignature: | ||
| { | ||
| // This will be the property node type if the parent is an interface | ||
| var sig = node; | ||
| var name_1 = sig.name; | ||
| var optional = (sig.questionToken != null); | ||
| saveObjectProperty(index, name_1, sig.type, optional); | ||
| } | ||
| break; | ||
| case ts.SyntaxKind.PropertyDeclaration: | ||
| { | ||
| // This will be the property node type if the parent is a class | ||
| var pdecl = node; | ||
| var name_2 = pdecl.name; | ||
| var optional = (pdecl.questionToken != null); | ||
| saveObjectProperty(index, name_2, pdecl.type, optional); | ||
| } | ||
| break; | ||
| } | ||
| } | ||
| } | ||
| function compileProperties() { | ||
| for (var i = 0; i < defComp.length; i++) { | ||
| var checkDef = symtab_1.typeToJSON(defComp[i].type, defComp[i].jsDoc, defComp[i].check); | ||
| var swaggerDef = symtab_1.typeToJSON(defComp[i].type, defComp[i].jsDoc, defComp[i].swagger); | ||
| if (checkDef != null && swaggerDef != null) { | ||
| defComp[i].sentry.members[defComp[i].propertyName] = { desc: { check: checkDef, swagger: swaggerDef }, type: defComp[i].type, optional: defComp[i].optional }; | ||
| } | ||
| } | ||
| } | ||
| function compileInheritance(sentry, heritageClauses) { | ||
| if (heritageClauses != null) { | ||
| ts.visitNodes(heritageClauses, function (n) { | ||
| var h = n; | ||
| ts.visitNodes(h.types, function (n) { | ||
| var hType = n; | ||
| var expr = hType.expression; | ||
| if (expr != null) { | ||
| var baseName = void 0; | ||
| switch (expr.kind) { | ||
| case ts.SyntaxKind.Identifier: | ||
| baseName = expr; | ||
| break; | ||
| case ts.SyntaxKind.PropertyAccessExpression: | ||
| baseName = expr.name; | ||
| break; | ||
| default: throw ("unknown inheritance source"); | ||
| } | ||
| var baseRef = symtab_1.checker.getSymbolAtLocation(baseName); | ||
| var baseIndex = symtab_1.getIndex(baseRef); | ||
| sentry.inherits.push(baseIndex); | ||
| } | ||
| return n; | ||
| }); | ||
| return n; | ||
| }); | ||
| } | ||
| } | ||
| // Recursively analyze an exported member of a source file. Relevant | ||
| // members include classes and interfaces and other refrenced types. | ||
| function visit(node) { | ||
| if (node.decorators != null) { | ||
| try { | ||
| for (var _i = 0, _a = node.decorators; _i < _a.length; _i++) { | ||
| var decorator = _a[_i]; | ||
| visitDecorator(decorator); | ||
| } | ||
| } | ||
| catch (e) { | ||
| console.log(e); | ||
| } | ||
| } | ||
| else if (tsany.isDeclaration(node)) { | ||
| var decl = node; | ||
| var name_3 = decl.name; | ||
| var type = void 0; | ||
| var symbol = void 0; | ||
| var comment = void 0; | ||
| var index = void 0; | ||
| var typeDesc = void 0; | ||
| if (name_3 != null) { | ||
| symbol = symtab_1.checker.getSymbolAtLocation(name_3); | ||
| comment = ts.displayPartsToString(symbol.getDocumentationComment(symtab_1.checker)); | ||
| index = symtab_1.getIndex(symbol); | ||
| var type_1 = symtab_1.checker.getDeclaredTypeOfSymbol(symbol); | ||
| typeDesc = symtab_1.checker.typeToTypeNode(type_1, node, ts.NodeBuilderFlags.IgnoreErrors | ts.NodeBuilderFlags.WriteTypeParametersInQualifiedName); | ||
| } | ||
| if (decl.kind == ts.SyntaxKind.TypeAliasDeclaration) { | ||
| var alias = decl; | ||
| ts.forEachChild(decl, visit); | ||
| symtab_1.symtabPut(index, { kind: "type", decl: node, typeDesc: typeDesc, members: {}, jsDoc: null, comment: comment }); | ||
| } | ||
| else if (decl.kind == ts.SyntaxKind.ClassDeclaration) { | ||
| var classDecl = decl; | ||
| var tags = ts.displayPartsToString(symbol.getJsDocTags()); | ||
| var sentry = symtab_1.symtabPut(index, { kind: "type", decl: node, typeDesc: typeDesc, members: {}, inherits: [], jsDoc: null, comment: comment }); | ||
| if (tags != "") | ||
| sentry.jsDoc = doctrine.parse(tags); | ||
| ts.forEachChild(decl, visit2); | ||
| compileInheritance(sentry, classDecl.heritageClauses); | ||
| } | ||
| else if (decl.kind == ts.SyntaxKind.InterfaceDeclaration) { | ||
| if (index != null) { | ||
| var intfDecl = decl; | ||
| var tags = ts.displayPartsToString(symbol.getJsDocTags()); | ||
| var sentry = symtab_1.symtabPut(index, { kind: "type", decl: node, typeDesc: typeDesc, members: {}, inherits: [], jsDoc: null, comment: comment }); | ||
| if (tags != "") | ||
| sentry.jsDoc = doctrine.parse(tags); | ||
| ts.forEachChild(decl, visit2); | ||
| compileInheritance(sentry, intfDecl.heritageClauses); | ||
| } | ||
| } | ||
| } | ||
| } | ||
| // Loop over all the source files and recursively analyze each | ||
| // exported member of that file. Build a symbol table containing | ||
| // relevant information, and then generate new source for | ||
| // automatic REST endpoints (which typeshcekcing) as well as | ||
| // accompanying swagger. | ||
| for (var _i = 0, _a = program.getSourceFiles(); _i < _a.length; _i++) { | ||
| var sourceFile = _a[_i]; | ||
| if (debugMode === true) { | ||
| console.log("visiting file: ", sourceFile.fileName); | ||
| } | ||
| ts.forEachChild(sourceFile, visit); | ||
| } | ||
| compileProperties(); | ||
| traverse_1.connectMethods(endpoints); | ||
| genSources(endpoints, packageName, srcRoot, checkFile, swaggerFile, redocFile, routesFile); | ||
| } | ||
| exports.generate = generate; | ||
| //# sourceMappingURL=main.js.map |
| {"version":3,"file":"main.js","sourceRoot":"","sources":["../../src/analyzer/main.ts"],"names":[],"mappings":"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"} |
| /// <reference types="node" /> | ||
| export declare function genRedoc(swaggerPath: string, redocFile: NodeJS.ReadWriteStream): void; |
| "use strict"; | ||
| Object.defineProperty(exports, "__esModule", { value: true }); | ||
| var redoc = require("../ReDoc"); | ||
| function genRedoc(swaggerPath, redocFile) { | ||
| redocFile.write(redoc.src(swaggerPath)); | ||
| } | ||
| exports.genRedoc = genRedoc; | ||
| //# sourceMappingURL=redoc.js.map |
| {"version":3,"file":"redoc.js","sourceRoot":"","sources":["../../src/analyzer/redoc.ts"],"names":[],"mappings":";;AAAA,gCAAkC;AAElC,SAAgB,QAAQ,CAAC,WAAkB,EAAC,SAAgC;IAC1E,SAAS,CAAC,KAAK,CAAC,KAAK,CAAC,GAAG,CAAC,WAAW,CAAC,CAAC,CAAC;AAC1C,CAAC;AAFD,4BAEC"} |
| import { Controller, Router } from "./types"; | ||
| /** | ||
| * Create the hardcoded first part of a swagger doc. Global documentation derived from the | ||
| * block comments of the controller classes as well as the class annotated with @router is set here. | ||
| * | ||
| * @param {any} def reference to the swagger doc. | ||
| * @param {string} projectName the name of the project (is derived from package.json packageName). | ||
| * @param {Router} router definition. | ||
| * @param {Controller[]} array of controller definitions. | ||
| */ | ||
| export declare function genSwaggerPreamble(def: any, projectName: string, router: Router, controllers: Controller[]): void; | ||
| /** | ||
| * Generate swagger tags based on controller paths | ||
| * | ||
| * @param {any} def reference to the swagger doc. | ||
| * @param {Router} router definition. | ||
| * @param {Controller[]} array of controller definitions. | ||
| */ | ||
| export declare function genSwaggerRootTags(def: any, router: Router, controllers: Controller[]): void; | ||
| /** | ||
| * Generate all paths belonging to a router. The expectation is that currently there will | ||
| * only be a singleton router. | ||
| * | ||
| * @param {any} def reference to the swagger doc. | ||
| * @param {Router} router definition. | ||
| * @param {Controller[]} array of controller definitions. | ||
| */ | ||
| export declare function genSwaggerRoutes(def: any, synthesizedTypes: any, router: Router, controllers: Controller[]): void; |
| "use strict"; | ||
| Object.defineProperty(exports, "__esModule", { value: true }); | ||
| var ts = require("typescript"); | ||
| var tsany = ts; | ||
| var symtab_1 = require("./symtab"); | ||
| var traverse_1 = require("./traverse"); | ||
| /** | ||
| * Create the hardcoded first part of a swagger doc. Global documentation derived from the | ||
| * block comments of the controller classes as well as the class annotated with @router is set here. | ||
| * | ||
| * @param {any} def reference to the swagger doc. | ||
| * @param {string} projectName the name of the project (is derived from package.json packageName). | ||
| * @param {Router} router definition. | ||
| * @param {Controller[]} array of controller definitions. | ||
| */ | ||
| function genSwaggerPreamble(def, projectName, router, controllers) { | ||
| var comments = ""; | ||
| if (router.comment != null && router.comment != '') | ||
| comments += router.comment + "\n\n"; | ||
| def.openapi = "3.0.0"; | ||
| def.info = { version: "1.0.0", title: projectName }; | ||
| if (comments.length != 0) | ||
| def.info.description = comments; | ||
| } | ||
| exports.genSwaggerPreamble = genSwaggerPreamble; | ||
| /** | ||
| * Generate swagger tags based on controller paths | ||
| * | ||
| * @param {any} def reference to the swagger doc. | ||
| * @param {Router} router definition. | ||
| * @param {Controller[]} array of controller definitions. | ||
| */ | ||
| function genSwaggerRootTags(def, router, controllers) { | ||
| var tags = []; | ||
| for (var i = 0; i < controllers.length; i++) { | ||
| var tag = controllers[i].classRef; | ||
| if (controllers[i].comment != null && controllers[i].comment != '') | ||
| tags.push({ name: tag, description: controllers[i].comment }); | ||
| } | ||
| def.tags = tags; | ||
| } | ||
| exports.genSwaggerRootTags = genSwaggerRootTags; | ||
| function genSwaggerPathParameters(router, controller, method, methodPathDecomposition) { | ||
| var parameters = []; | ||
| for (var i = 0; i < method.methodParameters.length; i++) { | ||
| var parameter = method.methodParameters[i]; | ||
| var jsDoc = traverse_1.synthesizeParameterJSDoc(method.methodParameters[i]); | ||
| var parameterTypedef = symtab_1.typeToJSON(parameter.type, jsDoc, { expandRefs: true, schemaNamespace: "swagger", docRoot: "#/components/schemas" }); | ||
| if (parameterTypedef != null && parameterTypedef.type == "object") { | ||
| for (var pname in parameterTypedef.properties) { | ||
| if (traverse_1.isURLParam(pname, router, controller, methodPathDecomposition)) | ||
| parameters.push({ name: pname, in: "path", schema: parameterTypedef.properties[pname], required: true }); | ||
| } | ||
| } | ||
| else { | ||
| if (traverse_1.isURLParam(parameter.id, router, controller, methodPathDecomposition)) | ||
| parameters.push({ name: parameter.id, in: "path", schema: parameterTypedef, required: true }); | ||
| } | ||
| } | ||
| return parameters; | ||
| } | ||
| function genSwaggerRequestParameters(router, controller, method, methodPathDecomposition) { | ||
| var parameters = []; | ||
| // Create the input doc swagger definition given the method parameters. Recursively expand | ||
| // objects rather that using JSON schema $ref, and if a method parameter is of type object, then | ||
| // assume it's a class or interance and instead generate a swagger doc that is the members of | ||
| // that aggregate. | ||
| for (var i = 0; i < method.methodParameters.length; i++) { | ||
| var parameter = method.methodParameters[i]; | ||
| var jsDoc = traverse_1.synthesizeParameterJSDoc(method.methodParameters[i]); | ||
| var parameterTypedef = symtab_1.typeToJSON(parameter.type, jsDoc, { expandRefs: true, docRoot: "#/components/schemas" }); | ||
| if (parameterTypedef != null && parameterTypedef.type == "object") { | ||
| for (var pname in parameterTypedef.properties) { | ||
| var isRequired = false; | ||
| if (!traverse_1.isURLParam(pname, router, controller, methodPathDecomposition)) { | ||
| if (parameterTypedef.required != null) { | ||
| for (var l = 0; l < parameterTypedef.required.length; l++) { | ||
| if (parameterTypedef.required[l] == pname) | ||
| isRequired = true; | ||
| } | ||
| } | ||
| parameters.push({ name: pname, in: "query", schema: parameterTypedef.properties[pname], required: isRequired }); | ||
| } | ||
| } | ||
| } | ||
| else if (!traverse_1.isURLParam(parameter.id, router, controller, methodPathDecomposition)) { | ||
| var parmDesc = { name: parameter.id, in: "query", schema: parameterTypedef }; | ||
| if (parameterTypedef.required != null && parameterTypedef.required.length > 0) | ||
| parmDesc.required = parameterTypedef.required; | ||
| parameters.push(parmDesc); | ||
| } | ||
| } | ||
| return parameters; | ||
| } | ||
| function genSwaggerRequestBody(synthesizedTypes, router, controller, method, methodPathDecomposition) { | ||
| var parameters = []; | ||
| var parametersEx = []; | ||
| for (var i = 0; i < method.methodParameters.length; i++) { | ||
| var parameter = method.methodParameters[i]; | ||
| var jsDoc = traverse_1.synthesizeParameterJSDoc(method.methodParameters[i]); | ||
| var parameterTypedef = symtab_1.typeToJSON(parameter.type, jsDoc, { schemaNamespace: "swagger", firstclassIntermediates: true, docRoot: "#/components/schemas" }); | ||
| var parameterTypedefEx = symtab_1.typeToJSON(parameter.type, jsDoc, { expandRefs: true, schemaNamespace: "swagger", docRoot: "#/components/schemas" }); | ||
| if (!traverse_1.isURLParam(parameter.id, router, controller, methodPathDecomposition)) { | ||
| parameters.push({ name: parameter.id, required: parameter.required, schema: parameterTypedef }); | ||
| parametersEx.push({ name: parameter.id, required: parameter.required, schema: parameterTypedefEx }); | ||
| } | ||
| } | ||
| if (parameters.length == 1) { | ||
| var properties = {}; | ||
| var propertiesEx = {}; | ||
| var jsonContent = void 0; | ||
| var formContent = void 0; | ||
| var encoding = {}; | ||
| var encodingPopulated = false; | ||
| if (parameters[0].schema['$ref'] != null) { | ||
| jsonContent = { schema: parameters[0].schema }; | ||
| formContent = { schema: parametersEx[0].schema }; | ||
| } | ||
| else { | ||
| jsonContent = { schema: { title: method.name + " plist", type: "object", properties: properties } }; | ||
| formContent = { schema: { title: method.name + " plist", type: "object", properties: propertiesEx } }; | ||
| properties[parameters[0].name] = parameters[0].schema; | ||
| propertiesEx[parametersEx[0].name] = parametersEx[0].schema; | ||
| } | ||
| for (var property in parametersEx[0].schema.properties) { | ||
| if (parametersEx[0].schema.content != "flat" && (parametersEx[0].schema.properties[property].type == "object" || parametersEx[0].schema.properties[property] == null)) { | ||
| encoding[property] = { contentType: "application/json" }; | ||
| encodingPopulated = true; | ||
| } | ||
| } | ||
| if (encodingPopulated) | ||
| formContent["encoding"] = encoding; | ||
| var res = { content: { "application/json": jsonContent, "application/x-www-form-urlencoded": formContent } }; | ||
| if (parameters[0].required.length != 0) | ||
| res.required = parameters[0].required; | ||
| return res; | ||
| } | ||
| else if (parameters.length > 1) { | ||
| var methodName = method.name; | ||
| var rqbName = "" + controller.classRef + methodName.substring(0, 1).toUpperCase() + methodName.substring(1) + "Body"; | ||
| var properties = {}; | ||
| var required = []; | ||
| var notAllOptional = false; | ||
| var inline = { type: "object", properties: properties }; | ||
| var encoding = {}; | ||
| var encodingPopulated = false; | ||
| for (var i = 0; i < parameters.length; i++) { | ||
| properties[parameters[i].name] = parameters[i].schema; | ||
| if (parameters[i].schema.content != "flat" && (parameters[i].schema.type == "object" || parameters[i].schema.type == null)) { | ||
| encoding[parameters[i].name] = { contentType: "application/json" }; | ||
| encodingPopulated = true; | ||
| } | ||
| if (parameters[i].required) { | ||
| required.push(parameters[i].name); | ||
| notAllOptional = true; | ||
| } | ||
| } | ||
| var jsonContent = { schema: { "$ref": "#/components/schemas/" + rqbName } }; | ||
| var formContent = { schema: inline }; | ||
| if (encodingPopulated) | ||
| formContent["encoding"] = encoding; | ||
| synthesizedTypes[rqbName] = { type: "object", properties: properties, description: "synthesized request body type for " + controller.classRef + "." + methodName }; | ||
| if (notAllOptional) { | ||
| synthesizedTypes[rqbName].required = required; | ||
| inline.required = required; | ||
| } | ||
| return { | ||
| required: notAllOptional, | ||
| content: { | ||
| "application/json": jsonContent, | ||
| "application/x-www-form-urlencoded": formContent | ||
| } | ||
| }; | ||
| } | ||
| else | ||
| return { content: {} }; | ||
| } | ||
| function returnAtom(typeDesc) { | ||
| var index = symtab_1.getIndex(typeDesc); | ||
| var contentType = "application/json"; | ||
| var res = {}; | ||
| var schema; | ||
| if (index != null && index.local == "FileRef") { | ||
| var args = typeDesc.typeArguments; | ||
| if (args != null) { | ||
| contentType = tsany.getTextOfNode(args[0]); | ||
| contentType = contentType.replace(/^"(.*)"$/, '$1'); | ||
| } | ||
| else | ||
| contentType = "application/octet-stream"; | ||
| schema = { type: "string", format: "binary" }; | ||
| } | ||
| else { | ||
| schema = symtab_1.typeToJSON(typeDesc, null, { expandRefs: true, schemaNamespace: "swagger", docRoot: "#/components/schemas" }); | ||
| } | ||
| res[contentType] = { schema: schema }; | ||
| return res; | ||
| } | ||
| function updateExplicitStatus(res, statusCode, componentType) { | ||
| var content = returnAtom(componentType); | ||
| if (content != null) { | ||
| var n = parseInt(statusCode); | ||
| var description = void 0; | ||
| switch (n) { | ||
| case 200: | ||
| description = "OK"; | ||
| break; | ||
| case 201: | ||
| description = "Created"; | ||
| break; | ||
| case 202: | ||
| description = "Accepted"; | ||
| break; | ||
| case 203: | ||
| description = "Non-Authoritative Information"; | ||
| break; | ||
| case 204: | ||
| description = "No Content"; | ||
| break; | ||
| case 205: | ||
| description = "Reset Content"; | ||
| break; | ||
| case 206: | ||
| description = "Partial Content"; | ||
| break; | ||
| case 207: | ||
| description = "Multi Status"; | ||
| break; | ||
| case 208: | ||
| description = "Already Reported"; | ||
| break; | ||
| case 226: | ||
| description = "IM Used"; | ||
| break; | ||
| case 300: | ||
| description = "Multiple Choices"; | ||
| break; | ||
| case 302: | ||
| description = "Found"; | ||
| break; | ||
| case 303: | ||
| description = "See Other"; | ||
| break; | ||
| case 304: | ||
| description = "Not Modified"; | ||
| break; | ||
| case 305: | ||
| description = "Use Proxy"; | ||
| break; | ||
| case 306: | ||
| description = "Switch Proxy"; | ||
| break; | ||
| case 307: | ||
| description = "Temporary Redirect"; | ||
| break; | ||
| case 308: | ||
| description = "Permanent Redirect"; | ||
| break; | ||
| case 400: | ||
| description = "Bad Request"; | ||
| break; | ||
| case 401: | ||
| description = "Unauthorized"; | ||
| break; | ||
| case 402: | ||
| description = "Payment Required"; | ||
| break; | ||
| case 403: | ||
| description = "Forbidden"; | ||
| break; | ||
| case 404: | ||
| description = "Not Found"; | ||
| break; | ||
| case 405: | ||
| description = "Method Not Allowed"; | ||
| break; | ||
| case 406: | ||
| description = "Not Acceptable"; | ||
| break; | ||
| case 407: | ||
| description = "Proxy Authentication Required"; | ||
| break; | ||
| case 408: | ||
| description = "Request Timeout"; | ||
| break; | ||
| case 409: | ||
| description = "Conflict"; | ||
| break; | ||
| case 410: | ||
| description = "Gone"; | ||
| break; | ||
| case 411: | ||
| description = "Length Required"; | ||
| break; | ||
| case 412: | ||
| description = "Precondition Failed"; | ||
| break; | ||
| case 413: | ||
| description = "Payload Too Large"; | ||
| break; | ||
| case 414: | ||
| description = "URI Too Long"; | ||
| break; | ||
| case 415: | ||
| description = "Unsupported Media Type"; | ||
| break; | ||
| case 416: | ||
| description = "Range Not Satisfiable"; | ||
| break; | ||
| case 417: | ||
| description = "Expectation Failed"; | ||
| break; | ||
| case 418: | ||
| description = "I'm a teapot"; | ||
| break; | ||
| case 421: | ||
| description = "Misdirected Request"; | ||
| break; | ||
| case 422: | ||
| description = "Unprocessable Entity"; | ||
| break; | ||
| case 423: | ||
| description = "Locked"; | ||
| break; | ||
| case 424: | ||
| description = "Failed Dependency"; | ||
| break; | ||
| case 426: | ||
| description = "Upgrade Required"; | ||
| break; | ||
| case 428: | ||
| description = "Precondition Required"; | ||
| break; | ||
| case 429: | ||
| description = "Too Many Request"; | ||
| break; | ||
| case 431: | ||
| description = "Request Header Fields Too Large"; | ||
| break; | ||
| case 451: | ||
| description = "Unavailable For Legal Reasons"; | ||
| break; | ||
| case 500: | ||
| description = "Internal Server Error"; | ||
| break; | ||
| case 501: | ||
| description = "Not Implemented"; | ||
| break; | ||
| case 502: | ||
| description = "Bad Gateway"; | ||
| break; | ||
| case 503: | ||
| description = "Service Unavailable"; | ||
| break; | ||
| case 504: | ||
| description = "Gateway Timeout"; | ||
| break; | ||
| case 505: | ||
| description = "HTTP Version Not Supported"; | ||
| break; | ||
| case 506: | ||
| description = "Variant Also Negotiates"; | ||
| break; | ||
| case 507: | ||
| description = "Insufficient Storage"; | ||
| break; | ||
| case 508: | ||
| description = "Loop Detected"; | ||
| break; | ||
| case 510: | ||
| description = "Not Extended"; | ||
| break; | ||
| case 511: | ||
| description = "Network Authentication Required"; | ||
| break; | ||
| default: | ||
| description = "Unknown"; | ||
| break; | ||
| } | ||
| res[statusCode] = { description: description, content: content }; | ||
| } | ||
| else | ||
| res["204"] = { description: "No Content" }; | ||
| return res; | ||
| } | ||
| function explicitStatus(returnTypeDesc) { | ||
| var res = {}; | ||
| var statusCodeDesc = returnTypeDesc.typeArguments[0]; | ||
| switch (statusCodeDesc.kind) { | ||
| case ts.SyntaxKind.LiteralType: | ||
| { | ||
| var statusCode = symtab_1.checker.getTypeFromTypeNode(statusCodeDesc).value; | ||
| var componentType = returnTypeDesc.typeArguments[1]; | ||
| updateExplicitStatus(res, statusCode, componentType); | ||
| } | ||
| break; | ||
| case ts.SyntaxKind.UnionType: | ||
| { | ||
| var unionDesc = statusCodeDesc; | ||
| for (var i = 0; i < unionDesc.types.length; i++) { | ||
| var statusCode = symtab_1.checker.getTypeFromTypeNode(unionDesc.types[i]).value; | ||
| var componentType = returnTypeDesc.typeArguments[1]; | ||
| updateExplicitStatus(res, statusCode, componentType); | ||
| } | ||
| } | ||
| break; | ||
| } | ||
| return res; | ||
| } | ||
| function returnMerge(resN, resX) { | ||
| for (var statusCode in resN) { | ||
| if (resX[statusCode] == null) | ||
| resX[statusCode] = resN[statusCode]; | ||
| else { | ||
| for (var contentType in resN[statusCode].content) { | ||
| if (resX[statusCode].content[contentType] == null) | ||
| resX[statusCode].content[contentType] = resN[statusCode].content[contentType]; | ||
| else if (contentType == "application/json") { | ||
| if (resX[statusCode].content[contentType].oneOf == null) { | ||
| var tmp = resX[statusCode].content[contentType]; | ||
| resX[statusCode].content[contentType] = { oneOf: [] }; | ||
| resX[statusCode].content.oneOf.push(tmp); | ||
| } | ||
| resX[statusCode].content.oneOf.push(resN); | ||
| } | ||
| else | ||
| throw ("unable to combine non-hierarchial content types with oneOf"); | ||
| } | ||
| } | ||
| } | ||
| } | ||
| function genSwaggerReturn(returnTypeDesc, res) { | ||
| if (returnTypeDesc == null) | ||
| return null; | ||
| var returnTypename = symtab_1.getIndex(returnTypeDesc); | ||
| // If the method return type is a promise infer that this is an async function and | ||
| // instead use the subordinate type as the type defined by the swagger doc. | ||
| if (returnTypename == "Promise") { | ||
| var promiseArg = returnTypeDesc.typeArguments[0]; | ||
| genSwaggerReturn(promiseArg, res); | ||
| } | ||
| else { | ||
| if (traverse_1.isExplicitStatus(returnTypename)) { | ||
| var resX = explicitStatus(returnTypeDesc); | ||
| for (var statusCode in resX) | ||
| res[statusCode] = resX[statusCode]; | ||
| } | ||
| else if (traverse_1.isFileReturn(returnTypename)) { | ||
| var content = returnAtom(returnTypeDesc); | ||
| if (content != null) | ||
| res["200"] = { description: "Successful response", content: content }; | ||
| else | ||
| res["204"] = { description: "Successful response" }; | ||
| } | ||
| else { | ||
| var isUnion = returnTypeDesc.kind == ts.SyntaxKind.UnionType; | ||
| if (!isUnion && returnTypeDesc.kind == ts.SyntaxKind.TypeReference) { | ||
| var alias = symtab_1.symtabGet(returnTypename).decl; | ||
| if (alias.type) { | ||
| isUnion = alias.type.kind == ts.SyntaxKind.UnionType; | ||
| if (isUnion) | ||
| returnTypeDesc = alias.type; | ||
| } | ||
| } | ||
| if (isUnion) { | ||
| var unionDesc = returnTypeDesc; | ||
| var resX = {}; | ||
| var isMultiStatus = false; | ||
| for (var i = 0; i < unionDesc.types.length; i++) { | ||
| var unionElementTypename = symtab_1.getIndex(unionDesc.types[i]); | ||
| if (unionElementTypename != null) { | ||
| if (!traverse_1.isExplicitStatus(unionElementTypename)) { | ||
| var swaggerDef = returnAtom(unionDesc.types[i]); | ||
| if (swaggerDef != null) { | ||
| var resY = {}; | ||
| resY["200"] = swaggerDef; | ||
| returnMerge(resY, resX); | ||
| } | ||
| } | ||
| else { | ||
| var resY = explicitStatus(unionDesc.types[i]); | ||
| returnMerge(resY, resX); | ||
| } | ||
| } | ||
| else { | ||
| var swaggerDef = returnAtom(unionDesc.types[i]); | ||
| if (swaggerDef != null) { | ||
| var resY = {}; | ||
| resY["200"] = swaggerDef; | ||
| returnMerge(resY, resX); | ||
| } | ||
| } | ||
| } | ||
| for (var statusCode in resX) | ||
| res[statusCode] = resX[statusCode]; | ||
| } | ||
| else { | ||
| if (returnTypeDesc.kind == ts.SyntaxKind.TypeReference) { | ||
| var decl = symtab_1.symtabGet(returnTypename).decl; | ||
| if (decl.type) { | ||
| returnTypeDesc = decl.type; | ||
| returnTypename = symtab_1.getIndex(returnTypeDesc); | ||
| } | ||
| } | ||
| if (traverse_1.isExplicitStatus(returnTypename)) { | ||
| var resX = explicitStatus(returnTypeDesc); | ||
| for (var statusCode in resX) | ||
| res[statusCode] = resX[statusCode]; | ||
| } | ||
| else { | ||
| var content = returnAtom(returnTypeDesc); | ||
| if (content != null) | ||
| res["200"] = { description: "Successful response", content: content }; | ||
| else | ||
| res["204"] = { description: "Successful response" }; | ||
| } | ||
| } | ||
| } | ||
| } | ||
| } | ||
| /** | ||
| * Generate swagger paths (REST endpoints) given the combination of prefix, controller | ||
| * paths and methods of those controllers. | ||
| * | ||
| * @param {any} def reference to the swagger doc. | ||
| * @param {string} prefix top level path to pre-pend to all paths. | ||
| * @param {Controller[]} array of controller definitions. | ||
| */ | ||
| function genSwaggerPaths(def, synthesizedTypes, router, controllers) { | ||
| var paths = {}; | ||
| var p1 = traverse_1.decompositionToPath(router.decomposition, "swagger"); | ||
| for (var i = 0; i < controllers.length; i++) { | ||
| var methods = controllers[i].methods; | ||
| var p2 = traverse_1.decompositionToPath(controllers[i].decomposition, "swagger"); | ||
| var comment = controllers[i].comment; | ||
| var tag = controllers[i].classRef; | ||
| // For each controller, iterate over every method and create a path | ||
| // for it. If the method verb decorator contains a path use it, otherwise | ||
| // use the name of the method itself. | ||
| for (var j = 0; j < methods.length; j++) { | ||
| var methodPath = methods[j].name; | ||
| var parameters = []; | ||
| var methodType = methods[j].type; | ||
| var responses = {}; | ||
| var methodComment = methods[j].comment; | ||
| if (methods[j].decoratorArgs.length != 0) | ||
| methodPath = methods[j].decoratorArgs[0]; | ||
| var methodPathDecomposition = traverse_1.decomposePath(methodPath); | ||
| var p3 = traverse_1.decompositionToPath(methodPathDecomposition, "swagger"); | ||
| // operationId is a unique identifier (across entire doc) for an operation | ||
| var operationId = tag + '_' + methods[j].name; | ||
| var path = { tags: [tag], operationId: operationId, responses: responses }; | ||
| var pathId = '/' + p2 + '/' + p3; | ||
| var pathParameters = genSwaggerPathParameters(router, controllers[i], methods[j], methodPathDecomposition); | ||
| if (methodComment != null && methodComment != "") | ||
| path.description = methodComment; | ||
| genSwaggerReturn(methods[j].returnType, responses); | ||
| if (methodType == "post" || methodType == "all" || methodType == "put" || methodType == "patch") { | ||
| if (pathParameters.length != 0) | ||
| path.parameters = pathParameters; | ||
| path.requestBody = genSwaggerRequestBody(synthesizedTypes, router, controllers[i], methods[j], methodPathDecomposition); | ||
| } | ||
| else | ||
| path.parameters = pathParameters.concat(genSwaggerRequestParameters(router, controllers[i], methods[j], methodPathDecomposition)); | ||
| if (p1 != "") | ||
| pathId = '/' + p1 + pathId; | ||
| if (paths[pathId] == null) | ||
| paths[pathId] = {}; | ||
| paths[pathId][methodType] = path; | ||
| } | ||
| } | ||
| def.paths = paths; | ||
| } | ||
| /** | ||
| * Generate all paths belonging to a router. The expectation is that currently there will | ||
| * only be a singleton router. | ||
| * | ||
| * @param {any} def reference to the swagger doc. | ||
| * @param {Router} router definition. | ||
| * @param {Controller[]} array of controller definitions. | ||
| */ | ||
| function genSwaggerRoutes(def, synthesizedTypes, router, controllers) { | ||
| var prefix = traverse_1.decompositionToPath(router.decomposition, "swagger"); | ||
| genSwaggerPaths(def, synthesizedTypes, router, controllers); | ||
| } | ||
| exports.genSwaggerRoutes = genSwaggerRoutes; | ||
| //# sourceMappingURL=swagger.js.map |
| {"version":3,"file":"swagger.js","sourceRoot":"","sources":["../../src/analyzer/swagger.ts"],"names":[],"mappings":"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"} |
| import * as ts from "typescript"; | ||
| declare let symtab: any; | ||
| declare let checker: any; | ||
| declare function setChecker(program: any): void; | ||
| declare function symtabGet(key: any): any; | ||
| declare function symtabPut(key: any, obj: any): any; | ||
| /** | ||
| * This function converts typescript keywords to JSON schema. | ||
| * | ||
| * @param {string} docRoot The root path in the document object for JSDoc | ||
| * definitions. Used to construct $ref values. | ||
| * @param {string} name The name of the typescript type. | ||
| */ | ||
| declare function mapTypeDescName(docRoot: string, name: string): Object; | ||
| declare function getIndex(desc: ts.TypeNode | ts.Symbol): any; | ||
| /** | ||
| * This function is the main entry point for converting a AST subtree describing a | ||
| * type declaration to its analogous JSON schema definition. Some typescript features | ||
| * are not mappable currently (e.g. functions), while some are simply not implemented | ||
| * yet. The typescript parser also collects JSDoc style comments associated with a | ||
| * type declaration and exposes that information in the AST as well. These comments | ||
| * are also part of the output JSON schema. The context of the use of the JSON schema | ||
| * can also effect the structure of the schema (e.g. use references to another part of | ||
| * the containing document, or expand fully all references). Such infomation is passed | ||
| * using options. | ||
| * | ||
| * @param {any} typeDesc Reference to the AST substree describing the type for which to | ||
| * create the JSON schema. | ||
| * @param {any} jsDoc The associated JSDoc comment. | ||
| * @param {any} options Affects the rules governing the structure of the resulting schema. | ||
| */ | ||
| declare function typeToJSON(typeDesc: any, jsDoc: any, context?: any): Object; | ||
| export { checker, getIndex, mapTypeDescName, setChecker, symtab, symtabGet, symtabPut, typeToJSON }; |
| "use strict"; | ||
| Object.defineProperty(exports, "__esModule", { value: true }); | ||
| var ts = require("typescript"); | ||
| var tsany = ts; | ||
| var symtab = {}; | ||
| exports.symtab = symtab; | ||
| var schemaRefIds = {}; | ||
| var numIntermediates = 0; | ||
| var checker; | ||
| exports.checker = checker; | ||
| function getSourceContext(n) { | ||
| var start = n; | ||
| while (n != null && n.parent != null && n.parent.kind != ts.SyntaxKind.SourceFile) | ||
| n = n.parent; | ||
| if (n != null && n.parent != null) { | ||
| var loc = ts.getLineAndCharacterOfPosition(n.parent, start.pos); | ||
| return { fileName: n.parent.fileName, lineNumber: loc.line }; | ||
| } | ||
| } | ||
| function setChecker(program) { | ||
| exports.checker = checker = program.getTypeChecker(); | ||
| } | ||
| exports.setChecker = setChecker; | ||
| function symtabKeyToString(key) { | ||
| if (typeof key == "string") | ||
| return key; | ||
| else if (typeof key == "object") { | ||
| if (key.module != null && key.local != null) | ||
| return "" + key.module + key.local; | ||
| if (key.local != null) | ||
| return key.local; | ||
| } | ||
| return null; | ||
| } | ||
| function symtabGet(key) { | ||
| var s = symtabKeyToString(key); | ||
| if (s != null) | ||
| return symtab[s]; | ||
| return null; | ||
| } | ||
| exports.symtabGet = symtabGet; | ||
| function newSchemaRefId(key) { | ||
| if (typeof key == "string") | ||
| return key; | ||
| if (key.local != null) { | ||
| if (schemaRefIds[key.local] == null) { | ||
| schemaRefIds[key.local] = { ext: 1 }; | ||
| return key.local; | ||
| } | ||
| else | ||
| schemaRefIds[key.local].ext++; | ||
| return key.local + "-" + schemaRefIds[key.local].ext; | ||
| } | ||
| } | ||
| function symtabPut(key, obj) { | ||
| var s = symtabKeyToString(key); | ||
| if (s != null) { | ||
| symtab[s] = obj; | ||
| symtab[s].schemaRefId = newSchemaRefId(key); | ||
| return obj; | ||
| } | ||
| return null; | ||
| } | ||
| exports.symtabPut = symtabPut; | ||
| function storeIntermediate(obj) { | ||
| var key = { local: "Intermediate" + numIntermediates++, module: "ts-api" }; | ||
| obj.kind = "itype"; | ||
| symtabPut(key, obj); | ||
| return key.local; | ||
| } | ||
| /** | ||
| * This function translates a token found in an AST for a type declaration to the | ||
| * corresponding JSON schema definition. The implementation for some objects is | ||
| * undefined (e.g. Function) and that token is ignored, unrecognized tokens cause | ||
| * an exception. | ||
| * | ||
| * @param {any} o The AST token object. | ||
| * @param {any} jsDoc A reference to the JSDoc object. | ||
| */ | ||
| function tokenObjectToJSON(o, jsDoc) { | ||
| var res = null; | ||
| var unknown = false; | ||
| switch (o.kind) { | ||
| case ts.SyntaxKind.StringKeyword: | ||
| { | ||
| res = { type: "string" }; | ||
| } | ||
| break; | ||
| case ts.SyntaxKind.NumberKeyword: | ||
| { | ||
| res = { type: "number" }; | ||
| } | ||
| break; | ||
| case ts.SyntaxKind.BooleanKeyword: | ||
| res = { type: "boolean" }; | ||
| break; | ||
| case ts.SyntaxKind.AnyKeyword: | ||
| res = { anyOf: [{ type: "array" }, { type: "object" }, { type: "number" }, { type: "string" }] }; | ||
| break; | ||
| case ts.SyntaxKind.NullKeyword: | ||
| res = { type: "null" }; | ||
| break; | ||
| case ts.SyntaxKind.UndefinedKeyword: break; | ||
| case ts.SyntaxKind.UnknownKeyword: break; | ||
| case ts.SyntaxKind.SymbolKeyword: break; | ||
| case ts.SyntaxKind.ObjectKeyword: | ||
| res = { type: "object" }; | ||
| break; | ||
| case ts.SyntaxKind.FunctionType: break; | ||
| case ts.SyntaxKind.VoidKeyword: | ||
| res = { type: "null" }; | ||
| break; | ||
| case ts.SyntaxKind.NeverKeyword: | ||
| break; | ||
| break; | ||
| default: | ||
| unknown = true; | ||
| break; | ||
| } | ||
| if (unknown) { | ||
| var sc = getSourceContext(o); | ||
| if (sc != null) | ||
| throw ("cannot convert unknown token (" + o.kind + ") to JSON\n file = " + sc.fileName + " line = " + sc.lineNumber); | ||
| throw ("cannot convert unknown token (" + o.kind + ") to JSON"); | ||
| } | ||
| return res; | ||
| } | ||
| /** | ||
| * This function converts typescript keywords to JSON schema. | ||
| * | ||
| * @param {string} docRoot The root path in the document object for JSDoc | ||
| * definitions. Used to construct $ref values. | ||
| * @param {string} name The name of the typescript type. | ||
| */ | ||
| function mapTypeDescName(docRoot, name) { | ||
| if (name == "Object") | ||
| return { type: "object" }; | ||
| if (name == "String") | ||
| return { type: "string" }; | ||
| if (name == "Number") | ||
| return { type: "number" }; | ||
| if (name == "Boolean") | ||
| return { type: "boolean" }; | ||
| if (name == "Function") | ||
| return null; | ||
| return { "$ref": docRoot + "/" + name }; | ||
| } | ||
| exports.mapTypeDescName = mapTypeDescName; | ||
| /** | ||
| * Convert a typescript union declaration to JSON schema; this is supported | ||
| * by use of the keyword anyOf. | ||
| * | ||
| * @param {any} typeDesc The AST subtree describing the union type. | ||
| * @param {any} jsDoc A reference to the current JSDoc document. | ||
| * @param {any} options Optional values effecting the output form. Currently | ||
| * serves as a parameter to the recursive call to typeToJSON. | ||
| */ | ||
| function unionToJSON(typeDesc, jsDoc, context) { | ||
| var unionDesc = typeDesc; | ||
| var res = { anyOf: [] }; | ||
| for (var i = 0; i < unionDesc.types.length; i++) { | ||
| var unionElement = typeToJSON(unionDesc.types[i], null, context); | ||
| if (unionElement != null) | ||
| res.anyOf.push(unionElement); | ||
| } | ||
| return res; | ||
| } | ||
| /** | ||
| * Convert a typescript intersection declaration to JSON schema; this is supported | ||
| * by use of the keyword allOf. | ||
| * | ||
| * @param {any} typeDesc The AST subtree describing the intersection type. | ||
| * @param {any} jsDoc A reference to the current JSDoc document. | ||
| * @param {any} options Optional values effecting the output form. Currently | ||
| * serves as a parameter to the recursive call to typeToJSON. | ||
| */ | ||
| function intersectionToJSON(typeDesc, jsDoc, context) { | ||
| var intersectionDesc = typeDesc; | ||
| var res = { allOf: [] }; | ||
| for (var i = 0; i < intersectionDesc.types.length; i++) { | ||
| var intersectionElement = typeToJSON(intersectionDesc.types[i], null, context); | ||
| if (intersectionElement != null) | ||
| res.allOf.push(intersectionElement); | ||
| } | ||
| return res; | ||
| } | ||
| /** | ||
| * Create the JSON schema for a typescript literal type. Literal types | ||
| * can be expressed using the pattern keyword. | ||
| * | ||
| * @param {any} typeDesc The AST subtree describing the literal. | ||
| * @param {any} jsDoc A reference to the current JSDoc document. | ||
| */ | ||
| function literalToJSON(typeDesc, jsDoc) { | ||
| var type = checker.getTypeFromTypeNode(typeDesc); | ||
| if (type.value != null) { | ||
| var valueType = typeof type.value; | ||
| if (valueType == "string") | ||
| return { type: "string", pattern: "^" + type.value + "$" }; | ||
| else if (valueType == "number") { | ||
| var numericValue = parseFloat(type.value); | ||
| return { type: "number", minimum: numericValue, maximum: numericValue }; | ||
| } | ||
| } | ||
| var literal = checker.typeToString(type); | ||
| if (literal == "false" || literal == "true") | ||
| return { type: "boolean" }; | ||
| var sc = getSourceContext(typeDesc); | ||
| if (sc != null) | ||
| throw ("unknown literal type (" + literal + ")\n file = " + sc.fileName + " line = " + sc.lineNumber); | ||
| throw ("unknown literal type (" + literal + ")"); | ||
| } | ||
| function typeliteralToJSON(typeDesc, jsDoc, context) { | ||
| var typeliteralDesc = typeDesc; | ||
| var properties = {}; | ||
| var required = []; | ||
| var elements = []; | ||
| for (var i = 0; i < typeliteralDesc.members.length; i++) { | ||
| var element = typeliteralDesc.members[i]; | ||
| if (element.name != null) { | ||
| var propertyName = tsany.getTextOfNode(element.name); | ||
| properties[propertyName] = typeToJSON(element, null, context); | ||
| if (element.questionToken == null) | ||
| required.push(propertyName); | ||
| } | ||
| else { | ||
| var j = typeToJSON(element, null, context); | ||
| if (j != null) | ||
| elements.push(j); | ||
| } | ||
| } | ||
| if (Object.keys(properties).length > 0 && elements.length == 0) { | ||
| if (context != null && context.options != null && context.options.firstclassIntermediates) { | ||
| var schema = { type: "object", properties: properties }; | ||
| if (required.length > 0) | ||
| schema.required = required; | ||
| var iname = storeIntermediate({ enclosedBy: context.enclosedBy, schema: schema }); | ||
| return { "$ref": context.options.docRoot + "/" + iname }; | ||
| } | ||
| else { | ||
| var schema = { type: "object", properties: properties }; | ||
| if (required.length > 0) | ||
| schema.required = required; | ||
| return schema; | ||
| } | ||
| } | ||
| else if (elements.length != 0 && Object.keys(properties).length == 0) { | ||
| return { anyOf: elements }; | ||
| } | ||
| else if (elements.length == 0 && Object.keys(properties).length == 0) { | ||
| return { type: "object", properties: [] }; | ||
| } | ||
| else { | ||
| var type = checker.getTypeFromTypeNode(typeDesc); | ||
| var literal = checker.typeToString(type); | ||
| var sc = getSourceContext(typeDesc); | ||
| if (sc != null) | ||
| throw ("unable to map typeliteral containing both named and unnamed elements " + literal + "\n file = " + sc.fileName + " line = " + sc.lineNumber); | ||
| throw ("unable to map typeliteral containing both named and unnamed elements " + literal); | ||
| } | ||
| } | ||
| function tupleTypeToJSON(typeDesc, jsDoc, context) { | ||
| var tupleDesc = typeDesc; | ||
| var res = { allOf: [] }; | ||
| for (var i = 0; i < tupleDesc.elementTypes.length; i++) { | ||
| var tupleElement = typeToJSON(tupleDesc.elementTypes[i], null, context); | ||
| if (tupleElement != null) | ||
| res.allOf.push(tupleElement); | ||
| } | ||
| return res; | ||
| } | ||
| function indexedAccessTypeToJSON(typeDesc, jsDoc, context) { | ||
| var iaDesc = typeDesc; | ||
| var indexType = checker.getTypeFromTypeNode(typeDesc.indexType); | ||
| var objectType = checker.getTypeFromTypeNode(typeDesc.objectType); | ||
| var index = checker.typeToString(indexType); | ||
| var objs = checker.typeToString(objectType); | ||
| var res; | ||
| if (index == "ArrayBuffer" && objs == "ArrayBufferTypes") | ||
| return { type: "string", hint: { encoding: "base64" } }; | ||
| return typeToJSON(typeDesc.objectType, jsDoc, context); | ||
| } | ||
| function mappedTypeToJSON(typeDesc, jsDoc, context) { | ||
| var mapDesc = typeDesc; | ||
| var constraint = ts.getEffectiveConstraintOfTypeParameter(mapDesc.typeParameter); | ||
| var res; | ||
| if (typeDesc.nextContainer) { | ||
| //console.log("next: ",typeDesc.nextContainer.type); | ||
| var type = checker.getTypeFromTypeNode(typeDesc.nextContainer.type); | ||
| var types = checker.typeToString(type); | ||
| //console.log("subordinate type: ",types); | ||
| //console.log("constraint: ",constraint); | ||
| //console.log("desc: ",typeDesc); | ||
| return typeToJSON(typeDesc.nextContainer.type, jsDoc, context); | ||
| } | ||
| return {}; | ||
| } | ||
| function conditionalTypeToJSON(typeDesc, jsDoc, context) { | ||
| var conditionalDesc = typeDesc; | ||
| var type = checker.getTypeFromTypeNode(typeDesc); | ||
| ///console.log("conditional type = ",checker.typeToString(type)); | ||
| return typeToJSON(conditionalDesc.extendsType, jsDoc, context); | ||
| } | ||
| /** | ||
| * This function adds the specified value tag to a JSON schema component. | ||
| * | ||
| * @param {any} schemaObject Reference to the schema component. | ||
| * @param {string} title The value attribute name. | ||
| * @param {any} value The value to set. | ||
| */ | ||
| function applyValueTag(schemaObject, title, value) { | ||
| if (schemaObject.type != null && schemaObject.type != "null") | ||
| schemaObject[title] = value; | ||
| else if (schemaObject.oneOf != null) { | ||
| for (var i = 0; i < schemaObject.oneOf.length; i++) { | ||
| if (schemaObject.oneOf[i].type != null && schemaObject.oneOf[i].type != "null") | ||
| schemaObject.oneOf[i][title] = value; | ||
| } | ||
| } | ||
| } | ||
| /** | ||
| * This function adds typing infomation to the speficied JSON schema component. | ||
| * | ||
| * @param {any} schemaObject Reference to the schema component. | ||
| * @param {string} name The typename. | ||
| */ | ||
| function applyTypenameTag(schemaObject, name) { | ||
| if (schemaObject.type != null && schemaObject.type != "null") | ||
| schemaObject.type = name; | ||
| else if (schemaObject.oneOf != null) { | ||
| for (var i = 0; i < schemaObject.oneOf.length; i++) { | ||
| if (schemaObject.oneOf[i].type != null && schemaObject.oneOf[i].type != "null") | ||
| schemaObject.oneOf[i].type = name; | ||
| } | ||
| } | ||
| } | ||
| /** | ||
| * This function adds a tag to a JSON schema component. The type of tag to apply | ||
| * is inferred from the contents of the tag. If the tag is not applicable to the | ||
| * type, then an error is raised. If the type is an array, the elemement type | ||
| * is used where applicable. | ||
| * | ||
| * @param {any} schemaObject Reference to the schema component. | ||
| * @param {any} tag The tag to apply. | ||
| */ | ||
| function applyTag(schemaObject, tag) { | ||
| if (tag == null) | ||
| return; | ||
| if (tag.title == "minimum" || tag.title == "maximum") { | ||
| if (schemaObject.type == "array") | ||
| applyTag(schemaObject.items, tag); | ||
| else if (schemaObject.type != "number") | ||
| throw ("@" + tag.title + " can only be applied to numbers"); | ||
| applyValueTag(schemaObject, tag.title, parseInt(tag.description)); | ||
| } | ||
| else if (tag.title == "minLength" || tag.title == "maxLength") { | ||
| if (schemaObject.type == "array") | ||
| applyTag(schemaObject.items, tag); | ||
| else if (schemaObject.type != "string") | ||
| throw ("@" + tag.title + " can only be applied to strings"); | ||
| applyValueTag(schemaObject, tag.title, parseInt(tag.description)); | ||
| } | ||
| else if (tag.title == "minItems" || tag.title == "maxItems") { | ||
| if (schemaObject.type != "array") | ||
| throw ("@" + tag.title + " can only be applied to arrays"); | ||
| applyValueTag(schemaObject, tag.title, parseInt(tag.description)); | ||
| } | ||
| else if (tag.title == "format" || tag.title == "pattern") { | ||
| if (schemaObject.type == "array") | ||
| applyTag(schemaObject.items, tag); | ||
| else if (schemaObject.type != "string") | ||
| throw ("@format can only be applied to strings"); | ||
| var value = tag.description.replace(/^{(.*)}$/, "$1"); | ||
| applyValueTag(schemaObject, tag.title, value); | ||
| } | ||
| else if (tag.title == "precision") { | ||
| if (schemaObject.type == "array") | ||
| applyTag(schemaObject.items, tag); | ||
| else if (schemaObject.type != "number") | ||
| throw ("@" + tag.title + " can only be applied to numbers"); | ||
| schemaObject.precision = parseInt(tag.description); | ||
| } | ||
| else if (tag.title == "type") { | ||
| if (schemaObject.type == "array") | ||
| applyTag(schemaObject.items, tag); | ||
| else if (tag.type.type == "NameExpression") | ||
| applyTypenameTag(schemaObject, tag.type.name); | ||
| } | ||
| } | ||
| function isTypeNode(desc) { | ||
| try { | ||
| desc.getSourceFile(); | ||
| return ts.isTypeNode(desc); | ||
| } | ||
| catch (e) { | ||
| return false; | ||
| } | ||
| } | ||
| function getIndex(desc) { | ||
| if (desc == null) | ||
| return null; | ||
| var FQN; | ||
| var index; | ||
| if (isTypeNode(desc)) { | ||
| var typeName = desc.typeName; | ||
| try { | ||
| var symbol1 = checker.getSymbolAtLocation(typeName); | ||
| var symbol2 = void 0; | ||
| try { | ||
| symbol2 = checker.getAliasedSymbol(symbol1); | ||
| } | ||
| catch (e) { } | ||
| var local = tsany.getTextOfNode(typeName); | ||
| index = local; | ||
| if (symbol2 == null) | ||
| FQN = checker.getFullyQualifiedName(symbol1); | ||
| else | ||
| FQN = checker.getFullyQualifiedName(symbol2); | ||
| } | ||
| catch (e) { | ||
| if (typeName == null) | ||
| return null; | ||
| var type = checker.getTypeFromTypeNode(desc); | ||
| var symbol1 = desc.typeName.symbol; | ||
| var symbol2 = void 0; | ||
| try { | ||
| symbol2 = checker.getAliasedSymbol(symbol1); | ||
| } | ||
| catch (e) { } | ||
| if (symbol2 == null) | ||
| FQN = checker.getFullyQualifiedName(symbol1); | ||
| else | ||
| FQN = checker.getFullyQualifiedName(symbol2); | ||
| } | ||
| } | ||
| else { | ||
| var symbol2 = void 0; | ||
| try { | ||
| symbol2 = checker.getAliasedSymbol(desc); | ||
| } | ||
| catch (e) { } | ||
| if (symbol2 == null) | ||
| FQN = checker.getFullyQualifiedName(desc); | ||
| else | ||
| FQN = checker.getFullyQualifiedName(symbol2); | ||
| } | ||
| if (FQN != "__type") { | ||
| var components = FQN.split('"'); | ||
| if (components.length == 1) | ||
| index = components[0]; | ||
| else | ||
| index = { module: components[1], local: components[2].substring(1) }; | ||
| } | ||
| return index; | ||
| } | ||
| exports.getIndex = getIndex; | ||
| /** | ||
| * This function is the main entry point for converting a AST subtree describing a | ||
| * type declaration to its analogous JSON schema definition. Some typescript features | ||
| * are not mappable currently (e.g. functions), while some are simply not implemented | ||
| * yet. The typescript parser also collects JSDoc style comments associated with a | ||
| * type declaration and exposes that information in the AST as well. These comments | ||
| * are also part of the output JSON schema. The context of the use of the JSON schema | ||
| * can also effect the structure of the schema (e.g. use references to another part of | ||
| * the containing document, or expand fully all references). Such infomation is passed | ||
| * using options. | ||
| * | ||
| * @param {any} typeDesc Reference to the AST substree describing the type for which to | ||
| * create the JSON schema. | ||
| * @param {any} jsDoc The associated JSDoc comment. | ||
| * @param {any} options Affects the rules governing the structure of the resulting schema. | ||
| */ | ||
| function typeToJSON(typeDesc, jsDoc, context) { | ||
| var res; | ||
| var type = checker.getTypeFromTypeNode(typeDesc); | ||
| if (context != null && context.options == null) | ||
| context = { options: context }; | ||
| if (typeDesc == null) | ||
| return { type: "object" }; | ||
| if (typeDesc.constructor.name == 'NodeObject') { | ||
| var unknown = false; | ||
| var docRoot = "#/definitions"; | ||
| var schemaNamespace = "check"; | ||
| if (context != null && context.options != null && context.options.docRoot != null) | ||
| docRoot = context.options.docRoot; | ||
| if (context != null && context.options != null && context.options.schemaNamespace != null) | ||
| schemaNamespace = context.options.schemaNamespace; | ||
| switch (typeDesc.kind) { | ||
| case ts.SyntaxKind.ArrayType: | ||
| res = { type: "array", items: typeToJSON(typeDesc.elementType, null, context) }; | ||
| break; | ||
| case ts.SyntaxKind.TypeReference: | ||
| { | ||
| var index = getIndex(typeDesc); | ||
| if (index == "Array") { | ||
| var arg = typeDesc.typeArguments[0]; | ||
| res = { type: "array", items: typeToJSON(arg, jsDoc, context) }; | ||
| } | ||
| else if (index == "Date") { | ||
| res = { oneOf: [{ type: "string", format: "date" }, { type: "string", format: "date-time" }], toDate: true, content: "flat" }; | ||
| } | ||
| else { | ||
| var name_1 = index; | ||
| if (typeof name_1 != "string") { | ||
| var sentry = symtabGet(index); | ||
| if (sentry != null) | ||
| name_1 = sentry.schemaRefId; | ||
| else | ||
| name_1 = null; | ||
| } | ||
| res = mapTypeDescName(docRoot, name_1); | ||
| if (res != null && res['$ref'] != null && context != null && context.options != null && context.options.expandRefs) { | ||
| var sentry = symtabGet(index); | ||
| if (sentry == null) { | ||
| var sc = getSourceContext(typeDesc); | ||
| if (sc != null) { | ||
| var _a = null; | ||
| console.log(_a.b); | ||
| throw ("undefined type reference " + index + "\n file = " + sc.fileName + " line = " + sc.lineNumber); | ||
| } | ||
| throw ("undefined type reference " + index); | ||
| } | ||
| res = sentry.schema[schemaNamespace]; | ||
| } | ||
| } | ||
| } | ||
| break; | ||
| case ts.SyntaxKind.PropertySignature: | ||
| { | ||
| var propertySignatureDesc = typeDesc; | ||
| if (propertySignatureDesc.type != null) | ||
| res = typeToJSON(propertySignatureDesc.type, jsDoc, context); | ||
| else | ||
| res = null; | ||
| } | ||
| break; | ||
| case ts.SyntaxKind.CallSignature: /* console.log(`ignoring call signature type ${checker.typeToString(type)}`); */ break; | ||
| case ts.SyntaxKind.MethodSignature: /* console.log(`ignoring method signature type ${checker.typeToString(type)}`); */ break; | ||
| case ts.SyntaxKind.FunctionType: /* console.log(`ignoring function type ${checker.typeToString(type)}`); */ break; | ||
| case ts.SyntaxKind.ConstructorType: /* console.log(`ignoring constructor type ${checker.typeToString(type)}`); */ break; | ||
| case ts.SyntaxKind.TypeQuery: /* console.log(`ignoring type query ${checker.typeToString(type)}`); */ break; | ||
| case ts.SyntaxKind.ParenthesizedType: /* console.log(`ignoring paranthesized type ${checker.typeToString(type)}`); */ break; | ||
| case ts.SyntaxKind.IndexSignature: /* console.log(`ignoring index signature ${checker.typeToString(type)}`); */ break; | ||
| case ts.SyntaxKind.TypeOperator: /* console.log(`ignoring type operator ${checker.typeToString(type)}`); */ break; | ||
| case ts.SyntaxKind.UnionType: | ||
| res = unionToJSON(typeDesc, jsDoc, context); | ||
| break; | ||
| case ts.SyntaxKind.LiteralType: | ||
| res = literalToJSON(typeDesc, jsDoc); | ||
| break; | ||
| case ts.SyntaxKind.IntersectionType: | ||
| res = intersectionToJSON(typeDesc, jsDoc, context); | ||
| break; | ||
| case ts.SyntaxKind.ConditionalType: | ||
| res = conditionalTypeToJSON(typeDesc, jsDoc, context); | ||
| break; | ||
| case ts.SyntaxKind.TypeLiteral: | ||
| res = typeliteralToJSON(typeDesc, jsDoc, context); | ||
| break; | ||
| case ts.SyntaxKind.MappedType: | ||
| res = mappedTypeToJSON(typeDesc, jsDoc, context); | ||
| break; | ||
| case ts.SyntaxKind.TupleType: | ||
| res = tupleTypeToJSON(typeDesc, jsDoc, context); | ||
| break; | ||
| case ts.SyntaxKind.IndexedAccessType: | ||
| res = indexedAccessTypeToJSON(typeDesc, jsDoc, context); | ||
| break; | ||
| default: | ||
| unknown = true; | ||
| break; | ||
| } | ||
| if (unknown) { | ||
| var sc = getSourceContext(typeDesc); | ||
| if (sc != null) { | ||
| /* Useful to debug never before seen types, usually not interesting enough to leave it in for users | ||
| let uType = checker.getTypeFromTypeNode(typeDesc); | ||
| let typeText = checker.typeToString(uType); | ||
| console.log(typeText); | ||
| */ | ||
| throw ("cannot convert unknown type (" + typeDesc.kind + ") to JSON\n file = " + sc.fileName + " line = " + sc.lineNumber); | ||
| } | ||
| throw ("cannot convert unknown type (" + typeDesc.kind + ") to JSON"); | ||
| } | ||
| } | ||
| else if (typeDesc.constructor.name == 'TokenObject') | ||
| res = tokenObjectToJSON(typeDesc, jsDoc); | ||
| else { | ||
| var sc = getSourceContext(typeDesc); | ||
| if (sc != null) | ||
| throw ("unknown type (" + typeDesc.constructor.name + ")\n file = " + sc.fileName + " line = " + sc.lineNumber); | ||
| throw ("unknown type (" + typeDesc.constructor.name + ")"); | ||
| } | ||
| if (res) { | ||
| var symbol = type.symbol; | ||
| if (jsDoc != null && jsDoc.length != 0) { | ||
| for (var i = 0; i < jsDoc.length; i++) { | ||
| if (jsDoc[i].tags != null && jsDoc[i].tags.length != 0) { | ||
| for (var j = 0; j < jsDoc[i].tags.length; j++) | ||
| applyTag(res, jsDoc[i].tags[j]); | ||
| } | ||
| } | ||
| } | ||
| if (symbol) | ||
| res.description = ts.displayPartsToString(symbol.getDocumentationComment(checker)); | ||
| } | ||
| return res; | ||
| } | ||
| exports.typeToJSON = typeToJSON; | ||
| //# sourceMappingURL=symtab.js.map |
| {"version":3,"file":"symtab.js","sourceRoot":"","sources":["../../src/analyzer/symtab.ts"],"names":[],"mappings":"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"} |
| import { TypedId, PathDecomposition, DecoratedFunction, Controller, Router } from "./types"; | ||
| export declare function synthesizeParameterJSDoc(parm: TypedId): any; | ||
| export declare function findRelevant(method: DecoratedFunction, options?: any): void; | ||
| /** | ||
| * This function constructs the JSON schema corresponding to the method parameter | ||
| * list. This is accomplished by contstructing the schema corresponding to a virtual | ||
| * aggregate type whose members are each a parameter to the method. To apply a JSON | ||
| * schema type checker is a matter of contructing an intermediate form corresponding | ||
| * to that virtual type -- this is done by the generated function argsToSchema found | ||
| * in __check.js. Each parameter type is marked to include in the reference schema | ||
| * definitions. | ||
| * | ||
| * @param {DecoratedFunction} method the definition of the method having the parameter | ||
| * list for which the schema is to be contstructed. | ||
| * @param {any} options affects the rules for schema creation. | ||
| * | ||
| */ | ||
| export declare function parameterListToJSON(method: DecoratedFunction, options?: any): Object; | ||
| /** | ||
| * This function loops over the parameter list of a method and returns an array of | ||
| * parameter describing interface objects. | ||
| * | ||
| * @param {any} parms The AST subtree describing the parameter list. | ||
| */ | ||
| export declare function traverseParameterList(parms: any, decoratorMeta: any): TypedId[]; | ||
| /** | ||
| * This function is called after the first pass of the AST is completed. It augments | ||
| * the classes found in the global symbol table that was constructed in part in pass 1 | ||
| * and annotated by @controller with the methods that belong to that class. | ||
| * | ||
| * @param {DecoratedFunction[]} endpoints an array of all of the relevant annotated | ||
| * methods. | ||
| */ | ||
| export declare function connectMethods(endpoints: DecoratedFunction[]): void; | ||
| export declare function isExplicitStatus(index: any): boolean; | ||
| export declare function isFileReturn(index: any): boolean; | ||
| /** | ||
| * This function creates the JSON schema reference document that corresponds to | ||
| * all marked (relevant) types defined in the global symbol table created from the | ||
| * traversal of the AST of the typescript sources. | ||
| * | ||
| */ | ||
| export declare function symtabToSchemaDefinitions(schemaNamespace: string, docRoot: string, expandOptions?: any): Object; | ||
| /** | ||
| * Detects a url param variable in a path, returns metadata of the path. | ||
| * | ||
| * @param path {string} the path of a URL associated decorator (router,controller,method). | ||
| */ | ||
| export declare function decomposePath(path: string): PathDecomposition; | ||
| /** | ||
| * Compiles the list of controller definitions by iterating over | ||
| * the global pass 1 typescript source symbol table and creating a record | ||
| * for each entry marked with type "controller". | ||
| */ | ||
| export declare function symtabToControllerDefinitions(): Controller[]; | ||
| /** | ||
| * Like above, compiles the list of router definitions by iterating over | ||
| * the global pass 1 typescript source symbol table and creating a record | ||
| * for each entry marked with type "router". | ||
| */ | ||
| export declare function symtabToRouterDefinitions(): Router[]; | ||
| export declare function isURLParam(id: string, router: Router, controller: Controller, methodPathDecomposition: PathDecomposition): boolean; | ||
| /** | ||
| * Generates a member of the check object for a method. Each entry contains a reference | ||
| * JSON schema labeled 'schema', the function argsToSchema which creates the arguments | ||
| * to the checker, and validate which is the validator. Each entry in indexed by the | ||
| * unique combination of className.methodName. | ||
| * | ||
| * @param className Name of the (controller) class. | ||
| * @param methodName Name of the method. | ||
| * @param parameterNames list of each formal parameter to the method. | ||
| * @param schema the JSON schema of all of the relevant type definitions. | ||
| */ | ||
| export declare function genMethodEntry(classRef: any, methodName: any, parameterNames: any, schema: any, passthrough: boolean): string; | ||
| /** | ||
| * Adds an entry for a controller to the global typescript source symbol table. | ||
| * | ||
| * @param {string} className the name of the class annotated by @controller. | ||
| * @param {string} fileName the name of the file containing the controller definition. | ||
| * @param {string} comment a JSDoc type comment of the controller. | ||
| */ | ||
| export declare function addController(index: any, fileName: string, comment: string): void; | ||
| /** | ||
| * Adds an entry for a router to the global typescript source symbol table. | ||
| * | ||
| * @param {string} className the name of the class annotated by @router. | ||
| * @param {string} fileName the name of the file containing the router definition. | ||
| * @param {string} comment a JSDoc type comment of the router. | ||
| */ | ||
| export declare function addRouter(index: any, fileName: string, comment: string): void; | ||
| /** | ||
| * Output a path of appropriate type-style by concetenating the components some of which | ||
| * might also be urlParam type components. | ||
| * | ||
| * @param decomposition {PathDecomposition} The decomposed form of a path -- broken down into components. | ||
| & @param pathType: Either swagger or express | ||
| */ | ||
| export declare function decompositionToPath(decomposition: PathDecomposition, pathType: "swagger" | "express"): string; |
| "use strict"; | ||
| Object.defineProperty(exports, "__esModule", { value: true }); | ||
| var ts = require("typescript"); | ||
| var doctrine = require("doctrine"); | ||
| var tsany = ts; | ||
| var symtab_1 = require("./symtab"); | ||
| /** | ||
| * This function marks all component types of a union type that is relevant as also relevant. | ||
| * | ||
| * @param {any} typeDesc Reference to the AST substree describing the type. | ||
| * @param {any} jsDoc The associated JSDoc comment. | ||
| * @param {any} options Affects the rules governing the recursion. | ||
| */ | ||
| function markUnionAsRelevant(typeDesc, jsDoc, options) { | ||
| var unionDesc = typeDesc; | ||
| for (var i = 0; i < unionDesc.types.length; i++) | ||
| markAsRelevant(unionDesc.types[i], null, options); | ||
| } | ||
| /** | ||
| * This function marks all component types of an intersection type that is relevant as also relevant. | ||
| * | ||
| * @param {any} typeDesc Reference to the AST substree describing the type. | ||
| * @param {any} jsDoc The associated JSDoc comment. | ||
| * @param {any} options Affects the rules governing the recursion. | ||
| */ | ||
| function markIntersectionAsRelevant(typeDesc, jsDoc, options) { | ||
| var intersectionDesc = typeDesc; | ||
| for (var i = 0; i < intersectionDesc.types.length; i++) | ||
| markAsRelevant(intersectionDesc.types[i], null, options); | ||
| } | ||
| /** | ||
| * This function marks a type as relevant. The purpose of marking a type relevant is to | ||
| * reduce the number of elements that appear in a describing document. Otherwise not only would | ||
| * al declared types by output, so too would all typescript built-in types which would lead | ||
| * to an unnecessarily enormous document. The expectation is that any class that is annotated | ||
| * with a decorator relevant to this project and any type used in a method that is likewise | ||
| * decorated as well as all of the types that help define those aformentioned types would be | ||
| * relevant in this way. Thus this function is call for those types and then recursively | ||
| * calls itself for an component types. | ||
| * | ||
| * @param {any} typeDesc Reference to the AST substree describing the type. | ||
| * @param {any} jsDoc The associated JSDoc comment. | ||
| * @param {any} options Affects the rules governing the recursion. | ||
| */ | ||
| function markAsRelevant(typeDesc, jsDoc, options) { | ||
| if (typeDesc.constructor.name == 'NodeObject') { | ||
| switch (typeDesc.kind) { | ||
| case ts.SyntaxKind.ArrayType: | ||
| markAsRelevant(typeDesc.elementType, jsDoc, options); | ||
| break; | ||
| case ts.SyntaxKind.TypeReference: | ||
| { | ||
| var alias = typeDesc; | ||
| var index = symtab_1.getIndex(typeDesc); | ||
| var args = typeDesc.typeArguments; | ||
| var ref = symtab_1.symtabGet(index); | ||
| if (ref == null) { | ||
| throw ("undefined type " + index + " in relevancy tree"); | ||
| } | ||
| ref.relevant = true; | ||
| if (args != null) { | ||
| for (var i = 0; i < args.length; i++) | ||
| markAsRelevant(args[i], jsDoc, options); | ||
| } | ||
| for (var key in ref.members) { | ||
| markAsRelevant(ref.members[key].type, jsDoc, options); | ||
| } | ||
| if (ref.decl != null && ref.decl.type != null) | ||
| markAsRelevant(ref.decl.type, jsDoc, options); | ||
| if (ref.inherits != null) { | ||
| for (var i = 0; i < ref.inherits.length; i++) { | ||
| var baseEntry = symtab_1.symtabGet(ref.inherits[i]); | ||
| markAsRelevant(baseEntry.typeDesc, baseEntry.jsDoc, baseEntry.options); | ||
| } | ||
| } | ||
| } | ||
| break; | ||
| case ts.SyntaxKind.UnionType: | ||
| markUnionAsRelevant(typeDesc, jsDoc, options); | ||
| break; | ||
| case ts.SyntaxKind.IntersectionType: | ||
| markIntersectionAsRelevant(typeDesc, jsDoc, options); | ||
| break; | ||
| default: break; | ||
| } | ||
| } | ||
| } | ||
| function synthesizeParameterJSDoc(parm) { | ||
| var jsDoc; | ||
| var jsDocSrc = []; | ||
| var type1 = ["format", "pattern", "type"]; | ||
| var type2 = ["minimum", "maximum", "minLength", "maxLength", "minItems", "maxItems", "precision"]; | ||
| if (parm.decorators != null) { | ||
| for (var decoratorName in parm.decorators) { | ||
| if (type1.indexOf(decoratorName) > -1 && parm.decorators[decoratorName].length >= 1) { | ||
| if (jsDocSrc.length == 0) | ||
| jsDocSrc.push('/**'); | ||
| jsDocSrc.push(" * @" + decoratorName + " {" + parm.decorators[decoratorName][0] + "}"); | ||
| } | ||
| else if (type2.indexOf(decoratorName) > -1 && parm.decorators[decoratorName].length >= 1) { | ||
| if (jsDocSrc.length == 0) | ||
| jsDocSrc.push('/**'); | ||
| jsDocSrc.push(" * @" + decoratorName + " " + parm.decorators[decoratorName][0]); | ||
| } | ||
| } | ||
| if (jsDocSrc.length != 0) { | ||
| jsDocSrc.push(" */"); | ||
| jsDoc = doctrine.parse(jsDocSrc.join('\n'), { unwrap: true }); | ||
| if (jsDoc != null) | ||
| jsDoc = [jsDoc]; | ||
| } | ||
| } | ||
| return jsDoc; | ||
| } | ||
| exports.synthesizeParameterJSDoc = synthesizeParameterJSDoc; | ||
| function findRelevant(method, options) { | ||
| markAsRelevant(method.returnType, null, options); | ||
| for (var i = 0; i < method.methodParameters.length; i++) { | ||
| var x = symtab_1.typeToJSON(method.methodParameters[i].type, null, options); | ||
| if (x != null) | ||
| markAsRelevant(method.methodParameters[i].type, null, options); | ||
| } | ||
| } | ||
| exports.findRelevant = findRelevant; | ||
| /** | ||
| * This function constructs the JSON schema corresponding to the method parameter | ||
| * list. This is accomplished by contstructing the schema corresponding to a virtual | ||
| * aggregate type whose members are each a parameter to the method. To apply a JSON | ||
| * schema type checker is a matter of contructing an intermediate form corresponding | ||
| * to that virtual type -- this is done by the generated function argsToSchema found | ||
| * in __check.js. Each parameter type is marked to include in the reference schema | ||
| * definitions. | ||
| * | ||
| * @param {DecoratedFunction} method the definition of the method having the parameter | ||
| * list for which the schema is to be contstructed. | ||
| * @param {any} options affects the rules for schema creation. | ||
| * | ||
| */ | ||
| function parameterListToJSON(method, options) { | ||
| var props = {}; | ||
| var parameterNames = []; | ||
| var required = []; | ||
| var passthrough = false; | ||
| if (method.methodParameters.length == 1) { | ||
| var jsDoc = synthesizeParameterJSDoc(method.methodParameters[0]); | ||
| var jsonValue = symtab_1.typeToJSON(method.methodParameters[0].type, jsDoc, options); | ||
| if (jsonValue) { | ||
| var augmentedOptions = { expandRefs: true }; | ||
| for (var key in options) { | ||
| if (key != "expandRefs") | ||
| augmentedOptions = options[key]; | ||
| } | ||
| jsonValue = symtab_1.typeToJSON(method.methodParameters[0].type, jsDoc, augmentedOptions); | ||
| if (jsonValue.type == "object") { | ||
| for (var p in jsonValue.properties) { | ||
| props[p] = jsonValue.properties[p]; | ||
| parameterNames.push(p); | ||
| } | ||
| required = jsonValue.required; | ||
| passthrough = true; | ||
| } | ||
| else { | ||
| var parameterName = method.methodParameters[0].id; | ||
| props[parameterName] = jsonValue; | ||
| parameterNames.push(parameterName); | ||
| if (parameterName) | ||
| required.push(parameterName); | ||
| } | ||
| } | ||
| } | ||
| else { | ||
| for (var i = 0; i < method.methodParameters.length; i++) { | ||
| var jsDoc = synthesizeParameterJSDoc(method.methodParameters[i]); | ||
| var jsonValue = symtab_1.typeToJSON(method.methodParameters[i].type, jsDoc, options); | ||
| if (jsonValue) | ||
| props[method.methodParameters[i].id] = jsonValue; | ||
| } | ||
| for (var i = 0; i < method.methodParameters.length; i++) { | ||
| var parameterName = method.methodParameters[i].id; | ||
| parameterNames.push(parameterName); | ||
| if (method.methodParameters[i].required) | ||
| required.push(parameterName); | ||
| } | ||
| } | ||
| var res = { | ||
| classRef: "" + method.classRef, | ||
| method: "" + method.name, | ||
| parameterNames: parameterNames, | ||
| passthrough: passthrough, | ||
| schema: { | ||
| title: method.name + " plist", | ||
| description: "Parameter list for " + method.name, | ||
| type: "object", | ||
| properties: props | ||
| } | ||
| }; | ||
| if (required != null && required.length > 0) | ||
| res.required = required; | ||
| return res; | ||
| } | ||
| exports.parameterListToJSON = parameterListToJSON; | ||
| /** | ||
| * This function loops over the parameter list of a method and returns an array of | ||
| * parameter describing interface objects. | ||
| * | ||
| * @param {any} parms The AST subtree describing the parameter list. | ||
| */ | ||
| function traverseParameterList(parms, decoratorMeta) { | ||
| var parameterList = []; | ||
| for (var i = 0; i < parms.length; i++) { | ||
| var required = true; | ||
| if (parms[i].questionToken != null) | ||
| required = false; | ||
| parameterList.push({ id: parms[i].name.text, type: parms[i].type, decorators: decoratorMeta[parms[i].name.text], required: required }); | ||
| } | ||
| return parameterList; | ||
| } | ||
| exports.traverseParameterList = traverseParameterList; | ||
| /** | ||
| * This function is called after the first pass of the AST is completed. It augments | ||
| * the classes found in the global symbol table that was constructed in part in pass 1 | ||
| * and annotated by @controller with the methods that belong to that class. | ||
| * | ||
| * @param {DecoratedFunction[]} endpoints an array of all of the relevant annotated | ||
| * methods. | ||
| */ | ||
| function connectMethods(endpoints) { | ||
| for (var i = 0; i < endpoints.length; i++) { | ||
| if (endpoints[i].index != null) { | ||
| var controller = symtab_1.symtabGet(endpoints[i].index); | ||
| if (controller != null) { | ||
| if (controller.methods != null) | ||
| controller.methods.push(endpoints[i]); | ||
| else | ||
| console.log("Ignoring endpoint " + endpoints[i].name + " of " + endpoints[i].classRef); | ||
| } | ||
| } | ||
| } | ||
| } | ||
| exports.connectMethods = connectMethods; | ||
| function isMagic(typeDesc) { | ||
| if (typeDesc == null) | ||
| return false; | ||
| var typeName = typeDesc.name.text; | ||
| if (typeName == "Res" || typeName == "FileRef") | ||
| return true; | ||
| var isUnion = typeDesc.kind == ts.SyntaxKind.UnionType; | ||
| if (!isUnion && typeDesc.kind == ts.SyntaxKind.TypeAliasDeclaration) { | ||
| while (typeDesc.kind == ts.SyntaxKind.TypeAliasDeclaration) { | ||
| var componentDesc = symtab_1.symtabGet(typeName); | ||
| if (componentDesc == null) | ||
| break; | ||
| var alias = componentDesc.decl; | ||
| if (alias.type != null) { | ||
| typeDesc = alias.type; | ||
| isUnion = alias.type.kind == ts.SyntaxKind.UnionType; | ||
| } | ||
| else | ||
| break; | ||
| if (isUnion) | ||
| break; | ||
| var typename = symtab_1.getIndex(typeDesc); | ||
| if (isExplicitStatus(typename)) | ||
| return true; | ||
| } | ||
| } | ||
| if (!isUnion) | ||
| return false; | ||
| var unionDesc = typeDesc; | ||
| var isMultiStatus = false; | ||
| for (var i = 0; i < unionDesc.types.length; i++) { | ||
| var unionElementTypename = symtab_1.getIndex(unionDesc.types[i]); | ||
| if (unionElementTypename != null && isExplicitStatus(unionElementTypename)) | ||
| return true; | ||
| } | ||
| return false; | ||
| } | ||
| function isExplicitStatus(index) { | ||
| if (index == null) | ||
| return false; | ||
| if (typeof index == "string") | ||
| return index == "Res"; | ||
| else if (index.local == "Res" && index.module.match(/.*ts-api.*/)) | ||
| return true; | ||
| return false; | ||
| } | ||
| exports.isExplicitStatus = isExplicitStatus; | ||
| function isFileReturn(index) { | ||
| if (index == null) | ||
| return false; | ||
| if (typeof index == "string") | ||
| return index == "FileRef"; | ||
| else if (index.local == "FileRef" && index.module.match(/.*ts-api.*/)) | ||
| return true; | ||
| return false; | ||
| } | ||
| exports.isFileReturn = isFileReturn; | ||
| /** | ||
| * This function creates the JSON schema reference document that corresponds to | ||
| * all marked (relevant) types defined in the global symbol table created from the | ||
| * traversal of the AST of the typescript sources. | ||
| * | ||
| */ | ||
| function symtabToSchemaDefinitions(schemaNamespace, docRoot, expandOptions) { | ||
| var res = {}; | ||
| for (var skey in symtab_1.symtab) { | ||
| var sentry = symtab_1.symtab[skey]; | ||
| if (sentry.kind == "type" && sentry.relevant) { | ||
| var required = []; | ||
| var decl = sentry.decl; | ||
| if (!isMagic(decl)) { | ||
| var schemaRefId = sentry.schemaRefId; | ||
| var allOf = void 0; | ||
| if (decl.kind == ts.SyntaxKind.InterfaceDeclaration || decl.kind == ts.SyntaxKind.ClassDeclaration) { | ||
| res[schemaRefId] = { type: "object", properties: {} }; | ||
| for (var mkey in sentry.members) { | ||
| res[schemaRefId].properties[mkey] = sentry.members[mkey].desc[schemaNamespace]; | ||
| if (!sentry.members[mkey].optional) | ||
| required.push(mkey); | ||
| } | ||
| if (sentry.inherits != null && sentry.inherits.length > 0) { | ||
| allOf = []; | ||
| for (var i = 0; i < sentry.inherits.length; i++) { | ||
| var hindex = sentry.inherits[i]; | ||
| var hentry = symtab_1.symtabGet(hindex); | ||
| allOf.push(symtab_1.mapTypeDescName(docRoot, hentry.schemaRefId)); | ||
| } | ||
| } | ||
| } | ||
| else if (decl.type != null) { | ||
| var options = { schemaNamespace: schemaNamespace, docRoot: docRoot }; | ||
| for (var option in expandOptions) | ||
| options[option] = expandOptions[option]; | ||
| res[schemaRefId] = symtab_1.typeToJSON(decl.type, sentry.jsDoc, { enclosedBy: skey, options: options }); | ||
| } | ||
| if (required.length > 0) | ||
| res[schemaRefId].required = required; | ||
| if (sentry.comment != null) | ||
| res[schemaRefId].description = sentry.comment; | ||
| if (sentry.schema == null) | ||
| sentry.schema = {}; | ||
| if (allOf != null) { | ||
| allOf.push(res[schemaRefId]); | ||
| res[schemaRefId] = { allOf: allOf }; | ||
| } | ||
| sentry.schema[schemaNamespace] = res[schemaRefId]; | ||
| } | ||
| } | ||
| } | ||
| // Now traverse again, and this time look for the itypes, all the processing has been | ||
| // done in the previous traversal, so just output the generated def. | ||
| if (expandOptions != null && expandOptions.firstclassIntermediates) { | ||
| for (var skey in symtab_1.symtab) { | ||
| var sentry = symtab_1.symtab[skey]; | ||
| if (sentry.kind == "itype") { | ||
| var esentry = symtab_1.symtabGet(sentry.enclosedBy); | ||
| if (esentry != null && esentry.relevant) { | ||
| var schemaRefId = sentry.schemaRefId; | ||
| res[schemaRefId] = sentry.schema; | ||
| } | ||
| } | ||
| } | ||
| } | ||
| return res; | ||
| } | ||
| exports.symtabToSchemaDefinitions = symtabToSchemaDefinitions; | ||
| /** | ||
| * Detects a url param variable in a path, returns metadata of the path. | ||
| * | ||
| * @param path {string} the path of a URL associated decorator (router,controller,method). | ||
| */ | ||
| function decomposePath(path) { | ||
| var delimited = path.split('/'); | ||
| var urlParams = {}; | ||
| var pathComponents = []; | ||
| for (var i = 0; i < delimited.length; i++) { | ||
| if (delimited[i] != '') { | ||
| if (delimited[i].match(/:.*/)) { | ||
| var base = delimited[i].replace(/:/g, ""); | ||
| pathComponents.push(base); | ||
| urlParams[base] = true; | ||
| } | ||
| else | ||
| pathComponents.push(delimited[i]); | ||
| } | ||
| } | ||
| return { pathComponents: pathComponents, urlParams: urlParams }; | ||
| } | ||
| exports.decomposePath = decomposePath; | ||
| /** | ||
| * Compiles the list of controller definitions by iterating over | ||
| * the global pass 1 typescript source symbol table and creating a record | ||
| * for each entry marked with type "controller". | ||
| */ | ||
| function symtabToControllerDefinitions() { | ||
| var res = []; | ||
| for (var skey in symtab_1.symtab) { | ||
| var sentry = symtab_1.symtab[skey]; | ||
| if (sentry.kind == "controller") { | ||
| var classRef = sentry.schemaRefId; | ||
| var path_1 = classRef; | ||
| var comment = sentry.comment; | ||
| var fileName = sentry.fileName; | ||
| if (sentry.args != null && sentry.args[0] != null) | ||
| path_1 = sentry.args[0]; | ||
| res.push({ | ||
| args: sentry.args, | ||
| classRef: classRef, | ||
| comment: comment, | ||
| fileName: fileName, | ||
| methods: sentry.methods, | ||
| decomposition: decomposePath(path_1) | ||
| }); | ||
| } | ||
| } | ||
| return res; | ||
| } | ||
| exports.symtabToControllerDefinitions = symtabToControllerDefinitions; | ||
| /** | ||
| * Like above, compiles the list of router definitions by iterating over | ||
| * the global pass 1 typescript source symbol table and creating a record | ||
| * for each entry marked with type "router". | ||
| */ | ||
| function symtabToRouterDefinitions() { | ||
| var res = []; | ||
| for (var skey in symtab_1.symtab) { | ||
| var sentry = symtab_1.symtab[skey]; | ||
| if (sentry.kind == "router") { | ||
| var className = sentry.schemaRefId; | ||
| var path_2 = className; | ||
| var comment = sentry.comment; | ||
| var fileName = sentry.fileName; | ||
| if (sentry.args != null && sentry.args[0] != null) | ||
| path_2 = sentry.args[0]; | ||
| var pathComponents = path_2.split('/'); | ||
| var urlParams = []; | ||
| for (var i = 0; i < pathComponents.length; i++) { | ||
| if (pathComponents[i].match(/:.*/)) | ||
| urlParams.push(pathComponents[i].replace(/:/g, "")); | ||
| } | ||
| res.push({ | ||
| args: sentry.args, | ||
| className: className, | ||
| comment: comment, | ||
| fileName: fileName, | ||
| decomposition: decomposePath(path_2) | ||
| }); | ||
| } | ||
| } | ||
| return res; | ||
| } | ||
| exports.symtabToRouterDefinitions = symtabToRouterDefinitions; | ||
| function isURLParam(id, router, controller, methodPathDecomposition) { | ||
| return router.decomposition.urlParams[id] || controller.decomposition.urlParams[id] || methodPathDecomposition.urlParams[id]; | ||
| } | ||
| exports.isURLParam = isURLParam; | ||
| /** | ||
| * Generates the the function "argsToSchema" in __check.js. This function | ||
| * is generated 1 time for each relevant method, and so it not a single exported | ||
| * function but rather a named member of a checking class contained by an | ||
| * enclosing object indexed by the classname of the class of which it is a member. | ||
| * The purpose of this generated function when run is to create the input to the JSON | ||
| * schema checker that corresponds to the parameters of that method. It is used | ||
| * by the verb decorator (see verb.ts). | ||
| * | ||
| * let check = binding.check[(<any>target.constructor).name + "." + key]; | ||
| * let valid = check.validate(check.argsToSchema(arguments)); | ||
| * | ||
| * @param {any} parameterNames the list of paremter names. | ||
| */ | ||
| function genArgsToSchema(parameterNames, passthrough) { | ||
| var s = ''; | ||
| s += "function(a) {\n"; | ||
| if (passthrough) | ||
| s += " let o = a[0];\n"; | ||
| else { | ||
| s += " let o = {};\n\n"; | ||
| for (var i = 0; i < parameterNames.length; i++) { | ||
| s += " o['" + parameterNames[i] + "'] = a[" + i + "];\n"; | ||
| } | ||
| } | ||
| s += " return o;\n }"; | ||
| return s; | ||
| } | ||
| /** | ||
| * Generates the the function "schemaToArgs" in __check.js. This function | ||
| * (as above) is generated 1 time for each relevant method, and likewise is | ||
| * meant to reverse the effect of the above method. This is to allow ajv | ||
| * transformation side effects in validate to propogate forwared so it's not | ||
| * simply a metter of just using the original argument list. | ||
| * | ||
| * @param {any} parameterNames the list of paremter names. | ||
| */ | ||
| function genSchemaToArgs(parameterNames, passthrough) { | ||
| var s = ''; | ||
| s += "function(o) {\n"; | ||
| if (passthrough) | ||
| s += " let a = [o];\n\n"; | ||
| else { | ||
| s += " let a = [];\n\n"; | ||
| for (var i = 0; i < parameterNames.length; i++) { | ||
| s += " a[" + i + "] = o['" + parameterNames[i] + "'];\n"; | ||
| } | ||
| } | ||
| s += " return a;\n }"; | ||
| return s; | ||
| } | ||
| /** | ||
| * Generates a member of the check object for a method. Each entry contains a reference | ||
| * JSON schema labeled 'schema', the function argsToSchema which creates the arguments | ||
| * to the checker, and validate which is the validator. Each entry in indexed by the | ||
| * unique combination of className.methodName. | ||
| * | ||
| * @param className Name of the (controller) class. | ||
| * @param methodName Name of the method. | ||
| * @param parameterNames list of each formal parameter to the method. | ||
| * @param schema the JSON schema of all of the relevant type definitions. | ||
| */ | ||
| function genMethodEntry(classRef, methodName, parameterNames, schema, passthrough) { | ||
| var s = "\nexports[\"" + classRef + "." + methodName + "\"] = {\n"; | ||
| if (schema.type == "object") { | ||
| var numParameters = 0; | ||
| var child = void 0; | ||
| var childName = void 0; | ||
| for (var p in schema.properties) { | ||
| child = schema.properties[p]; | ||
| childName = p; | ||
| numParameters++; | ||
| } | ||
| } | ||
| var schemaFormatted = JSON.stringify(schema, null, 2); | ||
| schemaFormatted = schemaFormatted.replace(/\n/g, "\n "); | ||
| s += " schema:compositeWithDefinitions(" + schemaFormatted + "),\n"; | ||
| s += " argsToSchema:" + genArgsToSchema(parameterNames, passthrough) + ",\n"; | ||
| s += " schemaToArgs:" + genSchemaToArgs(parameterNames, passthrough) + ",\n"; | ||
| s += " validate:validate(" + schemaFormatted + ")\n"; | ||
| s += "};\n"; | ||
| return s; | ||
| } | ||
| exports.genMethodEntry = genMethodEntry; | ||
| /** | ||
| * Adds an entry for a controller to the global typescript source symbol table. | ||
| * | ||
| * @param {string} className the name of the class annotated by @controller. | ||
| * @param {string} fileName the name of the file containing the controller definition. | ||
| * @param {string} comment a JSDoc type comment of the controller. | ||
| */ | ||
| function addController(index, fileName, comment) { | ||
| symtab_1.symtabPut(index, { kind: "controller", fileName: fileName, comment: comment, methods: [], args: [] }); | ||
| } | ||
| exports.addController = addController; | ||
| /** | ||
| * Adds an entry for a router to the global typescript source symbol table. | ||
| * | ||
| * @param {string} className the name of the class annotated by @router. | ||
| * @param {string} fileName the name of the file containing the router definition. | ||
| * @param {string} comment a JSDoc type comment of the router. | ||
| */ | ||
| function addRouter(index, fileName, comment) { | ||
| symtab_1.symtabPut(index, { kind: "router", fileName: fileName, comment: comment, args: [] }); | ||
| } | ||
| exports.addRouter = addRouter; | ||
| /** | ||
| * Output a path of appropriate type-style by concetenating the components some of which | ||
| * might also be urlParam type components. | ||
| * | ||
| * @param decomposition {PathDecomposition} The decomposed form of a path -- broken down into components. | ||
| & @param pathType: Either swagger or express | ||
| */ | ||
| function decompositionToPath(decomposition, pathType) { | ||
| var path = ""; | ||
| for (var i = 0; i < decomposition.pathComponents.length; i++) { | ||
| var component = decomposition.pathComponents[i]; | ||
| if (path != "") | ||
| path = path + '/'; | ||
| if (decomposition.urlParams[component]) { | ||
| if (pathType == "swagger") | ||
| path = path + '{' + component + '}'; | ||
| else | ||
| path = path + ':' + component; | ||
| } | ||
| else | ||
| path = path + component; | ||
| } | ||
| return path; | ||
| } | ||
| exports.decompositionToPath = decompositionToPath; | ||
| //# sourceMappingURL=traverse.js.map |
| {"version":3,"file":"traverse.js","sourceRoot":"","sources":["../../src/analyzer/traverse.ts"],"names":[],"mappings":"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"} |
| import * as ts from "typescript"; | ||
| /** | ||
| * Interface for recording the elements of a method parameter list | ||
| */ | ||
| export interface TypedId { | ||
| id: string; | ||
| type: Object; | ||
| required: boolean; | ||
| decorators: any[]; | ||
| } | ||
| /** | ||
| * Simple object for holding the processing of a path; principally for | ||
| * the result of url param detection and component assignement. | ||
| */ | ||
| export interface PathDecomposition { | ||
| pathComponents: string[]; | ||
| urlParams: Object; | ||
| } | ||
| /** | ||
| * Interface for collection of relevant information about class methods | ||
| * annotated with REST verb decorators (e.g. @get, @post, etc). | ||
| * | ||
| */ | ||
| export interface DecoratedFunction { | ||
| name: string; | ||
| index: string | Object; | ||
| classRef: string; | ||
| comment: string; | ||
| decoratorArgs: any[]; | ||
| methodParameters: TypedId[]; | ||
| returnType: ts.TypeNode; | ||
| type: string; | ||
| } | ||
| /** | ||
| * Interface for collection of relevant information about classes annotated | ||
| * by the @controller decorator. | ||
| * | ||
| */ | ||
| export interface Controller { | ||
| args: any[]; | ||
| classRef: string; | ||
| fileName: string; | ||
| comment: string; | ||
| methods: DecoratedFunction[]; | ||
| decomposition: PathDecomposition; | ||
| } | ||
| /** | ||
| * Interface for collection of relevant information about classes annotated | ||
| * by the @router decorator. | ||
| * | ||
| */ | ||
| export interface Router { | ||
| args: any[]; | ||
| className: string; | ||
| fileName: string; | ||
| comment: string; | ||
| decomposition: PathDecomposition; | ||
| } |
| "use strict"; | ||
| Object.defineProperty(exports, "__esModule", { value: true }); | ||
| var ts = require("typescript"); | ||
| var tsany = ts; | ||
| ; | ||
| ; | ||
| //# sourceMappingURL=types.js.map |
| {"version":3,"file":"types.js","sourceRoot":"","sources":["../../src/analyzer/types.ts"],"names":[],"mappings":";;AAAA,+BAAiC;AACjC,IAAM,KAAK,GAAG,EAAS,CAAC;AAUvB,CAAC;AAyBD,CAAC"} |
| import ControllerProperties from './ControllerProperties'; | ||
| /** | ||
| * ControllerBase | ||
| * | ||
| * A baseclass to coordinate ts-api REST endpoint callback and typechecks | ||
| * by simply declaring a string valued id. The class also declares a placeholder | ||
| * for coordination via context. Controller classes should derive from this | ||
| * class. Derived classes will automatically be constructed from these values. | ||
| */ | ||
| export default class ControllerBase { | ||
| protected properties: ControllerProperties; | ||
| path: string; | ||
| constructor(properties: ControllerProperties); | ||
| getEndpointSignatureBinding(): import("./EndpointCheckBinding").default; | ||
| getProperties(): ControllerProperties; | ||
| } |
| "use strict"; | ||
| Object.defineProperty(exports, "__esModule", { value: true }); | ||
| /** | ||
| * ControllerBase | ||
| * | ||
| * A baseclass to coordinate ts-api REST endpoint callback and typechecks | ||
| * by simply declaring a string valued id. The class also declares a placeholder | ||
| * for coordination via context. Controller classes should derive from this | ||
| * class. Derived classes will automatically be constructed from these values. | ||
| */ | ||
| var ControllerBase = /** @class */ (function () { | ||
| function ControllerBase(properties) { | ||
| this.properties = properties; | ||
| } | ||
| ControllerBase.prototype.getEndpointSignatureBinding = function () { return this.properties.binding; }; | ||
| ControllerBase.prototype.getProperties = function () { return this.properties; }; | ||
| return ControllerBase; | ||
| }()); | ||
| exports.default = ControllerBase; | ||
| //# sourceMappingURL=ControllerBase.js.map |
| {"version":3,"file":"ControllerBase.js","sourceRoot":"","sources":["../src/ControllerBase.ts"],"names":[],"mappings":";;AAEA;;;;;;;GAOG;AACH;IAIE,wBAAY,UAA+B;QACzC,IAAI,CAAC,UAAU,GAAG,UAAU,CAAC;IAC/B,CAAC;IAED,oDAA2B,GAA3B,cAAgC,OAAO,IAAI,CAAC,UAAU,CAAC,OAAO,CAAC,CAAC,CAAC;IACjE,sCAAa,GAAb,cAAkB,OAAO,IAAI,CAAC,UAAU,CAAC,CAAC,CAAC;IAC7C,qBAAC;AAAD,CAAC,AAVD,IAUC"} |
| import EndpointCheckBinding from './EndpointCheckBinding'; | ||
| export default class ControllerInitializer { | ||
| binding: EndpointCheckBinding; | ||
| context: any; | ||
| req: any; | ||
| res: any; | ||
| next: Function; | ||
| constructor(binding: EndpointCheckBinding, context: any, req: any, res: any, next: Function); | ||
| } |
| "use strict"; | ||
| Object.defineProperty(exports, "__esModule", { value: true }); | ||
| var ControllerInitializer = /** @class */ (function () { | ||
| function ControllerInitializer(binding, context, req, res, next) { | ||
| this.binding = binding; | ||
| this.context = context; | ||
| this.req = req; | ||
| this.res = res; | ||
| this.next = next; | ||
| } | ||
| return ControllerInitializer; | ||
| }()); | ||
| exports.default = ControllerInitializer; | ||
| //# sourceMappingURL=ControllerProperties.js.map |
| {"version":3,"file":"ControllerProperties.js","sourceRoot":"","sources":["../src/ControllerProperties.ts"],"names":[],"mappings":";;AAEA;IAOE,+BAAY,OAA6B,EAAC,OAAW,EAAC,GAAO,EAAC,GAAO,EAAC,IAAa;QACjF,IAAI,CAAC,OAAO,GAAG,OAAO,CAAC;QACvB,IAAI,CAAC,OAAO,GAAG,OAAO,CAAC;QACvB,IAAI,CAAC,GAAG,GAAG,GAAG,CAAC;QACf,IAAI,CAAC,GAAG,GAAG,GAAG,CAAC;QACf,IAAI,CAAC,IAAI,GAAG,IAAI,CAAC;IACnB,CAAC;IACH,4BAAC;AAAD,CAAC,AAdD,IAcC"} |
| export default function all(path?: string, errorHandler?: Function): (target: any, key: string, descriptor: TypedPropertyDescriptor<any>) => TypedPropertyDescriptor<any>; |
| "use strict"; | ||
| Object.defineProperty(exports, "__esModule", { value: true }); | ||
| var verb_1 = require("./verb"); | ||
| function all(path, errorHandler) { | ||
| return function (target, key, descriptor) { | ||
| if (descriptor === undefined) | ||
| descriptor = Object.getOwnPropertyDescriptor(target, key); | ||
| descriptor.value = verb_1.default(target, key, descriptor.value, errorHandler); | ||
| return descriptor; | ||
| }; | ||
| } | ||
| exports.default = all; | ||
| //# sourceMappingURL=all.js.map |
| {"version":3,"file":"all.js","sourceRoot":"","sources":["../../src/decorators/all.ts"],"names":[],"mappings":";;AAAA,+BAA0B;AAE1B,SAAwB,GAAG,CAAC,IAAY,EAAC,YAAsB;IAC7D,OAAO,UAAS,MAAU,EAAC,GAAU,EAAC,UAAuC;QAC3E,IAAG,UAAU,KAAK,SAAS;YAAE,UAAU,GAAG,MAAM,CAAC,wBAAwB,CAAC,MAAM,EAAC,GAAG,CAAC,CAAC;QACtF,UAAU,CAAC,KAAK,GAAG,cAAI,CAAC,MAAM,EAAC,GAAG,EAAC,UAAU,CAAC,KAAK,EAAC,YAAY,CAAC,CAAC;QAClE,OAAO,UAAU,CAAC;IACpB,CAAC,CAAA;AACH,CAAC;AAND,sBAMC"} |
| import 'reflect-metadata'; | ||
| /** | ||
| * Wrap the original controller definition with a function | ||
| * that will first save relevant infomation about the path | ||
| * in a member property before invoking the original | ||
| * constructor | ||
| */ | ||
| export default function controller(path: string): (target: any) => any; |
| "use strict"; | ||
| var __spreadArrays = (this && this.__spreadArrays) || function () { | ||
| for (var s = 0, i = 0, il = arguments.length; i < il; i++) s += arguments[i].length; | ||
| for (var r = Array(s), k = 0, i = 0; i < il; i++) | ||
| for (var a = arguments[i], j = 0, jl = a.length; j < jl; j++, k++) | ||
| r[k] = a[j]; | ||
| return r; | ||
| }; | ||
| Object.defineProperty(exports, "__esModule", { value: true }); | ||
| require("reflect-metadata"); | ||
| /** | ||
| * Wrap the original controller definition with a function | ||
| * that will first save relevant infomation about the path | ||
| * in a member property before invoking the original | ||
| * constructor | ||
| */ | ||
| function controller(path) { | ||
| return function (target) { | ||
| var original = target; | ||
| var f = function () { | ||
| var args = []; | ||
| for (var _i = 0; _i < arguments.length; _i++) { | ||
| args[_i] = arguments[_i]; | ||
| } | ||
| var newPath = path; | ||
| if (newPath.charAt(0) != '/') | ||
| newPath = '/' + newPath; | ||
| if (newPath.charAt(newPath.length - 1) == '/') | ||
| newPath = newPath.substring(0, newPath.length - 1); | ||
| var result = new (original.bind.apply(original, __spreadArrays([void 0], args)))(); | ||
| result.path = newPath; | ||
| return result; | ||
| }; | ||
| // copy prototype so intanceof operator still works | ||
| f.prototype = original.prototype; | ||
| // return new constructor (will override original) | ||
| return f; | ||
| }; | ||
| } | ||
| exports.default = controller; | ||
| //# sourceMappingURL=controller.js.map |
| {"version":3,"file":"controller.js","sourceRoot":"","sources":["../../src/decorators/controller.ts"],"names":[],"mappings":";;;;;;;;;AAAA,4BAA0B;AAE1B;;;;;GAKG;AACH,SAAwB,UAAU,CAAC,IAAY;IAC7C,OAAO,UAAS,MAAW;QACzB,IAAI,QAAQ,GAAG,MAAM,CAAC;QAEtB,IAAI,CAAC,GAAO;YAAS,cAAO;iBAAP,UAAO,EAAP,qBAAO,EAAP,IAAO;gBAAP,yBAAO;;YAC1B,IAAI,OAAO,GAAG,IAAI,CAAC;YACnB,IAAG,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC,IAAI,GAAG;gBAAE,OAAO,GAAG,GAAG,GAAG,OAAO,CAAC;YACrD,IAAG,OAAO,CAAC,MAAM,CAAC,OAAO,CAAC,MAAM,GAAG,CAAC,CAAC,IAAI,GAAG;gBAAE,OAAO,GAAG,OAAO,CAAC,SAAS,CAAC,CAAC,EAAC,OAAO,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC;YAEhG,IAAM,MAAM,QAAO,QAAQ,YAAR,QAAQ,2BAAI,IAAI,KAAC,CAAC;YACrC,MAAM,CAAC,IAAI,GAAG,OAAO,CAAC;YACtB,OAAO,MAAM,CAAC;QAChB,CAAC,CAAA;QAED,mDAAmD;QACnD,CAAC,CAAC,SAAS,GAAG,QAAQ,CAAC,SAAS,CAAC;QAEjC,kDAAkD;QAClD,OAAO,CAAC,CAAC;IACX,CAAC,CAAC;AACJ,CAAC;AApBD,6BAoBC"} |
| export default function del(path?: string, errorHandler?: Function): (target: any, key: string, descriptor: TypedPropertyDescriptor<any>) => TypedPropertyDescriptor<any>; |
| "use strict"; | ||
| Object.defineProperty(exports, "__esModule", { value: true }); | ||
| var verb_1 = require("./verb"); | ||
| function del(path, errorHandler) { | ||
| return function (target, key, descriptor) { | ||
| if (descriptor === undefined) | ||
| descriptor = Object.getOwnPropertyDescriptor(target, key); | ||
| descriptor.value = verb_1.default(target, key, descriptor.value, errorHandler); | ||
| return descriptor; | ||
| }; | ||
| } | ||
| exports.default = del; | ||
| //# sourceMappingURL=del.js.map |
| {"version":3,"file":"del.js","sourceRoot":"","sources":["../../src/decorators/del.ts"],"names":[],"mappings":";;AAAA,+BAA0B;AAE1B,SAAwB,GAAG,CAAC,IAAY,EAAC,YAAsB;IAC7D,OAAO,UAAS,MAAU,EAAC,GAAU,EAAC,UAAuC;QAC3E,IAAG,UAAU,KAAK,SAAS;YAAE,UAAU,GAAG,MAAM,CAAC,wBAAwB,CAAC,MAAM,EAAC,GAAG,CAAC,CAAC;QACtF,UAAU,CAAC,KAAK,GAAG,cAAI,CAAC,MAAM,EAAC,GAAG,EAAC,UAAU,CAAC,KAAK,EAAC,YAAY,CAAC,CAAC;QAClE,OAAO,UAAU,CAAC;IACpB,CAAC,CAAA;AACH,CAAC;AAND,sBAMC"} |
| export default function get(path?: string, errorHandler?: Function): (target: any, key: string, descriptor: TypedPropertyDescriptor<any>) => TypedPropertyDescriptor<any>; |
| "use strict"; | ||
| Object.defineProperty(exports, "__esModule", { value: true }); | ||
| var verb_1 = require("./verb"); | ||
| function get(path, errorHandler) { | ||
| return function (target, key, descriptor) { | ||
| if (descriptor === undefined) | ||
| descriptor = Object.getOwnPropertyDescriptor(target, key); | ||
| descriptor.value = verb_1.default(target, key, descriptor.value, errorHandler); | ||
| return descriptor; | ||
| }; | ||
| } | ||
| exports.default = get; | ||
| //# sourceMappingURL=get.js.map |
| {"version":3,"file":"get.js","sourceRoot":"","sources":["../../src/decorators/get.ts"],"names":[],"mappings":";;AAAA,+BAA0B;AAE1B,SAAwB,GAAG,CAAC,IAAY,EAAC,YAAsB;IAC7D,OAAO,UAAS,MAAU,EAAC,GAAU,EAAC,UAAuC;QAC3E,IAAG,UAAU,KAAK,SAAS;YAAE,UAAU,GAAG,MAAM,CAAC,wBAAwB,CAAC,MAAM,EAAC,GAAG,CAAC,CAAC;QACtF,UAAU,CAAC,KAAK,GAAG,cAAI,CAAC,MAAM,EAAC,GAAG,EAAC,UAAU,CAAC,KAAK,EAAC,YAAY,CAAC,CAAC;QAClE,OAAO,UAAU,CAAC;IACpB,CAAC,CAAA;AACH,CAAC;AAND,sBAMC"} |
| import all from "./all"; | ||
| import controller from "./controller"; | ||
| import del from "./del"; | ||
| import get from "./get"; | ||
| import post from "./post"; | ||
| import put from "./put"; | ||
| import router from "./router"; | ||
| import urlParam from "./urlParam"; | ||
| import { minimum, maximum, minItems, maxItems, minLength, maxLength, precision, format, pattern, type } from "./parm"; | ||
| export { all, controller, del, format, get, maxItems, maxLength, maximum, minItems, minLength, minimum, pattern, post, precision, put, router, type, urlParam }; |
| "use strict"; | ||
| Object.defineProperty(exports, "__esModule", { value: true }); | ||
| var all_1 = require("./all"); | ||
| exports.all = all_1.default; | ||
| var controller_1 = require("./controller"); | ||
| exports.controller = controller_1.default; | ||
| var del_1 = require("./del"); | ||
| exports.del = del_1.default; | ||
| var get_1 = require("./get"); | ||
| exports.get = get_1.default; | ||
| var post_1 = require("./post"); | ||
| exports.post = post_1.default; | ||
| var put_1 = require("./put"); | ||
| exports.put = put_1.default; | ||
| var router_1 = require("./router"); | ||
| exports.router = router_1.default; | ||
| var urlParam_1 = require("./urlParam"); | ||
| exports.urlParam = urlParam_1.default; | ||
| var parm_1 = require("./parm"); | ||
| exports.minimum = parm_1.minimum; | ||
| exports.maximum = parm_1.maximum; | ||
| exports.minItems = parm_1.minItems; | ||
| exports.maxItems = parm_1.maxItems; | ||
| exports.minLength = parm_1.minLength; | ||
| exports.maxLength = parm_1.maxLength; | ||
| exports.precision = parm_1.precision; | ||
| exports.format = parm_1.format; | ||
| exports.pattern = parm_1.pattern; | ||
| exports.type = parm_1.type; | ||
| //# sourceMappingURL=index.js.map |
| {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/decorators/index.ts"],"names":[],"mappings":";;AAAA,6BAAwB;AAWtB,cAXK,aAAG,CAWL;AAVL,2CAAsC;AAWpC,qBAXK,oBAAU,CAWL;AAVZ,6BAAwB;AAWtB,cAXK,aAAG,CAWL;AAVL,6BAAwB;AAYtB,cAZK,aAAG,CAYL;AAXL,+BAA0B;AAmBxB,eAnBK,cAAI,CAmBL;AAlBN,6BAAwB;AAoBtB,cApBK,aAAG,CAoBL;AAnBL,mCAA8B;AAoB5B,iBApBK,gBAAM,CAoBL;AAnBR,uCAAkC;AAqBhC,mBArBK,kBAAQ,CAqBL;AApBV,+BAA6G;AAa3G,kBAbO,cAAO,CAaP;AAHP,kBAVe,cAAO,CAUf;AACP,mBAXuB,eAAQ,CAWvB;AAHR,mBARgC,eAAQ,CAQhC;AAIR,oBAZyC,gBAAS,CAYzC;AAHT,oBATmD,gBAAS,CASnD;AAOT,oBAhB6D,gBAAS,CAgB7D;AAVT,iBANuE,aAAM,CAMvE;AAQN,kBAd8E,cAAO,CAc9E;AAKP,eAnBsF,WAAI,CAmBtF"} |
| import 'reflect-metadata'; | ||
| export declare function minimum(n: number): (target: any, propertyKey: string, parameterIndex: number) => void; | ||
| export declare function maximum(n: number): (target: any, propertyKey: string, parameterIndex: number) => void; | ||
| export declare function minLength(n: number): (target: any, propertyKey: string, parameterIndex: number) => void; | ||
| export declare function maxLength(n: number): (target: any, propertyKey: string, parameterIndex: number) => void; | ||
| export declare function minItems(n: number): (target: any, propertyKey: string, parameterIndex: number) => void; | ||
| export declare function maxItems(n: number): (target: any, propertyKey: string, parameterIndex: number) => void; | ||
| export declare function precision(n: number): (target: any, propertyKey: string, parameterIndex: number) => void; | ||
| export declare function format(s: string): (target: any, propertyKey: string, parameterIndex: number) => void; | ||
| export declare function pattern(s: string): (target: any, propertyKey: string, parameterIndex: number) => void; | ||
| export declare function type(s: string): (target: any, propertyKey: string, parameterIndex: number) => void; |
| "use strict"; | ||
| Object.defineProperty(exports, "__esModule", { value: true }); | ||
| require("reflect-metadata"); | ||
| function minimum(n) { | ||
| return function (target, propertyKey, parameterIndex) { }; | ||
| } | ||
| exports.minimum = minimum; | ||
| function maximum(n) { | ||
| return function (target, propertyKey, parameterIndex) { }; | ||
| } | ||
| exports.maximum = maximum; | ||
| function minLength(n) { | ||
| return function (target, propertyKey, parameterIndex) { }; | ||
| } | ||
| exports.minLength = minLength; | ||
| function maxLength(n) { | ||
| return function (target, propertyKey, parameterIndex) { }; | ||
| } | ||
| exports.maxLength = maxLength; | ||
| function minItems(n) { | ||
| return function (target, propertyKey, parameterIndex) { }; | ||
| } | ||
| exports.minItems = minItems; | ||
| function maxItems(n) { | ||
| return function (target, propertyKey, parameterIndex) { }; | ||
| } | ||
| exports.maxItems = maxItems; | ||
| function precision(n) { | ||
| return function (target, propertyKey, parameterIndex) { }; | ||
| } | ||
| exports.precision = precision; | ||
| function format(s) { | ||
| return function (target, propertyKey, parameterIndex) { }; | ||
| } | ||
| exports.format = format; | ||
| function pattern(s) { | ||
| return function (target, propertyKey, parameterIndex) { }; | ||
| } | ||
| exports.pattern = pattern; | ||
| function type(s) { | ||
| return function (target, propertyKey, parameterIndex) { }; | ||
| } | ||
| exports.type = type; | ||
| //# sourceMappingURL=parm.js.map |
| {"version":3,"file":"parm.js","sourceRoot":"","sources":["../../src/decorators/parm.ts"],"names":[],"mappings":";;AAAA,4BAA0B;AAE1B,SAAgB,OAAO,CAAC,CAAQ;IAC9B,OAAO,UAAS,MAAU,EAAC,WAAkB,EAAC,cAAsB,IAAG,CAAC,CAAA;AAC1E,CAAC;AAFD,0BAEC;AAED,SAAgB,OAAO,CAAC,CAAQ;IAC9B,OAAO,UAAS,MAAU,EAAC,WAAkB,EAAC,cAAsB,IAAG,CAAC,CAAA;AAC1E,CAAC;AAFD,0BAEC;AAED,SAAgB,SAAS,CAAC,CAAQ;IAChC,OAAO,UAAS,MAAU,EAAC,WAAkB,EAAC,cAAsB,IAAG,CAAC,CAAA;AAC1E,CAAC;AAFD,8BAEC;AAED,SAAgB,SAAS,CAAC,CAAQ;IAChC,OAAO,UAAS,MAAU,EAAC,WAAkB,EAAC,cAAsB,IAAG,CAAC,CAAA;AAC1E,CAAC;AAFD,8BAEC;AAED,SAAgB,QAAQ,CAAC,CAAQ;IAC/B,OAAO,UAAS,MAAU,EAAC,WAAkB,EAAC,cAAsB,IAAG,CAAC,CAAA;AAC1E,CAAC;AAFD,4BAEC;AAED,SAAgB,QAAQ,CAAC,CAAQ;IAC/B,OAAO,UAAS,MAAU,EAAC,WAAkB,EAAC,cAAsB,IAAG,CAAC,CAAA;AAC1E,CAAC;AAFD,4BAEC;AAED,SAAgB,SAAS,CAAC,CAAQ;IAChC,OAAO,UAAS,MAAU,EAAC,WAAkB,EAAC,cAAsB,IAAG,CAAC,CAAA;AAC1E,CAAC;AAFD,8BAEC;AAED,SAAgB,MAAM,CAAC,CAAQ;IAC7B,OAAO,UAAS,MAAU,EAAC,WAAkB,EAAC,cAAsB,IAAG,CAAC,CAAA;AAC1E,CAAC;AAFD,wBAEC;AAED,SAAgB,OAAO,CAAC,CAAQ;IAC9B,OAAO,UAAS,MAAU,EAAC,WAAkB,EAAC,cAAsB,IAAG,CAAC,CAAA;AAC1E,CAAC;AAFD,0BAEC;AAED,SAAgB,IAAI,CAAC,CAAQ;IAC3B,OAAO,UAAS,MAAU,EAAC,WAAkB,EAAC,cAAsB,IAAG,CAAC,CAAA;AAC1E,CAAC;AAFD,oBAEC"} |
| export default function post(path?: string, errorHandler?: Function): (target: any, key: string, descriptor: TypedPropertyDescriptor<any>) => TypedPropertyDescriptor<any>; |
| "use strict"; | ||
| Object.defineProperty(exports, "__esModule", { value: true }); | ||
| var verb_1 = require("./verb"); | ||
| function post(path, errorHandler) { | ||
| return function (target, key, descriptor) { | ||
| if (descriptor === undefined) | ||
| descriptor = Object.getOwnPropertyDescriptor(target, key); | ||
| descriptor.value = verb_1.default(target, key, descriptor.value, errorHandler); | ||
| return descriptor; | ||
| }; | ||
| } | ||
| exports.default = post; | ||
| //# sourceMappingURL=post.js.map |
| {"version":3,"file":"post.js","sourceRoot":"","sources":["../../src/decorators/post.ts"],"names":[],"mappings":";;AAAA,+BAA0B;AAE1B,SAAwB,IAAI,CAAC,IAAY,EAAC,YAAsB;IAC9D,OAAO,UAAS,MAAU,EAAC,GAAU,EAAC,UAAuC;QAC3E,IAAG,UAAU,KAAK,SAAS;YAAE,UAAU,GAAG,MAAM,CAAC,wBAAwB,CAAC,MAAM,EAAC,GAAG,CAAC,CAAC;QACtF,UAAU,CAAC,KAAK,GAAG,cAAI,CAAC,MAAM,EAAC,GAAG,EAAC,UAAU,CAAC,KAAK,EAAC,YAAY,CAAC,CAAC;QAClE,OAAO,UAAU,CAAC;IACpB,CAAC,CAAA;AACH,CAAC;AAND,uBAMC"} |
| export default function put(path?: string, errorHandler?: Function): (target: any, key: string, descriptor: TypedPropertyDescriptor<any>) => TypedPropertyDescriptor<any>; |
| "use strict"; | ||
| Object.defineProperty(exports, "__esModule", { value: true }); | ||
| var verb_1 = require("./verb"); | ||
| function put(path, errorHandler) { | ||
| return function (target, key, descriptor) { | ||
| if (descriptor === undefined) | ||
| descriptor = Object.getOwnPropertyDescriptor(target, key); | ||
| descriptor.value = verb_1.default(target, key, descriptor.value, errorHandler); | ||
| return descriptor; | ||
| }; | ||
| } | ||
| exports.default = put; | ||
| //# sourceMappingURL=put.js.map |
| {"version":3,"file":"put.js","sourceRoot":"","sources":["../../src/decorators/put.ts"],"names":[],"mappings":";;AAAA,+BAA0B;AAE1B,SAAwB,GAAG,CAAC,IAAY,EAAC,YAAsB;IAC7D,OAAO,UAAS,MAAU,EAAC,GAAU,EAAC,UAAuC;QAC3E,IAAG,UAAU,KAAK,SAAS;YAAE,UAAU,GAAG,MAAM,CAAC,wBAAwB,CAAC,MAAM,EAAC,GAAG,CAAC,CAAC;QACtF,UAAU,CAAC,KAAK,GAAG,cAAI,CAAC,MAAM,EAAC,GAAG,EAAC,UAAU,CAAC,KAAK,EAAC,YAAY,CAAC,CAAC;QAClE,OAAO,UAAU,CAAC;IACpB,CAAC,CAAA;AACH,CAAC;AAND,sBAMC"} |
| import 'reflect-metadata'; | ||
| /** | ||
| * Wrap the original router definition with a function | ||
| * that will first save relevant infomation about the path | ||
| * prefix in a member property before invoking the original | ||
| * constructor | ||
| */ | ||
| export default function router(prefix: string): (target: any) => any; |
| "use strict"; | ||
| var __spreadArrays = (this && this.__spreadArrays) || function () { | ||
| for (var s = 0, i = 0, il = arguments.length; i < il; i++) s += arguments[i].length; | ||
| for (var r = Array(s), k = 0, i = 0; i < il; i++) | ||
| for (var a = arguments[i], j = 0, jl = a.length; j < jl; j++, k++) | ||
| r[k] = a[j]; | ||
| return r; | ||
| }; | ||
| Object.defineProperty(exports, "__esModule", { value: true }); | ||
| require("reflect-metadata"); | ||
| /** | ||
| * Wrap the original router definition with a function | ||
| * that will first save relevant infomation about the path | ||
| * prefix in a member property before invoking the original | ||
| * constructor | ||
| */ | ||
| function router(prefix) { | ||
| return function (target) { | ||
| var original = target; | ||
| var f = function () { | ||
| var args = []; | ||
| for (var _i = 0; _i < arguments.length; _i++) { | ||
| args[_i] = arguments[_i]; | ||
| } | ||
| var newPrefix = prefix || ''; | ||
| if (newPrefix.charAt(0) != '/') | ||
| newPrefix = '/' + newPrefix; | ||
| if (newPrefix.charAt(newPrefix.length - 1) == '/') | ||
| newPrefix = newPrefix.substring(0, newPrefix.length - 1); | ||
| var result = new (original.bind.apply(original, __spreadArrays([void 0], args)))(); | ||
| result.prefix = newPrefix; | ||
| return result; | ||
| }; | ||
| // copy prototype so intanceof operator still works | ||
| f.prototype = original.prototype; | ||
| // return new constructor (will override original) | ||
| return f; | ||
| }; | ||
| } | ||
| exports.default = router; | ||
| //# sourceMappingURL=router.js.map |
| {"version":3,"file":"router.js","sourceRoot":"","sources":["../../src/decorators/router.ts"],"names":[],"mappings":";;;;;;;;;AAAA,4BAA0B;AAE1B;;;;;GAKG;AACH,SAAwB,MAAM,CAAC,MAAc;IAC3C,OAAO,UAAS,MAAW;QACzB,IAAI,QAAQ,GAAG,MAAM,CAAC;QAEtB,IAAI,CAAC,GAAO;YAAS,cAAO;iBAAP,UAAO,EAAP,qBAAO,EAAP,IAAO;gBAAP,yBAAO;;YAC1B,IAAI,SAAS,GAAG,MAAM,IAAI,EAAE,CAAC;YAC7B,IAAG,SAAS,CAAC,MAAM,CAAC,CAAC,CAAC,IAAI,GAAG;gBAAE,SAAS,GAAG,GAAG,GAAG,SAAS,CAAC;YAC3D,IAAG,SAAS,CAAC,MAAM,CAAC,SAAS,CAAC,MAAM,GAAG,CAAC,CAAC,IAAI,GAAG;gBAAE,SAAS,GAAG,SAAS,CAAC,SAAS,CAAC,CAAC,EAAC,SAAS,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC;YAE1G,IAAM,MAAM,QAAO,QAAQ,YAAR,QAAQ,2BAAI,IAAI,KAAC,CAAC;YACrC,MAAM,CAAC,MAAM,GAAG,SAAS,CAAC;YAC1B,OAAO,MAAM,CAAC;QAChB,CAAC,CAAA;QAED,mDAAmD;QACnD,CAAC,CAAC,SAAS,GAAG,QAAQ,CAAC,SAAS,CAAC;QAEjC,kDAAkD;QAClD,OAAO,CAAC,CAAC;IACX,CAAC,CAAC;AACJ,CAAC;AApBD,yBAoBC"} |
| import "reflect-metadata"; | ||
| export default function urlParam(component: string): (target: any, propertyKey: string | symbol, parameterIndex: number) => void; |
| "use strict"; | ||
| Object.defineProperty(exports, "__esModule", { value: true }); | ||
| require("reflect-metadata"); | ||
| function urlParam(component) { | ||
| return function (target, propertyKey, parameterIndex) { | ||
| var parms = Reflect.getOwnMetadata("urlParam", target, propertyKey) || []; | ||
| parms.push(parameterIndex); | ||
| Reflect.defineMetadata("urlParam", parms, target, propertyKey); | ||
| }; | ||
| } | ||
| exports.default = urlParam; | ||
| //# sourceMappingURL=urlParam.js.map |
| {"version":3,"file":"urlParam.js","sourceRoot":"","sources":["../../src/decorators/urlParam.ts"],"names":[],"mappings":";;AAAA,4BAA0B;AAE1B,SAAwB,QAAQ,CAAC,SAAgB;IAC/C,OAAO,UAAS,MAAU,EAAC,WAAyB,EAAC,cAAqB;QACxE,IAAM,KAAK,GAAG,OAAO,CAAC,cAAc,CAAC,UAAU,EAAC,MAAM,EAAC,WAAW,CAAC,IAAI,EAAE,CAAC;QAE1E,KAAK,CAAC,IAAI,CAAC,cAAc,CAAC,CAAC;QAC3B,OAAO,CAAC,cAAc,CAAC,UAAU,EAAC,KAAK,EAAC,MAAM,EAAC,WAAW,CAAC,CAAC;IAC9D,CAAC,CAAA;AACH,CAAC;AAPD,2BAOC"} |
| /** | ||
| * A decorator for REST endpoints. Use the typescript decorator system to | ||
| * automatically apply typechecking. Assume that the controller for which this | ||
| * decorator applies to it's methods follows the form defined by ControllerBase | ||
| * and itself hase been annotated by @controller. If that is true, then a reference | ||
| * to that controller class will be provided to an argument to this function. Use | ||
| * the controller reference to gain access to the function that defines the check as | ||
| * well as the JSON schema to use as an argument. Return a function that will first | ||
| * perform that check, and if the check passes then execute the method on which this | ||
| * decorator has been applied. Otherwise throw an error. Assume that the exception | ||
| * will be caught appropriately -- it will because this function will be invoked in the | ||
| * context of analogously renerated file __routes.js. Provide for the possibility | ||
| * of a user defined function for error processing which can itself either return | ||
| * a status code or throw an error. | ||
| * | ||
| * @param {any} target reference to containing class of the decorated method | ||
| * @param {string} key the method name | ||
| * @param {any} originalMethod reference to the decorated method | ||
| * @param {Function} errorHandler A user defined error handler. | ||
| */ | ||
| export default function verb(target: any, key: string, originalMethod: any, errorHandler: Function): () => any; |
| "use strict"; | ||
| Object.defineProperty(exports, "__esModule", { value: true }); | ||
| var Promise = require('bluebird'); | ||
| /** | ||
| * A decorator for REST endpoints. Use the typescript decorator system to | ||
| * automatically apply typechecking. Assume that the controller for which this | ||
| * decorator applies to it's methods follows the form defined by ControllerBase | ||
| * and itself hase been annotated by @controller. If that is true, then a reference | ||
| * to that controller class will be provided to an argument to this function. Use | ||
| * the controller reference to gain access to the function that defines the check as | ||
| * well as the JSON schema to use as an argument. Return a function that will first | ||
| * perform that check, and if the check passes then execute the method on which this | ||
| * decorator has been applied. Otherwise throw an error. Assume that the exception | ||
| * will be caught appropriately -- it will because this function will be invoked in the | ||
| * context of analogously renerated file __routes.js. Provide for the possibility | ||
| * of a user defined function for error processing which can itself either return | ||
| * a status code or throw an error. | ||
| * | ||
| * @param {any} target reference to containing class of the decorated method | ||
| * @param {string} key the method name | ||
| * @param {any} originalMethod reference to the decorated method | ||
| * @param {Function} errorHandler A user defined error handler. | ||
| */ | ||
| function verb(target, key, originalMethod, errorHandler) { | ||
| return function () { | ||
| var binding = this.getEndpointSignatureBinding(); | ||
| var controller = this; | ||
| var args = []; | ||
| if (binding != null) { | ||
| var check = binding.check[target.constructor.name + "." + key]; | ||
| var argObject = check.argsToSchema(arguments); | ||
| var valid = check.validate(argObject); | ||
| if (!valid) { | ||
| var err = check.validate.errors[0]; | ||
| throw ({ status: 400, message: "parameterList" + err.dataPath + " " + err.message }); | ||
| } | ||
| // generate args from schema because ajv might have transformed the original | ||
| args = check.schemaToArgs(argObject); | ||
| } | ||
| else { | ||
| for (var i = 0; i < arguments.length; i++) | ||
| args[i - 0] = arguments[i]; | ||
| } | ||
| try { | ||
| // note usage of originalMethod here | ||
| var obj_1 = originalMethod.apply(controller, args); | ||
| // If the original method is async, then resolve the promise before returning | ||
| if (obj_1 != null) { | ||
| if (obj_1.constructor.name == 'Promise') { | ||
| var promise = new Promise(function (resolve, reject) { | ||
| obj_1.then(function (value) { resolve(value); }, function (reason) { | ||
| if (errorHandler != null) { | ||
| try { | ||
| var properties = controller.getProperties(); | ||
| var errorHandlerResult = errorHandler(reason, properties.req, properties.res, properties.next); | ||
| if (errorHandlerResult != null && typeof errorHandlerResult == "object") { | ||
| if (errorHandlerResult.status == null) | ||
| errorHandlerResult.status = 500; | ||
| reject(errorHandlerResult); | ||
| } | ||
| else | ||
| reject({ status: 500, message: errorHandlerResult }); | ||
| } | ||
| catch (e) { | ||
| reject(e); | ||
| } | ||
| } | ||
| else { | ||
| if (typeof reason == 'object') | ||
| reason.status = 500; | ||
| reject(reason); | ||
| } | ||
| }); | ||
| }); | ||
| return promise; | ||
| } | ||
| } | ||
| return new Promise(function (resolve, reject) { resolve(obj_1); }); | ||
| } | ||
| catch (e) { | ||
| if (errorHandler != null) { | ||
| var properties = controller.getProperties(); | ||
| var errorHandlerResult = errorHandler(e, properties.req, properties.res, properties.next); | ||
| if (errorHandlerResult != null && typeof errorHandlerResult == "object") { | ||
| if (errorHandlerResult.status == null) | ||
| errorHandlerResult.status = 500; | ||
| throw (errorHandlerResult); | ||
| } | ||
| else | ||
| throw ({ status: 500, message: errorHandlerResult }); | ||
| } | ||
| throw (e); | ||
| } | ||
| }; | ||
| } | ||
| exports.default = verb; | ||
| //# sourceMappingURL=verb.js.map |
| {"version":3,"file":"verb.js","sourceRoot":"","sources":["../../src/decorators/verb.ts"],"names":[],"mappings":"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"} |
| export default class EndpointCheckBinding { | ||
| id: string; | ||
| check: any; | ||
| constructor(check: any); | ||
| } |
| "use strict"; | ||
| Object.defineProperty(exports, "__esModule", { value: true }); | ||
| var uuid = require('uuid/v1'); | ||
| var EndpointCheckBinding = /** @class */ (function () { | ||
| function EndpointCheckBinding(check) { | ||
| this.check = check; | ||
| this.id = uuid(); | ||
| } | ||
| return EndpointCheckBinding; | ||
| }()); | ||
| exports.default = EndpointCheckBinding; | ||
| //# sourceMappingURL=EndpointCheckBinding.js.map |
| {"version":3,"file":"EndpointCheckBinding.js","sourceRoot":"","sources":["../src/EndpointCheckBinding.ts"],"names":[],"mappings":";;AAAA,IAAM,IAAI,GAAG,OAAO,CAAC,SAAS,CAAC,CAAC;AAEhC;IAIE,8BAAY,KAAU;QACpB,IAAI,CAAC,KAAK,GAAG,KAAK,CAAC;QACnB,IAAI,CAAC,EAAE,GAAG,IAAI,EAAE,CAAC;IACnB,CAAC;IACH,2BAAC;AAAD,CAAC,AARD,IAQC"} |
| export declare type FileRef<m extends string> = { | ||
| filename?: string; | ||
| displayName?: string; | ||
| mimeType?: m; | ||
| }; |
| "use strict"; | ||
| Object.defineProperty(exports, "__esModule", { value: true }); | ||
| //# sourceMappingURL=FileRef.js.map |
| {"version":3,"file":"FileRef.js","sourceRoot":"","sources":["../../src/magic/FileRef.ts"],"names":[],"mappings":""} |
| export { StatusCodes, Res } from "./Res"; | ||
| export { FileRef } from "./FileRef"; |
| "use strict"; | ||
| Object.defineProperty(exports, "__esModule", { value: true }); | ||
| //# sourceMappingURL=index.js.map |
| {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/magic/index.ts"],"names":[],"mappings":""} |
| export declare type StatusCodes = 200 | 201 | 202 | 203 | 204 | 205 | 206 | 207 | 208 | 226 | 300 | 301 | 302 | 303 | 304 | 305 | 306 | 307 | 308 | 400 | 401 | 402 | 403 | 404 | 405 | 406 | 407 | 408 | 409 | 410 | 411 | 412 | 413 | 414 | 415 | 416 | 417 | 418 | 421 | 422 | 423 | 424 | 426 | 428 | 429 | 431 | 451 | 500 | 501 | 502 | 503 | 504 | 505 | 506 | 507 | 508 | 510 | 511; | ||
| export declare type Res<c extends StatusCodes, T> = { | ||
| body: T; | ||
| statusCode: c; | ||
| }; |
| "use strict"; | ||
| Object.defineProperty(exports, "__esModule", { value: true }); | ||
| //# sourceMappingURL=Res.js.map |
| {"version":3,"file":"Res.js","sourceRoot":"","sources":["../../src/magic/Res.ts"],"names":[],"mappings":""} |
| export declare function src(redocSrc: any): string; |
| "use strict"; | ||
| Object.defineProperty(exports, "__esModule", { value: true }); | ||
| function src(redocSrc) { | ||
| return "\n<!DOCTYPE html>\n <html>\n <head>\n <title>ReDoc</title>\n <!-- needed for adaptive design -->\n <meta charset=\"utf-8\"/>\n <meta name=\"viewport\" content=\"width=device-width, initial-scale=1\">\n <link href=\"https://fonts.googleapis.com/css?family=Montserrat:300,400,700|Roboto:300,400,700\" rel=\"stylesheet\">\n\n <!--\n ReDoc doesn't change outer page styles\n -->\n <style>\n body {\n margin: 0;\n padding: 0;\n }\n </style>\n </head>\n <body>\n <redoc spec-url='" + redocSrc + "'></redoc>\n <script src=\"https://cdn.jsdelivr.net/npm/redoc@next/bundles/redoc.standalone.js\"> </script>\n </body>\n </html>"; | ||
| } | ||
| exports.src = src; | ||
| //# sourceMappingURL=ReDoc.js.map |
| {"version":3,"file":"ReDoc.js","sourceRoot":"","sources":["../src/ReDoc.ts"],"names":[],"mappings":";;AAAA,SAAgB,GAAG,CAAC,QAAQ;IAAI,OAAO,2hBAqBhB,QAAQ,wIAGtB,CAAC;AACV,CAAC;AAzBD,kBAyBC"} |
| /** | ||
| * General REST processing in case of an error | ||
| */ | ||
| declare function error(e: any, req: any, res: any, next: any): void; | ||
| /** | ||
| * REST processing in case of endpoint success | ||
| */ | ||
| declare function success(obj: any, req: any, res: any, next: any): void; | ||
| declare const _default: { | ||
| error: typeof error; | ||
| success: typeof success; | ||
| }; | ||
| export default _default; |
| "use strict"; | ||
| Object.defineProperty(exports, "__esModule", { value: true }); | ||
| var uuidv1 = require('uuid/v1'); | ||
| var path = require('path'); | ||
| /** | ||
| * General REST processing in case of an error | ||
| */ | ||
| function error(e, req, res, next) { | ||
| if (res._header == null) { | ||
| if (e.stack) { | ||
| var ref = uuidv1(); | ||
| var status_1 = 500; | ||
| if (e.status) | ||
| status_1 = e.status; | ||
| console.log("response error " + ref + ":", e.stack); | ||
| res.status(status_1).send("<pre>\nerror: ref " + ref + ", check logs for further information\n</pre>"); | ||
| } | ||
| else { | ||
| if (e.status != null) | ||
| res.status(e.status).send({ error: e }); | ||
| else | ||
| next(e); | ||
| } | ||
| } | ||
| } | ||
| /** | ||
| * REST processing in case of endpoint success | ||
| */ | ||
| function success(obj, req, res, next) { | ||
| if (res._header == null) { | ||
| if (obj == null) | ||
| console.error("API return null result"); | ||
| else { | ||
| if (obj.statusCode != null) | ||
| res.status(obj.statusCode); | ||
| if (obj.filename != null) { | ||
| var resolvedPath = path.resolve(obj.filename); | ||
| if (obj.displayName != null) | ||
| res.download(resolvedPath, obj.displayName, function (err) { if (err != null) | ||
| next(err); }); | ||
| else | ||
| res.download(resolvedPath, function (err) { if (err != null) | ||
| next(err); }); | ||
| } | ||
| else { | ||
| if (obj.body != null) | ||
| res.send(obj.body); | ||
| else | ||
| res.send(obj); | ||
| } | ||
| } | ||
| } | ||
| } | ||
| exports.default = { error: error, success: success }; | ||
| //# sourceMappingURL=response.js.map |
| {"version":3,"file":"response.js","sourceRoot":"","sources":["../src/response.ts"],"names":[],"mappings":";;AAAA,IAAM,MAAM,GAAG,OAAO,CAAC,SAAS,CAAC,CAAC;AAClC,IAAM,IAAI,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC;AAE7B;;GAEG;AACH,SAAS,KAAK,CAAC,CAAK,EAAC,GAAO,EAAC,GAAO,EAAC,IAAQ;IAC3C,IAAG,GAAG,CAAC,OAAO,IAAI,IAAI,EAAE;QACtB,IAAG,CAAC,CAAC,KAAK,EAAE;YACV,IAAI,GAAG,GAAG,MAAM,EAAE,CAAC;YACnB,IAAI,QAAM,GAAG,GAAG,CAAC;YAEjB,IAAG,CAAC,CAAC,MAAM;gBAAE,QAAM,GAAG,CAAC,CAAC,MAAM,CAAC;YAC/B,OAAO,CAAC,GAAG,CAAC,oBAAkB,GAAG,MAAG,EAAC,CAAC,CAAC,KAAK,CAAC,CAAC;YAC9C,GAAG,CAAC,MAAM,CAAC,QAAM,CAAC,CAAC,IAAI,CAAC,uBAAqB,GAAG,iDAA8C,CAAC,CAAC;SACjG;aACI;YACH,IAAG,CAAC,CAAC,MAAM,IAAI,IAAI;gBAAE,GAAG,CAAC,MAAM,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,IAAI,CAAC,EAAE,KAAK,EAAC,CAAC,EAAE,CAAC,CAAC;;gBACvD,IAAI,CAAC,CAAC,CAAC,CAAC;SACd;KACF;AACH,CAAC;AAED;;GAEG;AACH,SAAS,OAAO,CAAC,GAAO,EAAC,GAAO,EAAC,GAAO,EAAC,IAAQ;IAC/C,IAAG,GAAG,CAAC,OAAO,IAAI,IAAI,EAAE;QACtB,IAAG,GAAG,IAAI,IAAI;YAAE,OAAO,CAAC,KAAK,CAAC,wBAAwB,CAAC,CAAC;aACnD;YACH,IAAG,GAAG,CAAC,UAAU,IAAI,IAAI;gBAAE,GAAG,CAAC,MAAM,CAAC,GAAG,CAAC,UAAU,CAAC,CAAC;YACtD,IAAG,GAAG,CAAC,QAAQ,IAAI,IAAI,EAAE;gBACvB,IAAI,YAAY,GAAG,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC;gBAE9C,IAAG,GAAG,CAAC,WAAW,IAAI,IAAI;oBACxB,GAAG,CAAC,QAAQ,CAAC,YAAY,EAAC,GAAG,CAAC,WAAW,EAAC,UAAS,GAAG,IAAI,IAAG,GAAG,IAAI,IAAI;wBAAE,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;;oBAExF,GAAG,CAAC,QAAQ,CAAC,YAAY,EAAC,UAAS,GAAG,IAAI,IAAG,GAAG,IAAI,IAAI;wBAAE,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;aAC3E;iBACI;gBACH,IAAG,GAAG,CAAC,IAAI,IAAI,IAAI;oBAAE,GAAG,CAAC,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;;oBACnC,GAAG,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;aACpB;SACF;KACF;AACH,CAAC;AAED,kBAAe,EAAE,KAAK,OAAA,EAAC,OAAO,SAAA,EAAE,CAAC"} |
| export default class RouterBase { | ||
| root: any; | ||
| routers: any; | ||
| prefix: string; | ||
| context: any; | ||
| constructor(context: any); | ||
| getExpressRouter(name?: string): any; | ||
| addRouter(path: string, name: string, options: any): void; | ||
| } |
| "use strict"; | ||
| Object.defineProperty(exports, "__esModule", { value: true }); | ||
| var express = require("express"); | ||
| var RouterBase = /** @class */ (function () { | ||
| function RouterBase(context) { | ||
| this.context = context; | ||
| this.routers = {}; | ||
| this.root = express.Router(); | ||
| } | ||
| RouterBase.prototype.getExpressRouter = function (name) { | ||
| if (name == null) | ||
| return this.root; | ||
| return this.routers[name]; | ||
| }; | ||
| RouterBase.prototype.addRouter = function (path, name, options) { | ||
| this.routers[name] = express.Router(options); | ||
| this.root.use(path, this.routers[name]); | ||
| }; | ||
| ; | ||
| return RouterBase; | ||
| }()); | ||
| exports.default = RouterBase; | ||
| //# sourceMappingURL=RouterBase.js.map |
| {"version":3,"file":"RouterBase.js","sourceRoot":"","sources":["../src/RouterBase.ts"],"names":[],"mappings":";;AAAA,IAAM,OAAO,GAAG,OAAO,CAAC,SAAS,CAAC,CAAC;AAEnC;IAME,oBAAY,OAAW;QACrB,IAAI,CAAC,OAAO,GAAG,OAAO,CAAC;QACvB,IAAI,CAAC,OAAO,GAAG,EAAE,CAAC;QAClB,IAAI,CAAC,IAAI,GAAG,OAAO,CAAC,MAAM,EAAE,CAAC;IAC/B,CAAC;IACD,qCAAgB,GAAhB,UAAiB,IAAY;QAC3B,IAAG,IAAI,IAAI,IAAI;YAAE,OAAO,IAAI,CAAC,IAAI,CAAC;QAClC,OAAO,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC;IAC5B,CAAC;IACD,8BAAS,GAAT,UAAU,IAAW,EAAC,IAAW,EAAC,OAAO;QACvC,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,GAAG,OAAO,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC;QAC7C,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,IAAI,EAAC,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC;IACzC,CAAC;IAAA,CAAC;IACJ,iBAAC;AAAD,CAAC,AAnBD,IAmBC"} |
Sorry, the diff of this file is not supported yet
| { | ||
| "name": "@payscale/print-service", | ||
| "version": "1.0.0", | ||
| "lockfileVersion": 1, | ||
| "requires": true, | ||
| "dependencies": { | ||
| "@types/body-parser": { | ||
| "version": "1.17.0", | ||
| "resolved": "https://registry.npmjs.org/@types/body-parser/-/body-parser-1.17.0.tgz", | ||
| "integrity": "sha512-a2+YeUjPkztKJu5aIF2yArYFQQp8d51wZ7DavSHjFuY1mqVgidGyzEQ41JIVNy82fXj8yPgy2vJmfIywgESW6w==", | ||
| "requires": { | ||
| "@types/connect": "*", | ||
| "@types/node": "*" | ||
| }, | ||
| "dependencies": { | ||
| "@types/node": { | ||
| "version": "10.12.18", | ||
| "resolved": "https://registry.npmjs.org/@types/node/-/node-10.12.18.tgz", | ||
| "integrity": "sha512-fh+pAqt4xRzPfqA6eh3Z2y6fyZavRIumvjhaCL753+TVkGKGhpPeyrJG2JftD0T9q4GF00KjefsQ+PQNDdWQaQ==" | ||
| } | ||
| } | ||
| }, | ||
| "@types/connect": { | ||
| "version": "3.4.32", | ||
| "resolved": "https://registry.npmjs.org/@types/connect/-/connect-3.4.32.tgz", | ||
| "integrity": "sha512-4r8qa0quOvh7lGD0pre62CAb1oni1OO6ecJLGCezTmhQ8Fz50Arx9RUszryR8KlgK6avuSXvviL6yWyViQABOg==", | ||
| "requires": { | ||
| "@types/node": "*" | ||
| }, | ||
| "dependencies": { | ||
| "@types/node": { | ||
| "version": "10.12.18", | ||
| "resolved": "https://registry.npmjs.org/@types/node/-/node-10.12.18.tgz", | ||
| "integrity": "sha512-fh+pAqt4xRzPfqA6eh3Z2y6fyZavRIumvjhaCL753+TVkGKGhpPeyrJG2JftD0T9q4GF00KjefsQ+PQNDdWQaQ==" | ||
| } | ||
| } | ||
| }, | ||
| "@types/events": { | ||
| "version": "1.2.0", | ||
| "resolved": "http://registry.npmjs.org/@types/events/-/events-1.2.0.tgz", | ||
| "integrity": "sha512-KEIlhXnIutzKwRbQkGWb/I4HFqBuUykAdHgDED6xqwXJfONCjF5VoE0cXEiurh3XauygxzeDzgtXUqvLkxFzzA==" | ||
| }, | ||
| "@types/express": { | ||
| "version": "4.16.0", | ||
| "resolved": "https://registry.npmjs.org/@types/express/-/express-4.16.0.tgz", | ||
| "integrity": "sha512-TtPEYumsmSTtTetAPXlJVf3kEqb6wZK0bZojpJQrnD/djV4q1oB6QQ8aKvKqwNPACoe02GNiy5zDzcYivR5Z2w==", | ||
| "requires": { | ||
| "@types/body-parser": "*", | ||
| "@types/express-serve-static-core": "*", | ||
| "@types/serve-static": "*" | ||
| } | ||
| }, | ||
| "@types/express-serve-static-core": { | ||
| "version": "4.16.0", | ||
| "resolved": "https://registry.npmjs.org/@types/express-serve-static-core/-/express-serve-static-core-4.16.0.tgz", | ||
| "integrity": "sha512-lTeoCu5NxJU4OD9moCgm0ESZzweAx0YqsAcab6OB0EB3+As1OaHtKnaGJvcngQxYsi9UNv0abn4/DRavrRxt4w==", | ||
| "requires": { | ||
| "@types/events": "*", | ||
| "@types/node": "*", | ||
| "@types/range-parser": "*" | ||
| }, | ||
| "dependencies": { | ||
| "@types/node": { | ||
| "version": "10.12.18", | ||
| "resolved": "https://registry.npmjs.org/@types/node/-/node-10.12.18.tgz", | ||
| "integrity": "sha512-fh+pAqt4xRzPfqA6eh3Z2y6fyZavRIumvjhaCL753+TVkGKGhpPeyrJG2JftD0T9q4GF00KjefsQ+PQNDdWQaQ==" | ||
| } | ||
| } | ||
| }, | ||
| "@types/mime": { | ||
| "version": "2.0.0", | ||
| "resolved": "https://registry.npmjs.org/@types/mime/-/mime-2.0.0.tgz", | ||
| "integrity": "sha512-A2TAGbTFdBw9azHbpVd+/FkdW2T6msN1uct1O9bH3vTerEHKZhTXJUQXy+hNq1B0RagfU8U+KBdqiZpxjhOUQA==" | ||
| }, | ||
| "@types/node": { | ||
| "version": "9.6.41", | ||
| "resolved": "https://registry.npmjs.org/@types/node/-/node-9.6.41.tgz", | ||
| "integrity": "sha512-sPZWEbFMz6qAy9SLY7jh5cgepmsiwqUUHjvEm8lpU6kug2hmmcyuTnwhoGw/GWpI5Npue4EqvsiQQI0eWjW/ZA==", | ||
| "dev": true | ||
| }, | ||
| "@types/range-parser": { | ||
| "version": "1.2.3", | ||
| "resolved": "https://registry.npmjs.org/@types/range-parser/-/range-parser-1.2.3.tgz", | ||
| "integrity": "sha512-ewFXqrQHlFsgc09MK5jP5iR7vumV/BYayNC6PgJO2LPe8vrnNFyjQjSppfEngITi0qvfKtzFvgKymGheFM9UOA==" | ||
| }, | ||
| "@types/serve-static": { | ||
| "version": "1.13.2", | ||
| "resolved": "https://registry.npmjs.org/@types/serve-static/-/serve-static-1.13.2.tgz", | ||
| "integrity": "sha512-/BZ4QRLpH/bNYgZgwhKEh+5AsboDBcUdlBYgzoLX0fpj3Y2gp6EApyOlM3bK53wQS/OE1SrdSYBAbux2D1528Q==", | ||
| "requires": { | ||
| "@types/express-serve-static-core": "*", | ||
| "@types/mime": "*" | ||
| } | ||
| }, | ||
| "@types/swagger-ui-express": { | ||
| "version": "3.0.0", | ||
| "resolved": "https://registry.npmjs.org/@types/swagger-ui-express/-/swagger-ui-express-3.0.0.tgz", | ||
| "integrity": "sha512-NDr7fgTh4govvso8IM8lkzSMuqGfhw7KX5inVohFUMjqAhDJQRfCwTHxzWk9sd/bTLtmSs9ib+A+09tf9QSt4Q==", | ||
| "requires": { | ||
| "@types/express": "*", | ||
| "@types/serve-static": "*" | ||
| } | ||
| }, | ||
| "accepts": { | ||
| "version": "1.3.5", | ||
| "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.5.tgz", | ||
| "integrity": "sha1-63d99gEXI6OxTopywIBcjoZ0a9I=", | ||
| "requires": { | ||
| "mime-types": "~2.1.18", | ||
| "negotiator": "0.6.1" | ||
| } | ||
| }, | ||
| "ajv": { | ||
| "version": "6.6.2", | ||
| "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.6.2.tgz", | ||
| "integrity": "sha512-FBHEW6Jf5TB9MGBgUUA9XHkTbjXYfAUjY43ACMfmdMRHniyoMHjHjzD50OK8LGDWQwp4rWEsIq5kEqq7rvIM1g==", | ||
| "requires": { | ||
| "fast-deep-equal": "^2.0.1", | ||
| "fast-json-stable-stringify": "^2.0.0", | ||
| "json-schema-traverse": "^0.4.1", | ||
| "uri-js": "^4.2.2" | ||
| } | ||
| }, | ||
| "ansi-regex": { | ||
| "version": "2.1.1", | ||
| "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", | ||
| "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=", | ||
| "dev": true | ||
| }, | ||
| "ansi-styles": { | ||
| "version": "3.2.1", | ||
| "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", | ||
| "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", | ||
| "dev": true, | ||
| "requires": { | ||
| "color-convert": "^1.9.0" | ||
| } | ||
| }, | ||
| "argparse": { | ||
| "version": "1.0.10", | ||
| "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", | ||
| "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==", | ||
| "dev": true, | ||
| "requires": { | ||
| "sprintf-js": "~1.0.2" | ||
| } | ||
| }, | ||
| "array-flatten": { | ||
| "version": "1.1.1", | ||
| "resolved": "http://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz", | ||
| "integrity": "sha1-ml9pkFGx5wczKPKgCJaLZOopVdI=" | ||
| }, | ||
| "arrify": { | ||
| "version": "1.0.1", | ||
| "resolved": "https://registry.npmjs.org/arrify/-/arrify-1.0.1.tgz", | ||
| "integrity": "sha1-iYUI2iIm84DfkEcoRWhJwVAaSw0=", | ||
| "dev": true | ||
| }, | ||
| "babel-code-frame": { | ||
| "version": "6.26.0", | ||
| "resolved": "https://registry.npmjs.org/babel-code-frame/-/babel-code-frame-6.26.0.tgz", | ||
| "integrity": "sha1-Y/1D99weO7fONZR9uP42mj9Yx0s=", | ||
| "dev": true, | ||
| "requires": { | ||
| "chalk": "^1.1.3", | ||
| "esutils": "^2.0.2", | ||
| "js-tokens": "^3.0.2" | ||
| }, | ||
| "dependencies": { | ||
| "ansi-styles": { | ||
| "version": "2.2.1", | ||
| "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz", | ||
| "integrity": "sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4=", | ||
| "dev": true | ||
| }, | ||
| "chalk": { | ||
| "version": "1.1.3", | ||
| "resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz", | ||
| "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=", | ||
| "dev": true, | ||
| "requires": { | ||
| "ansi-styles": "^2.2.1", | ||
| "escape-string-regexp": "^1.0.2", | ||
| "has-ansi": "^2.0.0", | ||
| "strip-ansi": "^3.0.0", | ||
| "supports-color": "^2.0.0" | ||
| } | ||
| }, | ||
| "supports-color": { | ||
| "version": "2.0.0", | ||
| "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz", | ||
| "integrity": "sha1-U10EXOa2Nj+kARcIRimZXp3zJMc=", | ||
| "dev": true | ||
| } | ||
| } | ||
| }, | ||
| "balanced-match": { | ||
| "version": "1.0.0", | ||
| "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz", | ||
| "integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c=" | ||
| }, | ||
| "bluebird": { | ||
| "version": "3.5.3", | ||
| "resolved": "https://registry.npmjs.org/bluebird/-/bluebird-3.5.3.tgz", | ||
| "integrity": "sha512-/qKPUQlaW1OyR51WeCPBvRnAlnZFUJkCSG5HzGnuIqhgyJtF+T94lFnn33eiazjRm2LAHVy2guNnaq48X9SJuw==" | ||
| }, | ||
| "body-parser": { | ||
| "version": "1.18.3", | ||
| "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.18.3.tgz", | ||
| "integrity": "sha1-WykhmP/dVTs6DyDe0FkrlWlVyLQ=", | ||
| "requires": { | ||
| "bytes": "3.0.0", | ||
| "content-type": "~1.0.4", | ||
| "debug": "2.6.9", | ||
| "depd": "~1.1.2", | ||
| "http-errors": "~1.6.3", | ||
| "iconv-lite": "0.4.23", | ||
| "on-finished": "~2.3.0", | ||
| "qs": "6.5.2", | ||
| "raw-body": "2.3.3", | ||
| "type-is": "~1.6.16" | ||
| }, | ||
| "dependencies": { | ||
| "debug": { | ||
| "version": "2.6.9", | ||
| "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", | ||
| "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", | ||
| "requires": { | ||
| "ms": "2.0.0" | ||
| } | ||
| }, | ||
| "ms": { | ||
| "version": "2.0.0", | ||
| "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", | ||
| "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=" | ||
| } | ||
| } | ||
| }, | ||
| "brace-expansion": { | ||
| "version": "1.1.11", | ||
| "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", | ||
| "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", | ||
| "requires": { | ||
| "balanced-match": "^1.0.0", | ||
| "concat-map": "0.0.1" | ||
| } | ||
| }, | ||
| "buffer-from": { | ||
| "version": "1.1.1", | ||
| "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.1.tgz", | ||
| "integrity": "sha512-MQcXEUbCKtEo7bhqEs6560Hyd4XaovZlO/k9V3hjVUF/zwW7KBVdSK4gIt/bzwS9MbR5qob+F5jusZsb0YQK2A==", | ||
| "dev": true | ||
| }, | ||
| "builtin-modules": { | ||
| "version": "1.1.1", | ||
| "resolved": "https://registry.npmjs.org/builtin-modules/-/builtin-modules-1.1.1.tgz", | ||
| "integrity": "sha1-Jw8HbFpywC9bZaR9+Uxf46J4iS8=", | ||
| "dev": true | ||
| }, | ||
| "bytes": { | ||
| "version": "3.0.0", | ||
| "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.0.0.tgz", | ||
| "integrity": "sha1-0ygVQE1olpn4Wk6k+odV3ROpYEg=" | ||
| }, | ||
| "chalk": { | ||
| "version": "2.4.1", | ||
| "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.1.tgz", | ||
| "integrity": "sha512-ObN6h1v2fTJSmUXoS3nMQ92LbDK9be4TV+6G+omQlGJFdcUX5heKi1LZ1YnRMIgwTLEj3E24bT6tYni50rlCfQ==", | ||
| "dev": true, | ||
| "requires": { | ||
| "ansi-styles": "^3.2.1", | ||
| "escape-string-regexp": "^1.0.5", | ||
| "supports-color": "^5.3.0" | ||
| } | ||
| }, | ||
| "color-convert": { | ||
| "version": "1.9.3", | ||
| "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", | ||
| "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", | ||
| "dev": true, | ||
| "requires": { | ||
| "color-name": "1.1.3" | ||
| } | ||
| }, | ||
| "color-name": { | ||
| "version": "1.1.3", | ||
| "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", | ||
| "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=", | ||
| "dev": true | ||
| }, | ||
| "commander": { | ||
| "version": "2.19.0", | ||
| "resolved": "https://registry.npmjs.org/commander/-/commander-2.19.0.tgz", | ||
| "integrity": "sha512-6tvAOO+D6OENvRAh524Dh9jcfKTYDQAqvqezbCW82xj5X0pSrcpxtvRKHLG0yBY6SD7PSDrJaj+0AiOcKVd1Xg==" | ||
| }, | ||
| "concat-map": { | ||
| "version": "0.0.1", | ||
| "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", | ||
| "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=" | ||
| }, | ||
| "content-disposition": { | ||
| "version": "0.5.2", | ||
| "resolved": "http://registry.npmjs.org/content-disposition/-/content-disposition-0.5.2.tgz", | ||
| "integrity": "sha1-DPaLud318r55YcOoUXjLhdunjLQ=" | ||
| }, | ||
| "content-type": { | ||
| "version": "1.0.4", | ||
| "resolved": "https://registry.npmjs.org/content-type/-/content-type-1.0.4.tgz", | ||
| "integrity": "sha512-hIP3EEPs8tB9AT1L+NUqtwOAps4mk2Zob89MWXMHjHWg9milF/j4osnnQLXBCBFBk/tvIG/tUc9mOUJiPBhPXA==" | ||
| }, | ||
| "cookie": { | ||
| "version": "0.3.1", | ||
| "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.3.1.tgz", | ||
| "integrity": "sha1-5+Ch+e9DtMi6klxcWpboBtFoc7s=" | ||
| }, | ||
| "cookie-signature": { | ||
| "version": "1.0.6", | ||
| "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz", | ||
| "integrity": "sha1-4wOogrNCzD7oylE6eZmXNNqzriw=" | ||
| }, | ||
| "debug": { | ||
| "version": "4.0.1", | ||
| "resolved": "https://registry.npmjs.org/debug/-/debug-4.0.1.tgz", | ||
| "integrity": "sha512-K23FHJ/Mt404FSlp6gSZCevIbTMLX0j3fmHhUEhQ3Wq0FMODW3+cUSoLdy1Gx4polAf4t/lphhmHH35BB8cLYw==", | ||
| "requires": { | ||
| "ms": "^2.1.1" | ||
| } | ||
| }, | ||
| "depd": { | ||
| "version": "1.1.2", | ||
| "resolved": "https://registry.npmjs.org/depd/-/depd-1.1.2.tgz", | ||
| "integrity": "sha1-m81S4UwJd2PnSbJ0xDRu0uVgtak=" | ||
| }, | ||
| "destroy": { | ||
| "version": "1.0.4", | ||
| "resolved": "https://registry.npmjs.org/destroy/-/destroy-1.0.4.tgz", | ||
| "integrity": "sha1-l4hXRCxEdJ5CBmE+N5RiBYJqvYA=" | ||
| }, | ||
| "diff": { | ||
| "version": "3.5.0", | ||
| "resolved": "https://registry.npmjs.org/diff/-/diff-3.5.0.tgz", | ||
| "integrity": "sha512-A46qtFgd+g7pDZinpnwiRJtxbC1hpgf0uzP3iG89scHk0AUC7A1TGxf5OiiOUv/JMZR8GOt8hL900hV0bOy5xA==", | ||
| "dev": true | ||
| }, | ||
| "doctrine": { | ||
| "version": "3.0.0", | ||
| "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-3.0.0.tgz", | ||
| "integrity": "sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w==", | ||
| "requires": { | ||
| "esutils": "^2.0.2" | ||
| } | ||
| }, | ||
| "ee-first": { | ||
| "version": "1.1.1", | ||
| "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz", | ||
| "integrity": "sha1-WQxhFWsK4vTwJVcyoViyZrxWsh0=" | ||
| }, | ||
| "encodeurl": { | ||
| "version": "1.0.2", | ||
| "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz", | ||
| "integrity": "sha1-rT/0yG7C0CkyL1oCw6mmBslbP1k=" | ||
| }, | ||
| "escape-html": { | ||
| "version": "1.0.3", | ||
| "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz", | ||
| "integrity": "sha1-Aljq5NPQwJdN4cFpGI7wBR0dGYg=" | ||
| }, | ||
| "escape-string-regexp": { | ||
| "version": "1.0.5", | ||
| "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", | ||
| "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=", | ||
| "dev": true | ||
| }, | ||
| "esprima": { | ||
| "version": "4.0.1", | ||
| "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz", | ||
| "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==", | ||
| "dev": true | ||
| }, | ||
| "esutils": { | ||
| "version": "2.0.2", | ||
| "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.2.tgz", | ||
| "integrity": "sha1-Cr9PHKpbyx96nYrMbepPqqBLrJs=" | ||
| }, | ||
| "etag": { | ||
| "version": "1.8.1", | ||
| "resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz", | ||
| "integrity": "sha1-Qa4u62XvpiJorr/qg6x9eSmbCIc=" | ||
| }, | ||
| "express": { | ||
| "version": "4.16.4", | ||
| "resolved": "https://registry.npmjs.org/express/-/express-4.16.4.tgz", | ||
| "integrity": "sha512-j12Uuyb4FMrd/qQAm6uCHAkPtO8FDTRJZBDd5D2KOL2eLaz1yUNdUB/NOIyq0iU4q4cFarsUCrnFDPBcnksuOg==", | ||
| "requires": { | ||
| "accepts": "~1.3.5", | ||
| "array-flatten": "1.1.1", | ||
| "body-parser": "1.18.3", | ||
| "content-disposition": "0.5.2", | ||
| "content-type": "~1.0.4", | ||
| "cookie": "0.3.1", | ||
| "cookie-signature": "1.0.6", | ||
| "debug": "2.6.9", | ||
| "depd": "~1.1.2", | ||
| "encodeurl": "~1.0.2", | ||
| "escape-html": "~1.0.3", | ||
| "etag": "~1.8.1", | ||
| "finalhandler": "1.1.1", | ||
| "fresh": "0.5.2", | ||
| "merge-descriptors": "1.0.1", | ||
| "methods": "~1.1.2", | ||
| "on-finished": "~2.3.0", | ||
| "parseurl": "~1.3.2", | ||
| "path-to-regexp": "0.1.7", | ||
| "proxy-addr": "~2.0.4", | ||
| "qs": "6.5.2", | ||
| "range-parser": "~1.2.0", | ||
| "safe-buffer": "5.1.2", | ||
| "send": "0.16.2", | ||
| "serve-static": "1.13.2", | ||
| "setprototypeof": "1.1.0", | ||
| "statuses": "~1.4.0", | ||
| "type-is": "~1.6.16", | ||
| "utils-merge": "1.0.1", | ||
| "vary": "~1.1.2" | ||
| }, | ||
| "dependencies": { | ||
| "debug": { | ||
| "version": "2.6.9", | ||
| "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", | ||
| "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", | ||
| "requires": { | ||
| "ms": "2.0.0" | ||
| } | ||
| }, | ||
| "ms": { | ||
| "version": "2.0.0", | ||
| "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", | ||
| "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=" | ||
| } | ||
| } | ||
| }, | ||
| "fast-deep-equal": { | ||
| "version": "2.0.1", | ||
| "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-2.0.1.tgz", | ||
| "integrity": "sha1-ewUhjd+WZ79/Nwv3/bLLFf3Qqkk=" | ||
| }, | ||
| "fast-json-stable-stringify": { | ||
| "version": "2.0.0", | ||
| "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.0.0.tgz", | ||
| "integrity": "sha1-1RQsDK7msRifh9OnYREGT4bIu/I=" | ||
| }, | ||
| "finalhandler": { | ||
| "version": "1.1.1", | ||
| "resolved": "http://registry.npmjs.org/finalhandler/-/finalhandler-1.1.1.tgz", | ||
| "integrity": "sha512-Y1GUDo39ez4aHAw7MysnUD5JzYX+WaIj8I57kO3aEPT1fFRL4sr7mjei97FgnwhAyyzRYmQZaTHb2+9uZ1dPtg==", | ||
| "requires": { | ||
| "debug": "2.6.9", | ||
| "encodeurl": "~1.0.2", | ||
| "escape-html": "~1.0.3", | ||
| "on-finished": "~2.3.0", | ||
| "parseurl": "~1.3.2", | ||
| "statuses": "~1.4.0", | ||
| "unpipe": "~1.0.0" | ||
| }, | ||
| "dependencies": { | ||
| "debug": { | ||
| "version": "2.6.9", | ||
| "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", | ||
| "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", | ||
| "requires": { | ||
| "ms": "2.0.0" | ||
| } | ||
| }, | ||
| "ms": { | ||
| "version": "2.0.0", | ||
| "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", | ||
| "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=" | ||
| } | ||
| } | ||
| }, | ||
| "find-root": { | ||
| "version": "1.1.0", | ||
| "resolved": "https://registry.npmjs.org/find-root/-/find-root-1.1.0.tgz", | ||
| "integrity": "sha512-NKfW6bec6GfKc0SGx1e07QZY9PE99u0Bft/0rzSD5k3sO/vwkVUpDUKVm5Gpp5Ue3YfShPFTX2070tDs5kB9Ng==" | ||
| }, | ||
| "forwarded": { | ||
| "version": "0.1.2", | ||
| "resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.1.2.tgz", | ||
| "integrity": "sha1-mMI9qxF1ZXuMBXPozszZGw/xjIQ=" | ||
| }, | ||
| "fresh": { | ||
| "version": "0.5.2", | ||
| "resolved": "https://registry.npmjs.org/fresh/-/fresh-0.5.2.tgz", | ||
| "integrity": "sha1-PYyt2Q2XZWn6g1qx+OSyOhBWBac=" | ||
| }, | ||
| "fs.realpath": { | ||
| "version": "1.0.0", | ||
| "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", | ||
| "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=" | ||
| }, | ||
| "glob": { | ||
| "version": "7.1.3", | ||
| "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.3.tgz", | ||
| "integrity": "sha512-vcfuiIxogLV4DlGBHIUOwI0IbrJ8HWPc4MU7HzviGeNho/UJDfi6B5p3sHeWIQ0KGIU0Jpxi5ZHxemQfLkkAwQ==", | ||
| "requires": { | ||
| "fs.realpath": "^1.0.0", | ||
| "inflight": "^1.0.4", | ||
| "inherits": "2", | ||
| "minimatch": "^3.0.4", | ||
| "once": "^1.3.0", | ||
| "path-is-absolute": "^1.0.0" | ||
| } | ||
| }, | ||
| "has-ansi": { | ||
| "version": "2.0.0", | ||
| "resolved": "https://registry.npmjs.org/has-ansi/-/has-ansi-2.0.0.tgz", | ||
| "integrity": "sha1-NPUEnOHs3ysGSa8+8k5F7TVBbZE=", | ||
| "dev": true, | ||
| "requires": { | ||
| "ansi-regex": "^2.0.0" | ||
| } | ||
| }, | ||
| "has-flag": { | ||
| "version": "3.0.0", | ||
| "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", | ||
| "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=", | ||
| "dev": true | ||
| }, | ||
| "http-errors": { | ||
| "version": "1.6.3", | ||
| "resolved": "http://registry.npmjs.org/http-errors/-/http-errors-1.6.3.tgz", | ||
| "integrity": "sha1-i1VoC7S+KDoLW/TqLjhYC+HZMg0=", | ||
| "requires": { | ||
| "depd": "~1.1.2", | ||
| "inherits": "2.0.3", | ||
| "setprototypeof": "1.1.0", | ||
| "statuses": ">= 1.4.0 < 2" | ||
| } | ||
| }, | ||
| "iconv-lite": { | ||
| "version": "0.4.23", | ||
| "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.23.tgz", | ||
| "integrity": "sha512-neyTUVFtahjf0mB3dZT77u+8O0QB89jFdnBkd5P1JgYPbPaia3gXXOVL2fq8VyU2gMMD7SaN7QukTB/pmXYvDA==", | ||
| "requires": { | ||
| "safer-buffer": ">= 2.1.2 < 3" | ||
| } | ||
| }, | ||
| "inflight": { | ||
| "version": "1.0.6", | ||
| "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", | ||
| "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=", | ||
| "requires": { | ||
| "once": "^1.3.0", | ||
| "wrappy": "1" | ||
| } | ||
| }, | ||
| "inherits": { | ||
| "version": "2.0.3", | ||
| "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", | ||
| "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=" | ||
| }, | ||
| "ipaddr.js": { | ||
| "version": "1.8.0", | ||
| "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.8.0.tgz", | ||
| "integrity": "sha1-6qM9bd16zo9/b+DJygRA5wZzix4=" | ||
| }, | ||
| "js-tokens": { | ||
| "version": "3.0.2", | ||
| "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-3.0.2.tgz", | ||
| "integrity": "sha1-mGbfOVECEw449/mWvOtlRDIJwls=", | ||
| "dev": true | ||
| }, | ||
| "js-yaml": { | ||
| "version": "3.13.1", | ||
| "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.13.1.tgz", | ||
| "integrity": "sha512-YfbcO7jXDdyj0DGxYVSlSeQNHbD7XPWvrVWeVUujrQEoZzWJIRrCPoyk6kL6IAjAG2IolMK4T0hNUe0HOUs5Jw==", | ||
| "dev": true, | ||
| "requires": { | ||
| "argparse": "^1.0.7", | ||
| "esprima": "^4.0.0" | ||
| } | ||
| }, | ||
| "json-schema-traverse": { | ||
| "version": "0.4.1", | ||
| "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", | ||
| "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==" | ||
| }, | ||
| "make-error": { | ||
| "version": "1.3.5", | ||
| "resolved": "https://registry.npmjs.org/make-error/-/make-error-1.3.5.tgz", | ||
| "integrity": "sha512-c3sIjNUow0+8swNwVpqoH4YCShKNFkMaw6oH1mNS2haDZQqkeZFlHS3dhoeEbKKmJB4vXpJucU6oH75aDYeE9g==", | ||
| "dev": true | ||
| }, | ||
| "media-typer": { | ||
| "version": "0.3.0", | ||
| "resolved": "http://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz", | ||
| "integrity": "sha1-hxDXrwqmJvj/+hzgAWhUUmMlV0g=" | ||
| }, | ||
| "merge-descriptors": { | ||
| "version": "1.0.1", | ||
| "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.1.tgz", | ||
| "integrity": "sha1-sAqqVW3YtEVoFQ7J0blT8/kMu2E=" | ||
| }, | ||
| "methods": { | ||
| "version": "1.1.2", | ||
| "resolved": "https://registry.npmjs.org/methods/-/methods-1.1.2.tgz", | ||
| "integrity": "sha1-VSmk1nZUE07cxSZmVoNbD4Ua/O4=" | ||
| }, | ||
| "mime": { | ||
| "version": "1.4.1", | ||
| "resolved": "https://registry.npmjs.org/mime/-/mime-1.4.1.tgz", | ||
| "integrity": "sha512-KI1+qOZu5DcW6wayYHSzR/tXKCDC5Om4s1z2QJjDULzLcmf3DvzS7oluY4HCTrc+9FiKmWUgeNLg7W3uIQvxtQ==" | ||
| }, | ||
| "mime-db": { | ||
| "version": "1.37.0", | ||
| "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.37.0.tgz", | ||
| "integrity": "sha512-R3C4db6bgQhlIhPU48fUtdVmKnflq+hRdad7IyKhtFj06VPNVdk2RhiYL3UjQIlso8L+YxAtFkobT0VK+S/ybg==" | ||
| }, | ||
| "mime-types": { | ||
| "version": "2.1.21", | ||
| "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.21.tgz", | ||
| "integrity": "sha512-3iL6DbwpyLzjR3xHSFNFeb9Nz/M8WDkX33t1GFQnFOllWk8pOrh/LSrB5OXlnlW5P9LH73X6loW/eogc+F5lJg==", | ||
| "requires": { | ||
| "mime-db": "~1.37.0" | ||
| } | ||
| }, | ||
| "minimatch": { | ||
| "version": "3.0.4", | ||
| "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", | ||
| "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==", | ||
| "requires": { | ||
| "brace-expansion": "^1.1.7" | ||
| } | ||
| }, | ||
| "minimist": { | ||
| "version": "0.0.8", | ||
| "resolved": "http://registry.npmjs.org/minimist/-/minimist-0.0.8.tgz", | ||
| "integrity": "sha1-hX/Kv8M5fSYluCKCYuhqp6ARsF0=" | ||
| }, | ||
| "mkdirp": { | ||
| "version": "0.5.1", | ||
| "resolved": "http://registry.npmjs.org/mkdirp/-/mkdirp-0.5.1.tgz", | ||
| "integrity": "sha1-MAV0OOrGz3+MR2fzhkjWaX11yQM=", | ||
| "requires": { | ||
| "minimist": "0.0.8" | ||
| } | ||
| }, | ||
| "ms": { | ||
| "version": "2.1.1", | ||
| "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.1.tgz", | ||
| "integrity": "sha512-tgp+dl5cGk28utYktBsrFqA7HKgrhgPsg6Z/EfhWI4gl1Hwq8B/GmY/0oXZ6nF8hDVesS/FpnYaD/kOWhYQvyg==" | ||
| }, | ||
| "negotiator": { | ||
| "version": "0.6.1", | ||
| "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.1.tgz", | ||
| "integrity": "sha1-KzJxhOiZIQEXeyhWP7XnECrNDKk=" | ||
| }, | ||
| "on-finished": { | ||
| "version": "2.3.0", | ||
| "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.3.0.tgz", | ||
| "integrity": "sha1-IPEzZIGwg811M3mSoWlxqi2QaUc=", | ||
| "requires": { | ||
| "ee-first": "1.1.1" | ||
| } | ||
| }, | ||
| "once": { | ||
| "version": "1.4.0", | ||
| "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", | ||
| "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", | ||
| "requires": { | ||
| "wrappy": "1" | ||
| } | ||
| }, | ||
| "parseurl": { | ||
| "version": "1.3.2", | ||
| "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.2.tgz", | ||
| "integrity": "sha1-/CidTtiZMRlGDBViUyYs3I3mW/M=" | ||
| }, | ||
| "path-is-absolute": { | ||
| "version": "1.0.1", | ||
| "resolved": "http://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", | ||
| "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=" | ||
| }, | ||
| "path-parse": { | ||
| "version": "1.0.6", | ||
| "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.6.tgz", | ||
| "integrity": "sha512-GSmOT2EbHrINBf9SR7CDELwlJ8AENk3Qn7OikK4nFYAu3Ote2+JYNVvkpAEQm3/TLNEJFD/xZJjzyxg3KBWOzw==", | ||
| "dev": true | ||
| }, | ||
| "path-to-regexp": { | ||
| "version": "0.1.7", | ||
| "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.7.tgz", | ||
| "integrity": "sha1-32BBeABfUi8V60SQ5yR6G/qmf4w=" | ||
| }, | ||
| "proxy-addr": { | ||
| "version": "2.0.4", | ||
| "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.4.tgz", | ||
| "integrity": "sha512-5erio2h9jp5CHGwcybmxmVqHmnCBZeewlfJ0pex+UW7Qny7OOZXTtH56TGNyBizkgiOwhJtMKrVzDTeKcySZwA==", | ||
| "requires": { | ||
| "forwarded": "~0.1.2", | ||
| "ipaddr.js": "1.8.0" | ||
| } | ||
| }, | ||
| "punycode": { | ||
| "version": "2.1.1", | ||
| "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.1.1.tgz", | ||
| "integrity": "sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A==" | ||
| }, | ||
| "qs": { | ||
| "version": "6.5.2", | ||
| "resolved": "https://registry.npmjs.org/qs/-/qs-6.5.2.tgz", | ||
| "integrity": "sha512-N5ZAX4/LxJmF+7wN74pUD6qAh9/wnvdQcjq9TZjevvXzSUo7bfmw91saqMjzGS2xq91/odN2dW/WOl7qQHNDGA==" | ||
| }, | ||
| "range-parser": { | ||
| "version": "1.2.0", | ||
| "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.0.tgz", | ||
| "integrity": "sha1-9JvmtIeJTdxA3MlKMi9hEJLgDV4=" | ||
| }, | ||
| "raw-body": { | ||
| "version": "2.3.3", | ||
| "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.3.3.tgz", | ||
| "integrity": "sha512-9esiElv1BrZoI3rCDuOuKCBRbuApGGaDPQfjSflGxdy4oyzqghxu6klEkkVIvBje+FF0BX9coEv8KqW6X/7njw==", | ||
| "requires": { | ||
| "bytes": "3.0.0", | ||
| "http-errors": "1.6.3", | ||
| "iconv-lite": "0.4.23", | ||
| "unpipe": "1.0.0" | ||
| } | ||
| }, | ||
| "reflect-metadata": { | ||
| "version": "0.1.12", | ||
| "resolved": "https://registry.npmjs.org/reflect-metadata/-/reflect-metadata-0.1.12.tgz", | ||
| "integrity": "sha512-n+IyV+nGz3+0q3/Yf1ra12KpCyi001bi4XFxSjbiWWjfqb52iTTtpGXmCCAOWWIAn9KEuFZKGqBERHmrtScZ3A==" | ||
| }, | ||
| "resolve": { | ||
| "version": "1.9.0", | ||
| "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.9.0.tgz", | ||
| "integrity": "sha512-TZNye00tI67lwYvzxCxHGjwTNlUV70io54/Ed4j6PscB8xVfuBJpRenI/o6dVk0cY0PYTY27AgCoGGxRnYuItQ==", | ||
| "dev": true, | ||
| "requires": { | ||
| "path-parse": "^1.0.6" | ||
| } | ||
| }, | ||
| "safe-buffer": { | ||
| "version": "5.1.2", | ||
| "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", | ||
| "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" | ||
| }, | ||
| "safer-buffer": { | ||
| "version": "2.1.2", | ||
| "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", | ||
| "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==" | ||
| }, | ||
| "semver": { | ||
| "version": "5.6.0", | ||
| "resolved": "https://registry.npmjs.org/semver/-/semver-5.6.0.tgz", | ||
| "integrity": "sha512-RS9R6R35NYgQn++fkDWaOmqGoj4Ek9gGs+DPxNUZKuwE183xjJroKvyo1IzVFeXvUrvmALy6FWD5xrdJT25gMg==", | ||
| "dev": true | ||
| }, | ||
| "send": { | ||
| "version": "0.16.2", | ||
| "resolved": "https://registry.npmjs.org/send/-/send-0.16.2.tgz", | ||
| "integrity": "sha512-E64YFPUssFHEFBvpbbjr44NCLtI1AohxQ8ZSiJjQLskAdKuriYEP6VyGEsRDH8ScozGpkaX1BGvhanqCwkcEZw==", | ||
| "requires": { | ||
| "debug": "2.6.9", | ||
| "depd": "~1.1.2", | ||
| "destroy": "~1.0.4", | ||
| "encodeurl": "~1.0.2", | ||
| "escape-html": "~1.0.3", | ||
| "etag": "~1.8.1", | ||
| "fresh": "0.5.2", | ||
| "http-errors": "~1.6.2", | ||
| "mime": "1.4.1", | ||
| "ms": "2.0.0", | ||
| "on-finished": "~2.3.0", | ||
| "range-parser": "~1.2.0", | ||
| "statuses": "~1.4.0" | ||
| }, | ||
| "dependencies": { | ||
| "debug": { | ||
| "version": "2.6.9", | ||
| "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", | ||
| "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", | ||
| "requires": { | ||
| "ms": "2.0.0" | ||
| } | ||
| }, | ||
| "ms": { | ||
| "version": "2.0.0", | ||
| "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", | ||
| "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=" | ||
| } | ||
| } | ||
| }, | ||
| "serve-static": { | ||
| "version": "1.13.2", | ||
| "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.13.2.tgz", | ||
| "integrity": "sha512-p/tdJrO4U387R9oMjb1oj7qSMaMfmOyd4j9hOFoxZe2baQszgHcSWjuya/CiT5kgZZKRudHNOA0pYXOl8rQ5nw==", | ||
| "requires": { | ||
| "encodeurl": "~1.0.2", | ||
| "escape-html": "~1.0.3", | ||
| "parseurl": "~1.3.2", | ||
| "send": "0.16.2" | ||
| } | ||
| }, | ||
| "setprototypeof": { | ||
| "version": "1.1.0", | ||
| "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.1.0.tgz", | ||
| "integrity": "sha512-BvE/TwpZX4FXExxOxZyRGQQv651MSwmWKZGqvmPcRIjDqWub67kTKuIMx43cZZrS/cBBzwBcNDWoFxt2XEFIpQ==" | ||
| }, | ||
| "source-map": { | ||
| "version": "0.6.1", | ||
| "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", | ||
| "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", | ||
| "dev": true | ||
| }, | ||
| "source-map-support": { | ||
| "version": "0.5.9", | ||
| "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.9.tgz", | ||
| "integrity": "sha512-gR6Rw4MvUlYy83vP0vxoVNzM6t8MUXqNuRsuBmBHQDu1Fh6X015FrLdgoDKcNdkwGubozq0P4N0Q37UyFVr1EA==", | ||
| "dev": true, | ||
| "requires": { | ||
| "buffer-from": "^1.0.0", | ||
| "source-map": "^0.6.0" | ||
| } | ||
| }, | ||
| "sprintf-js": { | ||
| "version": "1.0.3", | ||
| "resolved": "http://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", | ||
| "integrity": "sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw=", | ||
| "dev": true | ||
| }, | ||
| "statuses": { | ||
| "version": "1.4.0", | ||
| "resolved": "https://registry.npmjs.org/statuses/-/statuses-1.4.0.tgz", | ||
| "integrity": "sha512-zhSCtt8v2NDrRlPQpCNtw/heZLtfUDqxBM1udqikb/Hbk52LK4nQSwr10u77iopCW5LsyHpuXS0GnEc48mLeew==" | ||
| }, | ||
| "strip-ansi": { | ||
| "version": "3.0.1", | ||
| "resolved": "http://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", | ||
| "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", | ||
| "dev": true, | ||
| "requires": { | ||
| "ansi-regex": "^2.0.0" | ||
| } | ||
| }, | ||
| "supports-color": { | ||
| "version": "5.5.0", | ||
| "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", | ||
| "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", | ||
| "dev": true, | ||
| "requires": { | ||
| "has-flag": "^3.0.0" | ||
| } | ||
| }, | ||
| "swagger-ui-dist": { | ||
| "version": "3.20.4", | ||
| "resolved": "https://registry.npmjs.org/swagger-ui-dist/-/swagger-ui-dist-3.20.4.tgz", | ||
| "integrity": "sha512-SR/N+N7EIncEhyA4UGiMQ12vJBSv5OKO4S1g7E7etO+9ZUV6SZ7SqKVC8RDDyMOJzdXgMXV7aGIBIiMSCbEMJw==" | ||
| }, | ||
| "swagger-ui-express": { | ||
| "version": "4.0.2", | ||
| "resolved": "https://registry.npmjs.org/swagger-ui-express/-/swagger-ui-express-4.0.2.tgz", | ||
| "integrity": "sha512-XZtXI2+SKT3fgvJSGg4P7Dtmkzr50uoSb09IxbUWmjL538TIGRMZtfdEkjZEEq44xgGNAxMryzBEUdUnkXr8dA==", | ||
| "requires": { | ||
| "swagger-ui-dist": "^3.18.1" | ||
| } | ||
| }, | ||
| "ts-api": { | ||
| "version": "2.6.8", | ||
| "resolved": "https://registry.npmjs.org/ts-api/-/ts-api-2.6.8.tgz", | ||
| "integrity": "sha512-yItvFmtE1VDyT2x8PtoyxMhLeDtwJgUxnLiJPff0082ezkxB6DwFJ0/hpJ2ewzUBHCyHxK87/fddq1QhXM0iWw==", | ||
| "requires": { | ||
| "@types/node": "^8.10.0", | ||
| "@types/swagger-ui-express": "^3.0.0", | ||
| "ajv": "^6.3.0", | ||
| "bluebird": "x", | ||
| "commander": "^2.15.1", | ||
| "doctrine": "x", | ||
| "express": "^4.16.3", | ||
| "find-root": "x", | ||
| "glob": "^7.1.2", | ||
| "mkdirp": "^0.5.1", | ||
| "reflect-metadata": "^0.1.12", | ||
| "swagger-ui-express": "^4.0.1", | ||
| "typescript": "^3.1", | ||
| "uuid": "^3.3.2" | ||
| }, | ||
| "dependencies": { | ||
| "@types/node": { | ||
| "version": "8.10.39", | ||
| "resolved": "https://registry.npmjs.org/@types/node/-/node-8.10.39.tgz", | ||
| "integrity": "sha512-rE7fktr02J8ybFf6eysife+WF+L4sAHWzw09DgdCebEu+qDwMvv4zl6Bc+825ttGZP73kCKxa3dhJOoGJ8+5mA==" | ||
| } | ||
| } | ||
| }, | ||
| "ts-node": { | ||
| "version": "5.0.1", | ||
| "resolved": "https://registry.npmjs.org/ts-node/-/ts-node-5.0.1.tgz", | ||
| "integrity": "sha512-XK7QmDcNHVmZkVtkiwNDWiERRHPyU8nBqZB1+iv2UhOG0q3RQ9HsZ2CMqISlFbxjrYFGfG2mX7bW4dAyxBVzUw==", | ||
| "dev": true, | ||
| "requires": { | ||
| "arrify": "^1.0.0", | ||
| "chalk": "^2.3.0", | ||
| "diff": "^3.1.0", | ||
| "make-error": "^1.1.1", | ||
| "minimist": "^1.2.0", | ||
| "mkdirp": "^0.5.1", | ||
| "source-map-support": "^0.5.3", | ||
| "yn": "^2.0.0" | ||
| }, | ||
| "dependencies": { | ||
| "minimist": { | ||
| "version": "1.2.0", | ||
| "resolved": "http://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz", | ||
| "integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=", | ||
| "dev": true | ||
| } | ||
| } | ||
| }, | ||
| "tslib": { | ||
| "version": "1.9.3", | ||
| "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.9.3.tgz", | ||
| "integrity": "sha512-4krF8scpejhaOgqzBEcGM7yDIEfi0/8+8zDRZhNZZ2kjmHJ4hv3zCbQWxoJGz1iw5U0Jl0nma13xzHXcncMavQ==", | ||
| "dev": true | ||
| }, | ||
| "tslint": { | ||
| "version": "5.12.0", | ||
| "resolved": "https://registry.npmjs.org/tslint/-/tslint-5.12.0.tgz", | ||
| "integrity": "sha512-CKEcH1MHUBhoV43SA/Jmy1l24HJJgI0eyLbBNSRyFlsQvb9v6Zdq+Nz2vEOH00nC5SUx4SneJ59PZUS/ARcokQ==", | ||
| "dev": true, | ||
| "requires": { | ||
| "babel-code-frame": "^6.22.0", | ||
| "builtin-modules": "^1.1.1", | ||
| "chalk": "^2.3.0", | ||
| "commander": "^2.12.1", | ||
| "diff": "^3.2.0", | ||
| "glob": "^7.1.1", | ||
| "js-yaml": "^3.7.0", | ||
| "minimatch": "^3.0.4", | ||
| "resolve": "^1.3.2", | ||
| "semver": "^5.3.0", | ||
| "tslib": "^1.8.0", | ||
| "tsutils": "^2.27.2" | ||
| } | ||
| }, | ||
| "tsutils": { | ||
| "version": "2.29.0", | ||
| "resolved": "https://registry.npmjs.org/tsutils/-/tsutils-2.29.0.tgz", | ||
| "integrity": "sha512-g5JVHCIJwzfISaXpXE1qvNalca5Jwob6FjI4AoPlqMusJ6ftFE7IkkFoMhVLRgK+4Kx3gkzb8UZK5t5yTTvEmA==", | ||
| "dev": true, | ||
| "requires": { | ||
| "tslib": "^1.8.1" | ||
| } | ||
| }, | ||
| "type-is": { | ||
| "version": "1.6.16", | ||
| "resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.16.tgz", | ||
| "integrity": "sha512-HRkVv/5qY2G6I8iab9cI7v1bOIdhm94dVjQCPFElW9W+3GeDOSHmy2EBYe4VTApuzolPcmgFTN3ftVJRKR2J9Q==", | ||
| "requires": { | ||
| "media-typer": "0.3.0", | ||
| "mime-types": "~2.1.18" | ||
| } | ||
| }, | ||
| "typescript": { | ||
| "version": "3.2.2", | ||
| "resolved": "https://registry.npmjs.org/typescript/-/typescript-3.2.2.tgz", | ||
| "integrity": "sha512-VCj5UiSyHBjwfYacmDuc/NOk4QQixbE+Wn7MFJuS0nRuPQbof132Pw4u53dm264O8LPc2MVsc7RJNml5szurkg==" | ||
| }, | ||
| "unpipe": { | ||
| "version": "1.0.0", | ||
| "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz", | ||
| "integrity": "sha1-sr9O6FFKrmFltIF4KdIbLvSZBOw=" | ||
| }, | ||
| "uri-js": { | ||
| "version": "4.2.2", | ||
| "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.2.2.tgz", | ||
| "integrity": "sha512-KY9Frmirql91X2Qgjry0Wd4Y+YTdrdZheS8TFwvkbLWf/G5KNJDCh6pKL5OZctEW4+0Baa5idK2ZQuELRwPznQ==", | ||
| "requires": { | ||
| "punycode": "^2.1.0" | ||
| } | ||
| }, | ||
| "utils-merge": { | ||
| "version": "1.0.1", | ||
| "resolved": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.1.tgz", | ||
| "integrity": "sha1-n5VxD1CiZ5R7LMwSR0HBAoQn5xM=" | ||
| }, | ||
| "uuid": { | ||
| "version": "3.3.2", | ||
| "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.3.2.tgz", | ||
| "integrity": "sha512-yXJmeNaw3DnnKAOKJE51sL/ZaYfWJRl1pK9dr19YFCu0ObS231AB1/LbqTKRAQ5kw8A90rA6fr4riOUpTZvQZA==" | ||
| }, | ||
| "vary": { | ||
| "version": "1.1.2", | ||
| "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz", | ||
| "integrity": "sha1-IpnwLG3tMNSllhsLn3RSShj2NPw=" | ||
| }, | ||
| "wrappy": { | ||
| "version": "1.0.2", | ||
| "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", | ||
| "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=" | ||
| }, | ||
| "yn": { | ||
| "version": "2.0.0", | ||
| "resolved": "https://registry.npmjs.org/yn/-/yn-2.0.0.tgz", | ||
| "integrity": "sha1-5a2ryKz0CPY4X8dklWhMiOavaJo=", | ||
| "dev": true | ||
| } | ||
| } | ||
| } |
| { | ||
| "name": "ts-api-examples", | ||
| "version": "1.0.0", | ||
| "description": "Example TS-API Service", | ||
| "scripts": { | ||
| "start": "npm run serve", | ||
| "build": "npm run tslint && npm run build-ts", | ||
| "serve": "node dist/server.js", | ||
| "build-ts": "tsc && cg", | ||
| "tslint": "tslint -c tslint.json -p tsconfig.json" | ||
| }, | ||
| "dependencies": { | ||
| "debug": "4.0.1", | ||
| "express": "^4.16.2", | ||
| "ts-api": "x" | ||
| }, | ||
| "devDependencies": { | ||
| "@types/express": "^4.11.1", | ||
| "@types/node": "^9.4.6", | ||
| "ts-node": "^5.0.0", | ||
| "tslint": "^5.9.1", | ||
| "typescript": "^3.1.6" | ||
| } | ||
| } |
| # Example project using TS-API | ||
| This service is intended to be run-able but is not intended to be boilerplate or a generator for a new project. | ||
| * Interesting code is in `src/controllers` as a starting place | ||
| * Operate with npm commands (test, build, run) | ||
| import express from 'express'; | ||
| import * as bodyParser from 'body-parser'; | ||
| import Router from './Router'; | ||
| // Create Express server | ||
| const app = express(); | ||
| const router = new Router(app); | ||
| app.use(bodyParser.urlencoded({ extended: false })); | ||
| app.use(bodyParser.json()); | ||
| app.use(router.getExpressRouter()); | ||
| export default app; | ||
| import { ControllerBase, controller, get, post } from 'ts-api'; | ||
| import { IUser, IListQuery } from 'user.d.ts'; | ||
| @controller('/user') | ||
| export class AccountFoo extends ControllerBase { | ||
| @get('/') | ||
| async listUsers(userId: string, query: IListQuery): Promise<IUser[]> { | ||
| return [{ id: userId, name: 'foo' }]; | ||
| } | ||
| @get('/:userId') | ||
| async getUser(userId: string): Promise<IUser> { | ||
| return { id: userId, name: 'foo' }; | ||
| } | ||
| @post('/') | ||
| async createUser(newAccountBody: IUser): Promise<IUser> { | ||
| return newAccountBody; | ||
| } | ||
| } |
| import { RouterBase, router } from 'ts-api'; | ||
| /** | ||
| * Example TS-API Service | ||
| */ | ||
| @router('/api') | ||
| export default class Router extends RouterBase { | ||
| constructor(app: any) { | ||
| super(app); | ||
| require('./__routes')(this); | ||
| } | ||
| } | ||
| import app from './app'; | ||
| const PORT = process.env.PORT || '3001'; | ||
| /** | ||
| * Start Express server. | ||
| */ | ||
| function initServer() { | ||
| const server = app.listen(PORT, () => { | ||
| console.log(`App is running at http://localhost:${PORT} in ${app.get('env')} mode`); | ||
| console.log(' Press CTRL-C to stop\n'); | ||
| }); | ||
| return server; | ||
| } | ||
| const server = initServer(); | ||
| export default server; |
| export interface IUser { | ||
| /** @format {uuid} */ | ||
| id: string; | ||
| name: string; | ||
| isActive?: boolean; | ||
| } | ||
| export interface IListQuery { | ||
| sort?: string; | ||
| /** @type {integer} */ | ||
| limit?: number; | ||
| } |
| { | ||
| "compilerOptions": { | ||
| "module": "commonjs", | ||
| "esModuleInterop": true, | ||
| "target": "es5", | ||
| "noImplicitAny": true, | ||
| "moduleResolution": "node", | ||
| "sourceMap": true, | ||
| "outDir": "dist", | ||
| "baseUrl": ".", | ||
| "experimentalDecorators": true, | ||
| "rootDir": "./src", | ||
| "emitDecoratorMetadata": true, | ||
| "lib": [ | ||
| "es6", | ||
| "dom" | ||
| ], | ||
| "paths": { | ||
| "*": [ | ||
| "node_modules/*", | ||
| "src/types/*" | ||
| ] | ||
| } | ||
| }, | ||
| "include": [ | ||
| "src/**/*" | ||
| ] | ||
| } |
| { | ||
| "rules": { | ||
| "class-name": true, | ||
| "comment-format": [ | ||
| true, | ||
| "check-space" | ||
| ], | ||
| "indent": [ | ||
| true, | ||
| "spaces" | ||
| ], | ||
| "one-line": [ | ||
| true, | ||
| "check-open-brace", | ||
| "check-whitespace" | ||
| ], | ||
| "no-var-keyword": true, | ||
| "quotemark": [ | ||
| true, | ||
| "single", | ||
| "avoid-escape" | ||
| ], | ||
| "semicolon": [ | ||
| true, | ||
| "always", | ||
| "ignore-bound-class-methods" | ||
| ], | ||
| "whitespace": [ | ||
| true, | ||
| "check-branch", | ||
| "check-decl", | ||
| "check-operator", | ||
| "check-module", | ||
| "check-separator", | ||
| "check-type" | ||
| ], | ||
| "typedef-whitespace": [ | ||
| true, | ||
| { | ||
| "call-signature": "nospace", | ||
| "index-signature": "nospace", | ||
| "parameter": "nospace", | ||
| "property-declaration": "nospace", | ||
| "variable-declaration": "nospace" | ||
| }, | ||
| { | ||
| "call-signature": "onespace", | ||
| "index-signature": "onespace", | ||
| "parameter": "onespace", | ||
| "property-declaration": "onespace", | ||
| "variable-declaration": "onespace" | ||
| } | ||
| ], | ||
| "no-internal-module": true, | ||
| "no-trailing-whitespace": true, | ||
| "no-null-keyword": true, | ||
| "prefer-const": true, | ||
| "jsdoc-format": true | ||
| } | ||
| } |
+201
| Apache License | ||
| Version 2.0, January 2004 | ||
| http://www.apache.org/licenses/ | ||
| TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION | ||
| 1. Definitions. | ||
| "License" shall mean the terms and conditions for use, reproduction, | ||
| and distribution as defined by Sections 1 through 9 of this document. | ||
| "Licensor" shall mean the copyright owner or entity authorized by | ||
| the copyright owner that is granting the License. | ||
| "Legal Entity" shall mean the union of the acting entity and all | ||
| other entities that control, are controlled by, or are under common | ||
| control with that entity. For the purposes of this definition, | ||
| "control" means (i) the power, direct or indirect, to cause the | ||
| direction or management of such entity, whether by contract or | ||
| otherwise, or (ii) ownership of fifty percent (50%) or more of the | ||
| outstanding shares, or (iii) beneficial ownership of such entity. | ||
| "You" (or "Your") shall mean an individual or Legal Entity | ||
| exercising permissions granted by this License. | ||
| "Source" form shall mean the preferred form for making modifications, | ||
| including but not limited to software source code, documentation | ||
| source, and configuration files. | ||
| "Object" form shall mean any form resulting from mechanical | ||
| transformation or translation of a Source form, including but | ||
| not limited to compiled object code, generated documentation, | ||
| and conversions to other media types. | ||
| "Work" shall mean the work of authorship, whether in Source or | ||
| Object form, made available under the License, as indicated by a | ||
| copyright notice that is included in or attached to the work | ||
| (an example is provided in the Appendix below). | ||
| "Derivative Works" shall mean any work, whether in Source or Object | ||
| form, that is based on (or derived from) the Work and for which the | ||
| editorial revisions, annotations, elaborations, or other modifications | ||
| represent, as a whole, an original work of authorship. For the purposes | ||
| of this License, Derivative Works shall not include works that remain | ||
| separable from, or merely link (or bind by name) to the interfaces of, | ||
| the Work and Derivative Works thereof. | ||
| "Contribution" shall mean any work of authorship, including | ||
| the original version of the Work and any modifications or additions | ||
| to that Work or Derivative Works thereof, that is intentionally | ||
| submitted to Licensor for inclusion in the Work by the copyright owner | ||
| or by an individual or Legal Entity authorized to submit on behalf of | ||
| the copyright owner. For the purposes of this definition, "submitted" | ||
| means any form of electronic, verbal, or written communication sent | ||
| to the Licensor or its representatives, including but not limited to | ||
| communication on electronic mailing lists, source code control systems, | ||
| and issue tracking systems that are managed by, or on behalf of, the | ||
| Licensor for the purpose of discussing and improving the Work, but | ||
| excluding communication that is conspicuously marked or otherwise | ||
| designated in writing by the copyright owner as "Not a Contribution." | ||
| "Contributor" shall mean Licensor and any individual or Legal Entity | ||
| on behalf of whom a Contribution has been received by Licensor and | ||
| subsequently incorporated within the Work. | ||
| 2. Grant of Copyright License. Subject to the terms and conditions of | ||
| this License, each Contributor hereby grants to You a perpetual, | ||
| worldwide, non-exclusive, no-charge, royalty-free, irrevocable | ||
| copyright license to reproduce, prepare Derivative Works of, | ||
| publicly display, publicly perform, sublicense, and distribute the | ||
| Work and such Derivative Works in Source or Object form. | ||
| 3. Grant of Patent License. Subject to the terms and conditions of | ||
| this License, each Contributor hereby grants to You a perpetual, | ||
| worldwide, non-exclusive, no-charge, royalty-free, irrevocable | ||
| (except as stated in this section) patent license to make, have made, | ||
| use, offer to sell, sell, import, and otherwise transfer the Work, | ||
| where such license applies only to those patent claims licensable | ||
| by such Contributor that are necessarily infringed by their | ||
| Contribution(s) alone or by combination of their Contribution(s) | ||
| with the Work to which such Contribution(s) was submitted. If You | ||
| institute patent litigation against any entity (including a | ||
| cross-claim or counterclaim in a lawsuit) alleging that the Work | ||
| or a Contribution incorporated within the Work constitutes direct | ||
| or contributory patent infringement, then any patent licenses | ||
| granted to You under this License for that Work shall terminate | ||
| as of the date such litigation is filed. | ||
| 4. Redistribution. You may reproduce and distribute copies of the | ||
| Work or Derivative Works thereof in any medium, with or without | ||
| modifications, and in Source or Object form, provided that You | ||
| meet the following conditions: | ||
| (a) You must give any other recipients of the Work or | ||
| Derivative Works a copy of this License; and | ||
| (b) You must cause any modified files to carry prominent notices | ||
| stating that You changed the files; and | ||
| (c) You must retain, in the Source form of any Derivative Works | ||
| that You distribute, all copyright, patent, trademark, and | ||
| attribution notices from the Source form of the Work, | ||
| excluding those notices that do not pertain to any part of | ||
| the Derivative Works; and | ||
| (d) If the Work includes a "NOTICE" text file as part of its | ||
| distribution, then any Derivative Works that You distribute must | ||
| include a readable copy of the attribution notices contained | ||
| within such NOTICE file, excluding those notices that do not | ||
| pertain to any part of the Derivative Works, in at least one | ||
| of the following places: within a NOTICE text file distributed | ||
| as part of the Derivative Works; within the Source form or | ||
| documentation, if provided along with the Derivative Works; or, | ||
| within a display generated by the Derivative Works, if and | ||
| wherever such third-party notices normally appear. The contents | ||
| of the NOTICE file are for informational purposes only and | ||
| do not modify the License. You may add Your own attribution | ||
| notices within Derivative Works that You distribute, alongside | ||
| or as an addendum to the NOTICE text from the Work, provided | ||
| that such additional attribution notices cannot be construed | ||
| as modifying the License. | ||
| You may add Your own copyright statement to Your modifications and | ||
| may provide additional or different license terms and conditions | ||
| for use, reproduction, or distribution of Your modifications, or | ||
| for any such Derivative Works as a whole, provided Your use, | ||
| reproduction, and distribution of the Work otherwise complies with | ||
| the conditions stated in this License. | ||
| 5. Submission of Contributions. Unless You explicitly state otherwise, | ||
| any Contribution intentionally submitted for inclusion in the Work | ||
| by You to the Licensor shall be under the terms and conditions of | ||
| this License, without any additional terms or conditions. | ||
| Notwithstanding the above, nothing herein shall supersede or modify | ||
| the terms of any separate license agreement you may have executed | ||
| with Licensor regarding such Contributions. | ||
| 6. Trademarks. This License does not grant permission to use the trade | ||
| names, trademarks, service marks, or product names of the Licensor, | ||
| except as required for reasonable and customary use in describing the | ||
| origin of the Work and reproducing the content of the NOTICE file. | ||
| 7. Disclaimer of Warranty. Unless required by applicable law or | ||
| agreed to in writing, Licensor provides the Work (and each | ||
| Contributor provides its Contributions) on an "AS IS" BASIS, | ||
| WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or | ||
| implied, including, without limitation, any warranties or conditions | ||
| of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A | ||
| PARTICULAR PURPOSE. You are solely responsible for determining the | ||
| appropriateness of using or redistributing the Work and assume any | ||
| risks associated with Your exercise of permissions under this License. | ||
| 8. Limitation of Liability. In no event and under no legal theory, | ||
| whether in tort (including negligence), contract, or otherwise, | ||
| unless required by applicable law (such as deliberate and grossly | ||
| negligent acts) or agreed to in writing, shall any Contributor be | ||
| liable to You for damages, including any direct, indirect, special, | ||
| incidental, or consequential damages of any character arising as a | ||
| result of this License or out of the use or inability to use the | ||
| Work (including but not limited to damages for loss of goodwill, | ||
| work stoppage, computer failure or malfunction, or any and all | ||
| other commercial damages or losses), even if such Contributor | ||
| has been advised of the possibility of such damages. | ||
| 9. Accepting Warranty or Additional Liability. While redistributing | ||
| the Work or Derivative Works thereof, You may choose to offer, | ||
| and charge a fee for, acceptance of support, warranty, indemnity, | ||
| or other liability obligations and/or rights consistent with this | ||
| License. However, in accepting such obligations, You may act only | ||
| on Your own behalf and on Your sole responsibility, not on behalf | ||
| of any other Contributor, and only if You agree to indemnify, | ||
| defend, and hold each Contributor harmless for any liability | ||
| incurred by, or claims asserted against, such Contributor by reason | ||
| of your accepting any such warranty or additional liability. | ||
| END OF TERMS AND CONDITIONS | ||
| APPENDIX: How to apply the Apache License to your work. | ||
| To apply the Apache License to your work, attach the following | ||
| boilerplate notice, with the fields enclosed by brackets "[]" | ||
| replaced with your own identifying information. (Don't include | ||
| the brackets!) The text should be enclosed in the appropriate | ||
| comment syntax for the file format. We also recommend that a | ||
| file or class name and description of purpose be included on the | ||
| same "printed page" as the copyright notice for easier | ||
| identification within third-party archives. | ||
| Copyright 2016-2017 The New York Times Company | ||
| Licensed under the Apache License, Version 2.0 (the "License"); | ||
| you may not use this file except in compliance with the License. | ||
| You may obtain a copy of the License at | ||
| http://www.apache.org/licenses/LICENSE-2.0 | ||
| Unless required by applicable law or agreed to in writing, software | ||
| distributed under the License is distributed on an "AS IS" BASIS, | ||
| WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
| See the License for the specific language governing permissions and | ||
| limitations under the License. |
+128
| # TS-API | ||
| APIs in NodeJS should have a single source of truth for api specs between code and docs, as well as compile time type safety. | ||
| Schemas are often duplicated between json schemas for input validation, typescript types, jsdoc comment annotations or swagger-specific wrappers in your app. Routes and response status codes also suffer from similar issues where code can get out of sync with documentation. | ||
| TS-API solves this by leveraging the typescript parser to generate: | ||
| * OpenAPI (Swagger) docs | ||
| * Runtime type checks with Json schemas | ||
| * ExpressJS routes to be mounted | ||
| * Optional correctness verification of status code <-> result type mapping | ||
| ## Concepts | ||
| ### Type conversion | ||
| TypeScript types are extracted from the source code, such as this example: | ||
| ```javascript | ||
| export interface User { | ||
| name: string; | ||
| isActive?: boolean; | ||
| } | ||
| ``` | ||
| is converted to a json schema: | ||
| ```json | ||
| "User": { | ||
| "type": "object", | ||
| "properties": { | ||
| "name": { | ||
| "type": "string" | ||
| }, | ||
| "isActive": { | ||
| "type": "boolean" | ||
| } | ||
| }, | ||
| "required": [ | ||
| "name" | ||
| ] | ||
| } | ||
| ``` | ||
| ### Route Generation | ||
| ```javascript | ||
| @controller('/user') | ||
| export class User extends ControllerBase { | ||
| @get('/') | ||
| async listUsers(): Promise<User[]> { | ||
| ... | ||
| return [{ ...account1 }, ...] | ||
| } | ||
| ``` | ||
| The controller and Rest verbs (get, post, put, etc.) optionally take a route override, otherwise it uses the class or method name by default. | ||
| A router tree is build by TS-API from all controllers in the typescript path: | ||
| ```javascript | ||
| AccountRouter.get('/', async(req,res,next) => { ... } | ||
| ``` | ||
| You can mount this anywhere in your app, use middleware, and treat it like any other ExpressJS router. The controller gives full access to req/res/next in the constructor. There's further customizations support, such as hooks to customize input validation, but by default it returns a `400` status. | ||
| ### OpenAPI (Swagger) docs | ||
| OpenAPI 3 output for a sample controller: | ||
|  | ||
| [ReDoc](https://github.com/Rebilly/ReDoc) is also supported as viewer. | ||
| ## Usage | ||
| ### Install | ||
| npm install --save-dev ts-api | ||
| First make this package a dependency. This will provide the necessary decorators *@controller*, | ||
| *@router* *@get* *@post*, etc. The analyzer will search for those names and generate code that | ||
| uses them, but these decorators also do things themselves like invoke the runtime type checker. | ||
| ### Create appropriately annotated classes and methods. | ||
| The key steps are: | ||
| 1. Create a class that extend the base controller | ||
| 2. Add a controller decorator to the class | ||
| 3. Decorate methods that represend API endpoints | ||
| 4. Use typescript interfaces for type declarations in the method arguments/response | ||
| See an [example controller](examples/src/controllers/user.ts) for a working reference. | ||
| ### Import the router and use in your app | ||
| ```javascript | ||
| @router('/api') | ||
| export default class Router extends RouterBase { | ||
| constructor(app: any) { | ||
| super(app); | ||
| require('./__routes')(this); | ||
| } | ||
| } | ||
| ``` | ||
| ### Run cg after typescript compiling your code | ||
| The easiest way to do this is an npm script (or npm install -g): | ||
| tsc && cg | ||
| The `cg` CLI tool can take options and specific files: | ||
| cg <options> <list of files> | ||
| ### Run your app | ||
| You can verify output by using the hosted docs. The route will depend on where you mount the app, such as: | ||
| http://localhost:3002/api/docs | ||
| ## License | ||
| [Apache 2.0](LICENSE) |
| import * as ts from "typescript"; | ||
| import * as path from "path"; | ||
| const tsany = ts as any; | ||
| import { TypedId, PathDecomposition, DecoratedFunction, Controller, Router } from "./types"; | ||
| import { typeToJSON } from "./symtab"; | ||
| import { synthesizeParameterJSDoc, decomposePath, decompositionToPath, isURLParam } from "./traverse"; | ||
| function genAssignment1(id:string,dataSource:string,kind:string,typeSpec:any,content:string) { | ||
| let output = ""; | ||
| let type = typeSpec.type; | ||
| if(content != "flat" && (type == "object" || type == null || type == "array")) { | ||
| if(type == "array") { | ||
| if(typeSpec.items.type == "object" || typeSpec.items['$ref'] != null) { | ||
| output = ` let ${id};\n`; | ||
| } | ||
| else { | ||
| if(kind == "urlParam") | ||
| output = ` let ${id} = req.params.${id};\n`; | ||
| else | ||
| output = ` let ${id} = req.${dataSource}.${id};\n`; | ||
| } | ||
| } | ||
| else { | ||
| output = ` let ${id};\n`; | ||
| } | ||
| } | ||
| else { | ||
| if(kind == "urlParam") | ||
| output = ` let ${id} = req.params.${id};\n`; | ||
| else | ||
| output = ` let ${id} = req.${dataSource}.${id};\n`; | ||
| } | ||
| return output; | ||
| } | ||
| function genAssignment2(id:string,dataSource:string,kind:string,typeSpec:any,content:string) { | ||
| let output = ""; | ||
| let type = typeSpec.type; | ||
| if(content != "flat" && (type == "object" || type == null || type == "array")) { | ||
| if(type == "array") { | ||
| if(typeSpec.items.type == "object" || typeSpec.items['$ref'] != null) { | ||
| if(kind == "urlParam") | ||
| output = ` try { ${id} = (typeof req.params.${id} == "string")?JSON.parse(req.params.${id}):req.params.${id}; } catch(e) {};\n`; | ||
| else | ||
| output = ` try { ${id} = (typeof req.${dataSource}.${id} == "string")?JSON.parse(req.${dataSource}.${id}):req.${dataSource}.${id}; } catch(e) {};\n`; | ||
| } | ||
| } | ||
| else { | ||
| if(kind == "urlParam") | ||
| output = ` try { ${id} = (typeof req.params.${id} == "string")?JSON.parse(req.params.${id}):req.params.${id}; } catch(e) {};\n`; | ||
| else | ||
| output = ` try { ${id} = (typeof req.${dataSource}.${id} == "string")?JSON.parse(req.${dataSource}.${id}):req.${dataSource}.${id}; } catch(e) {};\n`; | ||
| } | ||
| } | ||
| return output; | ||
| } | ||
| function genAssignment3(id:string,dataSource:string,kind:string,typeSpec:any,content:string) { | ||
| let output = ""; | ||
| let type = typeSpec.type; | ||
| if(type == "array") { | ||
| output += ` if(${id} != null) {\n`; | ||
| output += ` if(!Array.isArray(${id})) ${id} = [${id}];\n`; | ||
| output += ` }\n`; | ||
| } | ||
| return output; | ||
| } | ||
| function genControllerArgAssignmentsA(dataSource:string,params:any[],endpointName:string,genFunc:Function): string { | ||
| let output = ""; | ||
| for(let i = 0;i < params.length;i++) | ||
| output += genFunc(params[i].id,dataSource,params[i].kind,params[i].type,params[i].type.content); | ||
| return output; | ||
| } | ||
| function genControllerArgAssignmentsB(dataSource:string,params:any[],endpointName:string,genFunc:Function,argListFormal:Array<any>): string { | ||
| let output = ""; | ||
| for(let i = 0;i < params.length;i++) { | ||
| if(params[i].kind == "urlParam") { | ||
| output += genFunc(params[i].id,dataSource,params[i].kind,params[i].type,params[i].type.content); | ||
| if(argListFormal != null) argListFormal.push(params[i].id); | ||
| } | ||
| else { | ||
| if(params[i].type.type == "object") { | ||
| let properties = params[i].type.properties; | ||
| let objArgs = []; | ||
| for(let propertyName in properties) { | ||
| output += genFunc(propertyName,dataSource,"regular",properties[propertyName],properties[propertyName].content); | ||
| objArgs.push(propertyName); | ||
| } | ||
| if(argListFormal != null) argListFormal.push(objArgs); | ||
| } | ||
| else { | ||
| output += genFunc(params[i].id,dataSource,params[i].kind,params[i].type,params[i].type.content); | ||
| if(argListFormal != null) argListFormal.push(params[i].id); | ||
| } | ||
| } | ||
| } | ||
| return output; | ||
| } | ||
| function genControllerArgListA(dataSource:string,params:any[],endpointName:string): string { | ||
| let output = ""; | ||
| let assignments1 = genControllerArgAssignmentsA(dataSource,params,endpointName,genAssignment1); | ||
| let assignments2 = genControllerArgAssignmentsA(dataSource,params,endpointName,genAssignment2); | ||
| let assignments3 = genControllerArgAssignmentsA(dataSource,params,endpointName,genAssignment3); | ||
| if(assignments1 != "") output += `${assignments1}`; | ||
| if(assignments2 != "") output += `\n${assignments2}\n`; | ||
| if(assignments3 != "") output += `\n${assignments3}\n`; | ||
| output += ` const __res = await controller.${endpointName}(`; | ||
| for(let i = 0;i < params.length;i++) { | ||
| if(i != 0) output += ','; | ||
| output += `${params[i].id}`; | ||
| } | ||
| output += `);\n\n`; | ||
| return output; | ||
| } | ||
| function genControllerArgListB(dataSource:string,params:any[],endpointName:string): string { | ||
| let output = ""; | ||
| let argListFormal = []; | ||
| let assignments1 = genControllerArgAssignmentsB(dataSource,params,endpointName,genAssignment1,argListFormal); | ||
| let assignments2 = genControllerArgAssignmentsB(dataSource,params,endpointName,genAssignment2,null); | ||
| let assignments3 = genControllerArgAssignmentsB(dataSource,params,endpointName,genAssignment3,null); | ||
| let anum; | ||
| if(assignments1 != "") output += `${assignments1}`; | ||
| if(assignments2 != "") output += `\n${assignments2}\n`; | ||
| if(assignments3 != "") output += `\n${assignments3}\n`; | ||
| for(let i = 0;i < argListFormal.length;i++) { | ||
| if(typeof argListFormal[i] != "string") { | ||
| if(anum == null) anum = 0; | ||
| output += ` let __arg${anum++} = {};\n`; | ||
| } | ||
| } | ||
| if(anum != null) { | ||
| anum = 0; | ||
| for(let i = 0;i < argListFormal.length;i++) { | ||
| if(typeof argListFormal[i] != "string") { | ||
| for(let j = 0;j < argListFormal[i].length;j++) { | ||
| output += ` if(${argListFormal[i][j]} != null) __arg${anum}.${argListFormal[i][j]} = ${argListFormal[i][j]};\n`; | ||
| } | ||
| anum++; | ||
| } | ||
| } | ||
| } | ||
| if(anum != null) anum = 0; | ||
| output += ` const __res = await controller.${endpointName}(`; | ||
| for(let i = 0;i < argListFormal.length;i++) { | ||
| if(i != 0) output += ','; | ||
| if(typeof argListFormal[i] == "string") output += `${argListFormal[i]}`; | ||
| else output += `__arg${anum++}`; | ||
| } | ||
| output += `);\n\n`; | ||
| return output; | ||
| } | ||
| /** | ||
| * Generate the express routes fron the router, controller, and method declarations. Make | ||
| * use of the fact that the generated file '__check.js' will always be located in the same | ||
| * directory as the routes file '__routes.js'. Make use of supporting files from this package | ||
| * to create instances of the controller classes. The form of this file when used as a target | ||
| * to require is to export a single function that takes a single argument of type RouterBase | ||
| * (which the class annotated with @router should derive from), and when invoked will create | ||
| * all of the controllers, and add them to the the router, and then connect the controllers | ||
| * to express app; it is assumed that the router class will have a reference to app at the time, | ||
| * but it should since this is a required parameter to RouterBase constructor. Generate | ||
| * a app.{get,post,put,...} for each method of a controller an analogous annotation. | ||
| * | ||
| * @param {DecoratedFunction[]} endpoints A array of all of the methods decorated with REST verbs. | ||
| * @param {Router} top level router class. | ||
| * @param {Controller[]} controllers array of method controllers | ||
| * @param {NodeJS.ReadWriteStream} routesFile reference to the routes output file. | ||
| */ | ||
| export function genExpressRoutes(endpoints:DecoratedFunction[],router:Router,controllers:Controller[],srcRoot: string,routesFile: NodeJS.ReadWriteStream):string { | ||
| let output = `"use strict";\n\n`; | ||
| let resolvedRoot; | ||
| let controllerIndex = {}; | ||
| if(srcRoot != null) resolvedRoot = path.resolve(srcRoot).replace(/\\/g, '/'); | ||
| output += `const express = require('express');\n`; | ||
| output += `const api = require('ts-api');\n`; | ||
| output += `const EndpointCheckBinding = api.EndpointCheckBinding;\n`; | ||
| output += `const ControllerProperties = api.ControllerProperties;\n`; | ||
| output += `const error_response = api.response.error;\n`; | ||
| output += `const success_response = api.response.success;\n`; | ||
| // Generate requires for controller classes. Use parser support for | ||
| // the file they are defined in to provide the parameter for require. | ||
| for(let i = 0;i < controllers.length;i++) { | ||
| let fileName = path.resolve(controllers[i].fileName).replace(/\\/g, '/'); | ||
| if(srcRoot != null) { | ||
| fileName = fileName.replace(resolvedRoot + '/',''); | ||
| fileName = fileName.replace(path.extname(fileName),""); | ||
| output += `const ${controllers[i].classRef}Module = require('./${fileName}');\n`; | ||
| } | ||
| else output += `const ${controllers[i].classRef}Module = require('./${path.basename(fileName)}');\n`; | ||
| controllerIndex[controllers[i].classRef] = controllers[i]; | ||
| } | ||
| // include support for automatic swagger document display endpoint. Avoid | ||
| // requiring that package directory by proxying the require through ts-api. | ||
| // make use of the guaranteed location of the swagger doc that is generated | ||
| // relative to the routes file. | ||
| output += `const swaggerUi = api.swaggerUi;\n`; | ||
| output += `const swaggerDocument = require('./docs/swagger.json');\n`; | ||
| output += `\nlet binding = new EndpointCheckBinding(require('./__check'));\n`; | ||
| output += `\nmodule.exports = function(root) {\n`; | ||
| let routerPath = decompositionToPath(router.decomposition,"express"); | ||
| for(let i = 0;i < controllers.length;i++) { | ||
| let path = '/' + decompositionToPath(controllers[i].decomposition,"express"); | ||
| if(routerPath != "") path = `/${routerPath}${path}`; | ||
| output += ` root.addRouter('${path}','${controllers[i].classRef}',{ mergeParams:true });\n`; | ||
| } | ||
| for(let i = 0;i < endpoints.length;i++) { | ||
| let rfunc = endpoints[i].type; | ||
| let endpointName = endpoints[i].name; | ||
| let path = endpointName; | ||
| let dataSource = "query"; | ||
| if(endpoints[i].decoratorArgs.length != 0) path = endpoints[i].decoratorArgs[0]; | ||
| let endpointPathDecomposition = decomposePath(path); | ||
| let endpointPath = decompositionToPath(endpointPathDecomposition,"express"); | ||
| // For each method, tie everything together by creating the right controller instance, | ||
| // collecting the express REST parameters, converting it to the method parameters, and then | ||
| // invoking the method with those parameters. Assume coordiation with the | ||
| // express verb decorator defined in this package. | ||
| output += `\n`; | ||
| output += ` root.getExpressRouter('${endpoints[i].classRef}').${rfunc}('/${endpointPath}', async(req,res,next) => {\n`; | ||
| output += ` try {\n`; | ||
| if(rfunc != 'get') { | ||
| output += ` if(req.body == null) throw("body is null (possible missing body parser)")\n`; | ||
| dataSource = "body"; | ||
| } | ||
| output += ` const properties = new ControllerProperties(binding,root.context,req,res,next);\n` | ||
| output += ` const controller = new ${endpoints[i].classRef}Module.default(properties);\n` | ||
| let params = []; | ||
| let numURLParam = 0; | ||
| // Gather parameter metadata prior to output | ||
| for(let j = 0;j < endpoints[i].methodParameters.length;j++) { | ||
| let parm = endpoints[i].methodParameters[j]; | ||
| let jsDoc = synthesizeParameterJSDoc(endpoints[i].methodParameters[j]); | ||
| let parmType = typeToJSON(parm.type,jsDoc,{ expandRefs:true, firstclassIntermediates:true, schemaNamespace:"swagger", docRoot:"#/definitions" }) | ||
| if(parm.decorators != null) { | ||
| let isURLDecorated = false; | ||
| for(let decoratorName in parm.decorators) { | ||
| if(decoratorName == 'urlParam') { | ||
| let decoratorArgs = parm.decorators[decoratorName]; | ||
| if(decoratorArgs.length) params.push({ id:decoratorArgs[0], kind:"urlParam" }); | ||
| else params.push({ id:parm.id, kind: "urlParam", type:parmType }); | ||
| numURLParam += 1; | ||
| } | ||
| } | ||
| if(!isURLDecorated) { | ||
| if(isURLParam(parm.id,router,controllerIndex[endpoints[i].classRef],endpointPathDecomposition)) { | ||
| params.push({ id:parm.id, kind: "urlParam", type:parmType }); | ||
| numURLParam += 1; | ||
| } | ||
| else params.push({ id:parm.id, kind: "regular", type:parmType }); | ||
| } | ||
| } | ||
| else if(isURLParam(parm.id,router,controllerIndex[endpoints[i].classRef],endpointPathDecomposition)) { | ||
| params.push({ id:parm.id, kind: "urlParam", type:parmType }); | ||
| numURLParam += 1; | ||
| } | ||
| else | ||
| params.push({ id:parm.id, kind: "regular", type:parmType }); | ||
| } | ||
| if(params.length - numURLParam > 1) output += genControllerArgListA(dataSource,params,endpointName); | ||
| else output += genControllerArgListB(dataSource,params,endpointName); | ||
| output += ` success_response(__res,req,res,next);\n`; | ||
| output += ` }\n`; | ||
| output += ` catch(e) { error_response(e,req,res,next); }\n`; | ||
| output += ` });\n`; | ||
| } | ||
| let docPath = '/docs'; | ||
| let redocPath = '/redoc'; | ||
| let staticPath = '/doc-static'; | ||
| let swaggerPath = '/doc-static/swagger.json'; | ||
| if(routerPath != "") { | ||
| docPath = `/${routerPath}${docPath}`; | ||
| redocPath = `/${routerPath}${redocPath}`; | ||
| staticPath = `/${routerPath}${staticPath}`; | ||
| swaggerPath = `/${routerPath}${swaggerPath}`; | ||
| } | ||
| output += ` root.getExpressRouter().use('${docPath}',swaggerUi.serve,swaggerUi.setup(swaggerDocument));\n`; | ||
| output += ` root.getExpressRouter().get('${redocPath}',function(req,res,next) {\n `; | ||
| output += ` res.sendFile(__dirname + '/docs/redoc.html');\n`; | ||
| output += ` });\n`; | ||
| output += ` root.getExpressRouter().use('${staticPath}',express.static(__dirname + '/docs'));\n`; | ||
| output += ` return root.getExpressRouter();\n`; | ||
| output += `}\n`; | ||
| routesFile.write(output); | ||
| return swaggerPath; | ||
| } |
| import * as ts from "typescript"; | ||
| import { generate } from "./main"; | ||
| module.exports = { | ||
| generate:function(env,checkFile,swaggerFile,redocFile,routesFile) { | ||
| let src = env.programArgs.slice(2); | ||
| if(src.length == 0) src = env.tsInclude; | ||
| generate( | ||
| src, | ||
| { target:ts.ScriptTarget.ES5, module: ts.ModuleKind.CommonJS, experimentalDecorators:true }, | ||
| env.packageName, | ||
| env.srcRoot, | ||
| checkFile, | ||
| swaggerFile, | ||
| redocFile, | ||
| routesFile, | ||
| env.debug | ||
| ); | ||
| } | ||
| } |
| import * as ts from "typescript"; | ||
| import * as glob from "glob"; | ||
| import * as doctrine from "doctrine"; | ||
| const tsany = ts as any; | ||
| import { TypedId, PathDecomposition, DecoratedFunction, Controller, Router } from "./types"; | ||
| import { checker, getIndex, setChecker, symtab, symtabGet, symtabPut, typeToJSON } from "./symtab"; | ||
| import { | ||
| addController, | ||
| addRouter, | ||
| connectMethods, | ||
| findRelevant, | ||
| genMethodEntry, | ||
| parameterListToJSON, | ||
| symtabToSchemaDefinitions, | ||
| symtabToControllerDefinitions, | ||
| symtabToRouterDefinitions, | ||
| traverseParameterList | ||
| } from "./traverse"; | ||
| import { genSwaggerPreamble, genSwaggerRootTags, genSwaggerRoutes } from "./swagger"; | ||
| import { genExpressRoutes } from "./express_routes"; | ||
| import { genRedoc } from "./redoc"; | ||
| /** | ||
| * Generate source given the definitions inicated by annotations in the source code. These | ||
| * sources include __router.js __check.js and docs/swagger.json. By default these files will | ||
| * be created in the destination directory as defined by the tsconfig file. | ||
| * | ||
| * @param {DecoratedFunction[]} items array of endpoint methods that correspond to express routes | ||
| * and swagger paths. | ||
| * @param {string} packageName name of the package (from package.json). This will be converted to | ||
| * the swagger title. | ||
| * @param {string} srcRoot location of the source code (from tsconfig.json). | ||
| * @param {NodeJS.ReadWriteStream} checkFile reference to the file __check.js | ||
| * @param {NodeJS.ReadWriteStream} swaggerFile reference to the file docs/swagger.json | ||
| * @param {NodeJS.ReadWriteStream} routesFiles reference to the file __routes.js | ||
| */ | ||
| function genSources( | ||
| items:DecoratedFunction[], | ||
| packageName: string, | ||
| srcRoot: string, | ||
| checkFile: NodeJS.ReadWriteStream, | ||
| swaggerFile: NodeJS.ReadWriteStream, | ||
| redocFile: NodeJS.ReadWriteStream, | ||
| routesFile: NodeJS.ReadWriteStream | ||
| ) { | ||
| let controllers:Controller[] = symtabToControllerDefinitions(); | ||
| let routers:Router[] = symtabToRouterDefinitions(); | ||
| let swaggerDefinitions:any = {}; | ||
| let contents_part1 = ''; | ||
| let contents_part2 = ''; | ||
| let contents_part3 = ''; | ||
| if(routers.length == 0) throw("No Router Definitions Found"); | ||
| if(routers.length > 1) throw("Multiple Router Definitions Found"); | ||
| contents_part1 += `const Ajv = require('ajv');\n`; | ||
| contents_part1 += `\nlet ajv = new Ajv({ coerceTypes: true });\n\n`; | ||
| contents_part1 += `ajv.addKeyword('toDate', {\n`; | ||
| contents_part1 += ` modifying: true,\n`; | ||
| contents_part1 += ` schema: false, \n`; | ||
| contents_part1 += ` valid: true, \n`; | ||
| contents_part1 += ` validate: function(data,dataPath,parentData,parentDataProperty) {\n`; | ||
| contents_part1 += ` if(typeof data == "string" && parentData != null) parentData[parentDataProperty] = new Date(data);\n`; | ||
| contents_part1 += ` }\n`; | ||
| contents_part1 += `});\n\n`; | ||
| contents_part1 += `ajv.addKeyword('precision', {\n`; | ||
| contents_part1 += ` schema: true,\n`; | ||
| contents_part1 += ` validate: function(schema,data) {\n`; | ||
| contents_part1 += ` let x = data - Math.floor(data);\n`; | ||
| contents_part1 += ` let m = Math.pow(10,schema);\n`; | ||
| contents_part1 += ` let y = x*m;\n`; | ||
| contents_part1 += ` \n`; | ||
| contents_part1 += ` return y == Math.floor(y);\n`; | ||
| contents_part1 += ` }\n`; | ||
| contents_part1 += `});\n`; | ||
| contents_part3 += `\nfunction compositeWithDefinitions(schema) { schema.definitions = definitions; return schema; }\n`; | ||
| contents_part3 += `function validate(schema) { try { return ajv.compile(compositeWithDefinitions(schema)); } catch(e) { throw new Error(e); } }\n`; | ||
| for(let i = 0;i < items.length;i++) findRelevant(items[i]); | ||
| let definitions1 = symtabToSchemaDefinitions("check","#/definitions"); | ||
| let definitions2 = symtabToSchemaDefinitions("swagger","#/components/schemas",{ firstclassIntermediates:true }); | ||
| let synthesizedTypes = {}; | ||
| for(let i = 0;i < items.length;i++) { | ||
| let x = <any>parameterListToJSON(items[i]); | ||
| if(x.parameterNames) x.schema.required = x.required; | ||
| contents_part3 += genMethodEntry(x.classRef,x.method,x.parameterNames,x.schema,x.passthrough); | ||
| } | ||
| contents_part2 += `\n\nlet definitions = ${JSON.stringify(definitions1,null,2)}\n`; | ||
| checkFile.write(contents_part1); | ||
| checkFile.write(contents_part2); | ||
| checkFile.write(contents_part3); | ||
| genSwaggerPreamble(swaggerDefinitions,packageName,routers[0],controllers); | ||
| genSwaggerRootTags(swaggerDefinitions,routers[0],controllers); | ||
| genSwaggerRoutes(swaggerDefinitions,synthesizedTypes,routers[0],controllers); | ||
| for(let synthesizedTypename in synthesizedTypes) definitions2[synthesizedTypename] = synthesizedTypes[synthesizedTypename]; | ||
| swaggerDefinitions.components = { schemas:definitions2 }; | ||
| swaggerFile.write(`${JSON.stringify(swaggerDefinitions,null,2)}\n`); | ||
| let swaggerPath = genExpressRoutes(items,routers[0],controllers,srcRoot,routesFile); | ||
| genRedoc(swaggerPath,redocFile); | ||
| } | ||
| /** | ||
| * Use glob to contruct the list of input files to scan given a list of glob-type | ||
| * patterns. | ||
| * | ||
| * @param {string[]} patterns array of glob-patterns describing the list of files. | ||
| */ | ||
| function getFilenames(patterns: string[]) { | ||
| let fa = []; | ||
| for(let i = 0;i < patterns.length;i++) { | ||
| let filenames = glob.sync(patterns[i]); | ||
| for(let j = 0;j < filenames.length;j++) fa.push(filenames[j]); | ||
| } | ||
| return fa; | ||
| } | ||
| /** | ||
| * Extract arguments of relevant decorators for static analysis. Some arguments | ||
| * to decorators are needed at compile time for file generation (e.g. @controller | ||
| * path). This function finds these values for use later on in the 2nd pass. | ||
| * Literal values can be used, but arguements only usable at runtime are ignored. | ||
| * | ||
| * @param {ts.CallExpression} cexpr AST subtree rooted with decorator type node. | ||
| */ | ||
| function genArgumentList(cexpr: ts.CallExpression) { | ||
| let argList = []; | ||
| for(const arg of cexpr.arguments) { | ||
| switch(arg.kind) { | ||
| case ts.SyntaxKind.StringLiteral: | ||
| { | ||
| let text = tsany.getTextOfNode(arg); | ||
| let s = text.replace(/^["']|["']$/g,''); | ||
| argList.push(s); | ||
| } | ||
| break; | ||
| case ts.SyntaxKind.NumericLiteral: | ||
| { | ||
| argList.push(parseFloat(tsany.getTextOfNode(arg))); | ||
| } | ||
| break; | ||
| case ts.SyntaxKind.Identifier: | ||
| { | ||
| argList.push(tsany.getTextOfNode(arg)); | ||
| } | ||
| break; | ||
| case ts.SyntaxKind.FunctionExpression: console.log(" ignoring function in decorator argument list"); break; | ||
| default: throw("unknown type (" + arg.kind + ") in decorator argument list"); | ||
| } | ||
| } | ||
| return argList; | ||
| } | ||
| /** | ||
| * Main entry point for static analysis of a list of typescript files. Given the list | ||
| * of files, invokes the typescript parser and typechecker APIs, and then using the | ||
| * resulting AST from that pass, generate file appropriate for the following objectives | ||
| * | ||
| * 1. Creation of runtime checking routines. Construct a JSON schema for each appropriatedly | ||
| * annotated method and a function that will apply a schema check to that argument list. | ||
| * Place these functions in __check.js | ||
| * | ||
| * 2. Assembly of express type routes. Generate a file __routes that will create appropriate | ||
| * objects and connect them to express using one or more express Router classes. Apply | ||
| * runtime checking in 1. as part of that route. | ||
| * | ||
| * 3. Generate analogous Swagger doc. Create a swagger document that corresponds to the | ||
| * routes created by 2. | ||
| * | ||
| * @param {string[]} patterns list of source file patters to analyze. | ||
| * @param {ts.CompilerOptions} options options controlling behavior of the typescript parser | ||
| * and type checker | ||
| * @param {string} packageName derived from package.json of the input project. Use for top level naming. | ||
| * @param {string} srcRoot root of the source directory (derived form tsconfig.json by default). | ||
| * @param {NodeJS.ReadWriteStream} checkFile reference to the generated file __check.js | ||
| * @param {NodeJS.ReadWriteStream} swaggerFile reference to the generated file docs/swagger.json | ||
| * @param {NodeJS.ReadWriteStream} routesFile reference to the generated file __routes.js | ||
| */ | ||
| export function generate( | ||
| patterns: string[], | ||
| options: ts.CompilerOptions, | ||
| packageName: string, | ||
| srcRoot: string, | ||
| checkFile: NodeJS.ReadWriteStream, | ||
| swaggerFile: NodeJS.ReadWriteStream, | ||
| redocFile: NodeJS.ReadWriteStream, | ||
| routesFile: NodeJS.ReadWriteStream, | ||
| debugMode: boolean | ||
| ): void { | ||
| let fa = getFilenames(patterns); | ||
| let program = ts.createProgram(fa,options); | ||
| let endpoints:DecoratedFunction[] = []; | ||
| let x = {}; | ||
| let defComp = []; | ||
| setChecker(program); | ||
| function isNodeExported(node: ts.Node): boolean { | ||
| return (node.flags & ts.ModifierFlags.Export) !== 0 || (node.parent && node.parent.kind === ts.SyntaxKind.SourceFile); | ||
| } | ||
| // Recurse over all of the decorated functions, classes, etc and extract | ||
| // relevant information and place that in a symbol table for later processing. | ||
| function visitDecorator(node: ts.Node) { | ||
| if(ts.isDecorator(node)) { | ||
| const expr = (<ts.Decorator>node).expression; | ||
| let dsym = checker.getSymbolAtLocation(expr.getFirstToken()); | ||
| let dname = dsym.getName(); | ||
| let parentIndex = "unknown"; | ||
| let methodParameters:TypedId[] = []; | ||
| let doRuntimeCheck = false; | ||
| let doDecoratedClass = false; | ||
| let functionName; | ||
| let returnType; | ||
| let comment; | ||
| switch(node.parent.kind) { | ||
| case ts.SyntaxKind.FunctionDeclaration: | ||
| { | ||
| let parent:ts.FunctionDeclaration = <ts.FunctionDeclaration>node.parent; | ||
| if(parent.name != null) { | ||
| let symbol = checker.getSymbolAtLocation(parent.name); | ||
| comment = ts.displayPartsToString(symbol.getDocumentationComment(checker)); | ||
| } | ||
| returnType = parent.type; | ||
| functionName = (<any>parent.name).text; | ||
| doRuntimeCheck = true; | ||
| } | ||
| break; | ||
| case ts.SyntaxKind.MethodDeclaration: | ||
| { | ||
| if(dname == "get" || dname == "post" || dname == "put" || dname == "del" || dname == "all") { | ||
| let parent:ts.MethodDeclaration = <ts.MethodDeclaration>node.parent; | ||
| let symbol = checker.getSymbolAtLocation(parent.name); | ||
| parentIndex = getIndex(symbol); | ||
| let type = checker.getTypeOfSymbolAtLocation(symbol,symbol.valueDeclaration); | ||
| let typeNode = checker.typeToTypeNode(type,node.parent,ts.NodeBuilderFlags.IgnoreErrors|ts.NodeBuilderFlags.WriteTypeParametersInQualifiedName); | ||
| let parameterContext = parent.parameters; | ||
| comment = ts.displayPartsToString(symbol.getDocumentationComment(checker)); | ||
| returnType = parent.type; | ||
| let parms = (<any>typeNode).parameters; | ||
| let parmContext = parent.parameters; | ||
| let decoratorMeta = {}; | ||
| for(let i = 0;i < parmContext.length;i++) { | ||
| if(parmContext[i].decorators != null) { | ||
| for(let j = 0;j < parmContext[i].decorators.length;j++) { | ||
| const dec = (<ts.Decorator>parmContext[i].decorators[j]).expression; | ||
| let dsym = checker.getSymbolAtLocation(dec.getFirstToken()); | ||
| let dname = dsym.getName(); | ||
| let parmDecl:ts.ParameterDeclaration = <ts.ParameterDeclaration>dec.parent; | ||
| let psym = checker.getSymbolAtLocation(parmDecl.parent.name); | ||
| let pname = psym.getName(); | ||
| let decArgList; | ||
| if(ts.isCallExpression(dec)) { | ||
| decArgList = genArgumentList(<ts.CallExpression>dec); | ||
| } | ||
| if(decArgList == null) decArgList = []; | ||
| if(decoratorMeta[pname] == null) decoratorMeta[pname] = {}; | ||
| decoratorMeta[pname][dname] = decArgList; | ||
| } | ||
| } | ||
| } | ||
| methodParameters = traverseParameterList((<any>typeNode).parameters,decoratorMeta); | ||
| functionName = (<any>parent.name).text; | ||
| doRuntimeCheck = true; | ||
| } | ||
| } | ||
| break; | ||
| case ts.SyntaxKind.ClassDeclaration: | ||
| { | ||
| let parent:ts.ClassDeclaration = <ts.ClassDeclaration>node.parent; | ||
| let symbol = checker.getSymbolAtLocation(parent.name); | ||
| let source = <ts.SourceFile>(parent.parent); | ||
| parentIndex = getIndex(symbol); | ||
| comment = ts.displayPartsToString(symbol.getDocumentationComment(checker)); | ||
| if(dname == "controller") { | ||
| addController(parentIndex,source.fileName,comment); | ||
| doDecoratedClass = true; | ||
| } | ||
| else if(dname == "router") { | ||
| addRouter(parentIndex,source.fileName,comment); | ||
| doDecoratedClass = true; | ||
| } | ||
| ts.forEachChild(parent,visit); | ||
| } | ||
| break; | ||
| default: { | ||
| let parent = node.parent; | ||
| throw("unknown decorated type (" + parent.kind + ")"); | ||
| } | ||
| } | ||
| if(ts.isCallExpression(expr)) { | ||
| const cexpr = <ts.CallExpression>expr; | ||
| const id = <ts.Identifier>cexpr.expression; | ||
| let type = id.text; | ||
| if(type == "del") type = "delete"; | ||
| if(doRuntimeCheck) { | ||
| let symbol = checker.getSymbolAtLocation((<any>id.parent.parent.parent.parent).name); | ||
| let index = getIndex(symbol); | ||
| let decoratorArgs = genArgumentList(cexpr); | ||
| let sentry = symtabGet(index); | ||
| let item:DecoratedFunction = { | ||
| index:index, | ||
| classRef:sentry.schemaRefId, | ||
| comment:comment, | ||
| name:functionName, | ||
| decoratorArgs:decoratorArgs, | ||
| methodParameters:methodParameters, | ||
| returnType:returnType, | ||
| type:type | ||
| }; | ||
| endpoints.push(item); | ||
| } | ||
| else if(doDecoratedClass) { | ||
| let entry = symtabGet(parentIndex); | ||
| entry.args = genArgumentList(cexpr); | ||
| } | ||
| } | ||
| } | ||
| } | ||
| function saveObjectProperty(parentIndex:any,name:ts.PropertyName,typeDesc:ts.TypeNode,optional:boolean) { | ||
| let symbol = checker.getSymbolAtLocation(name); | ||
| let propertyName = tsany.getTextOfNode(name); | ||
| if(propertyName != null && typeDesc != null) { | ||
| let jsDoc = []; | ||
| let tags = symbol.getJsDocTags(); | ||
| let comment = ts.displayPartsToString(symbol.getDocumentationComment(checker)); | ||
| if(tags.length != 0) { | ||
| let tagSrc = ["/**"," *"]; | ||
| for(let i = 0;i < tags.length;i++) { | ||
| if(tags[i].name == "integer") tagSrc.push(" * @type {integer}"); | ||
| else tagSrc.push(` * @${tags[i].name} ${tags[i].text}`); | ||
| } | ||
| tagSrc.push(" */"); | ||
| try { | ||
| //checkFile.write(tagSrc.join('\n')); | ||
| jsDoc.push(doctrine.parse(tagSrc.join('\n'),{ unwrap:true })); | ||
| } | ||
| catch(e) { throw("invalid JSDoc: " + e); } | ||
| } | ||
| // Create and save the JSON schema definition for a property for later use | ||
| // Save the args to invoke the call later. This is necessary due to out | ||
| // of order definitions of child member types. | ||
| defComp.push({ | ||
| sentry:symtabGet(parentIndex), | ||
| propertyName:propertyName, | ||
| type:typeDesc, | ||
| jsDoc:jsDoc, | ||
| check:{ schemaNamespace:"check", docRoot:"#/definitions" }, | ||
| swagger:{ enclosedBy:parentIndex, options:{ schemaNamespace:"swagger", docRoot:"#/components/schemas", firstclassIntermediates:true }}, | ||
| optional:optional | ||
| }); | ||
| } | ||
| } | ||
| // Analyze the contents of a an interface or class declaration collect typing information | ||
| // and JSDoc style comments. | ||
| function visit2(node: ts.Node) { | ||
| let parent = node.parent; | ||
| let x; | ||
| if(parent.kind == ts.SyntaxKind.InterfaceDeclaration) x = (<ts.InterfaceDeclaration>parent).name; | ||
| else if(parent.kind == ts.SyntaxKind.ClassDeclaration) x = (<ts.ClassDeclaration>parent).name; | ||
| if(x != null) { | ||
| let parentSymbol = checker.getSymbolAtLocation(x); | ||
| let index = getIndex(parentSymbol); | ||
| switch(node.kind) { | ||
| case ts.SyntaxKind.PropertySignature: | ||
| { | ||
| // This will be the property node type if the parent is an interface | ||
| let sig = <ts.PropertySignature>node; | ||
| let name = <any>sig.name; | ||
| let optional = (sig.questionToken != null); | ||
| saveObjectProperty(index,name,sig.type,optional); | ||
| } | ||
| break; | ||
| case ts.SyntaxKind.PropertyDeclaration: | ||
| { | ||
| // This will be the property node type if the parent is a class | ||
| let pdecl = <ts.PropertyDeclaration>node; | ||
| let name = <any>pdecl.name; | ||
| let optional = (pdecl.questionToken != null); | ||
| saveObjectProperty(index,name,pdecl.type,optional); | ||
| } | ||
| break; | ||
| } | ||
| } | ||
| } | ||
| function compileProperties() { | ||
| for(let i = 0;i < defComp.length;i++) { | ||
| let checkDef = typeToJSON(defComp[i].type,defComp[i].jsDoc,defComp[i].check); | ||
| let swaggerDef = typeToJSON(defComp[i].type,defComp[i].jsDoc,defComp[i].swagger); | ||
| if(checkDef != null && swaggerDef != null) { | ||
| defComp[i].sentry.members[defComp[i].propertyName] = { desc:{ check:checkDef, swagger:swaggerDef }, type:defComp[i].type, optional:defComp[i].optional }; | ||
| } | ||
| } | ||
| } | ||
| function compileInheritance(sentry:any,heritageClauses:ts.NodeArray<ts.HeritageClause>) { | ||
| if(heritageClauses != null) { | ||
| ts.visitNodes(heritageClauses,function(n:ts.Node):ts.VisitResult<ts.Node> { | ||
| let h:ts.HeritageClause = <ts.HeritageClause>n; | ||
| ts.visitNodes(h.types,function(n:ts.Node):ts.VisitResult<ts.Node> { | ||
| let hType:ts.ExpressionWithTypeArguments = <ts.ExpressionWithTypeArguments>n; | ||
| let expr = hType.expression; | ||
| if(expr != null) { | ||
| let baseName; | ||
| switch(expr.kind) { | ||
| case ts.SyntaxKind.Identifier: baseName = <ts.Identifier>expr; break; | ||
| case ts.SyntaxKind.PropertyAccessExpression: baseName = (<ts.PropertyAccessExpression>expr).name; break; | ||
| default: throw("unknown inheritance source"); | ||
| } | ||
| let baseRef = checker.getSymbolAtLocation(baseName); | ||
| let baseIndex = getIndex(baseRef); | ||
| sentry.inherits.push(baseIndex); | ||
| } | ||
| return n; | ||
| }); | ||
| return n; | ||
| }); | ||
| } | ||
| } | ||
| // Recursively analyze an exported member of a source file. Relevant | ||
| // members include classes and interfaces and other refrenced types. | ||
| function visit(node: ts.Node) { | ||
| if(node.decorators != null) { | ||
| try { | ||
| for(const decorator of node.decorators) visitDecorator(decorator); | ||
| } | ||
| catch(e) { | ||
| console.log(e); | ||
| } | ||
| } | ||
| else if(tsany.isDeclaration(node)) { | ||
| let decl:ts.DeclarationStatement = <ts.DeclarationStatement>node; | ||
| let name = decl.name; | ||
| let type; | ||
| let symbol; | ||
| let comment; | ||
| let index; | ||
| let typeDesc; | ||
| if(name != null) { | ||
| symbol = checker.getSymbolAtLocation(name); | ||
| comment = ts.displayPartsToString(symbol.getDocumentationComment(checker)); | ||
| index = getIndex(symbol); | ||
| let type = checker.getDeclaredTypeOfSymbol(symbol); | ||
| typeDesc = checker.typeToTypeNode(type,node,ts.NodeBuilderFlags.IgnoreErrors|ts.NodeBuilderFlags.WriteTypeParametersInQualifiedName); | ||
| } | ||
| if(decl.kind == ts.SyntaxKind.TypeAliasDeclaration) { | ||
| let alias = <ts.TypeAliasDeclaration>decl; | ||
| ts.forEachChild(decl,visit); | ||
| symtabPut(index,{ kind:"type", decl:node, typeDesc:typeDesc, members:{}, jsDoc:null, comment:comment }); | ||
| } | ||
| else if(decl.kind == ts.SyntaxKind.ClassDeclaration) { | ||
| let classDecl = <ts.ClassDeclaration>decl; | ||
| let tags = ts.displayPartsToString(symbol.getJsDocTags()); | ||
| let sentry = symtabPut(index,{ kind:"type", decl:node, typeDesc:typeDesc, members:{}, inherits:[], jsDoc:null, comment:comment }); | ||
| if(tags != "") sentry.jsDoc = doctrine.parse(tags); | ||
| ts.forEachChild(decl,visit2); | ||
| compileInheritance(sentry,classDecl.heritageClauses); | ||
| } | ||
| else if(decl.kind == ts.SyntaxKind.InterfaceDeclaration) { | ||
| if(index != null) { | ||
| let intfDecl = <ts.InterfaceDeclaration>decl; | ||
| let tags = ts.displayPartsToString(symbol.getJsDocTags()); | ||
| let sentry:any = symtabPut(index,{ kind:"type", decl:node, typeDesc:typeDesc, members:{}, inherits:[], jsDoc:null, comment:comment }); | ||
| if(tags != "") sentry.jsDoc = doctrine.parse(tags); | ||
| ts.forEachChild(decl,visit2); | ||
| compileInheritance(sentry,intfDecl.heritageClauses); | ||
| } | ||
| } | ||
| } | ||
| } | ||
| // Loop over all the source files and recursively analyze each | ||
| // exported member of that file. Build a symbol table containing | ||
| // relevant information, and then generate new source for | ||
| // automatic REST endpoints (which typeshcekcing) as well as | ||
| // accompanying swagger. | ||
| for(const sourceFile of program.getSourceFiles()) { | ||
| if(debugMode === true) { | ||
| console.log("visiting file: ",sourceFile.fileName); | ||
| } | ||
| ts.forEachChild(sourceFile,visit); | ||
| } | ||
| compileProperties(); | ||
| connectMethods(endpoints); | ||
| genSources(endpoints,packageName,srcRoot,checkFile,swaggerFile,redocFile,routesFile); | ||
| } |
| import * as redoc from "../ReDoc"; | ||
| export function genRedoc(swaggerPath:string,redocFile:NodeJS.ReadWriteStream): void { | ||
| redocFile.write(redoc.src(swaggerPath)); | ||
| } |
| import * as ts from "typescript"; | ||
| const tsany = ts as any; | ||
| import { TypedId, PathDecomposition, DecoratedFunction, Controller, Router } from "./types"; | ||
| import { checker, getIndex, symtabGet, symtabPut, typeToJSON } from "./symtab"; | ||
| import { synthesizeParameterJSDoc, isExplicitStatus, isFileReturn, decomposePath, decompositionToPath, isURLParam } from "./traverse"; | ||
| /** | ||
| * Create the hardcoded first part of a swagger doc. Global documentation derived from the | ||
| * block comments of the controller classes as well as the class annotated with @router is set here. | ||
| * | ||
| * @param {any} def reference to the swagger doc. | ||
| * @param {string} projectName the name of the project (is derived from package.json packageName). | ||
| * @param {Router} router definition. | ||
| * @param {Controller[]} array of controller definitions. | ||
| */ | ||
| export function genSwaggerPreamble(def: any,projectName:string,router:Router,controllers:Controller[]): void { | ||
| let comments = ""; | ||
| if(router.comment != null && router.comment != '') comments += router.comment + "\n\n"; | ||
| def.openapi = "3.0.0"; | ||
| def.info = { version:"1.0.0", title:projectName }; | ||
| if(comments.length != 0) def.info.description = comments; | ||
| } | ||
| /** | ||
| * Generate swagger tags based on controller paths | ||
| * | ||
| * @param {any} def reference to the swagger doc. | ||
| * @param {Router} router definition. | ||
| * @param {Controller[]} array of controller definitions. | ||
| */ | ||
| export function genSwaggerRootTags(def: any,router:Router,controllers:Controller[]): void { | ||
| let tags = []; | ||
| for(let i = 0;i < controllers.length;i++) { | ||
| let tag = controllers[i].classRef; | ||
| if(controllers[i].comment != null && controllers[i].comment != '') | ||
| tags.push({ name:tag, description:controllers[i].comment }); | ||
| } | ||
| def.tags = tags; | ||
| } | ||
| function genSwaggerPathParameters(router:Router,controller:Controller,method:DecoratedFunction,methodPathDecomposition:PathDecomposition) { | ||
| let parameters = []; | ||
| for(let i = 0;i < method.methodParameters.length;i++) { | ||
| let parameter = method.methodParameters[i]; | ||
| let jsDoc = synthesizeParameterJSDoc(method.methodParameters[i]); | ||
| let parameterTypedef:any = typeToJSON(parameter.type,jsDoc,{ expandRefs:true, schemaNamespace:"swagger", docRoot:"#/components/schemas" }); | ||
| if(parameterTypedef != null && parameterTypedef.type == "object") { | ||
| for(let pname in parameterTypedef.properties) { | ||
| if(isURLParam(pname,router,controller,methodPathDecomposition)) | ||
| parameters.push({ name:pname, in:"path", schema:parameterTypedef.properties[pname], required:true }); | ||
| } | ||
| } | ||
| else { | ||
| if(isURLParam(parameter.id,router,controller,methodPathDecomposition)) | ||
| parameters.push({ name:parameter.id, in:"path", schema:parameterTypedef, required:true }); | ||
| } | ||
| } | ||
| return parameters; | ||
| } | ||
| function genSwaggerRequestParameters(router:Router,controller:Controller,method:DecoratedFunction,methodPathDecomposition:PathDecomposition) { | ||
| let parameters = []; | ||
| // Create the input doc swagger definition given the method parameters. Recursively expand | ||
| // objects rather that using JSON schema $ref, and if a method parameter is of type object, then | ||
| // assume it's a class or interance and instead generate a swagger doc that is the members of | ||
| // that aggregate. | ||
| for(let i = 0;i < method.methodParameters.length;i++) { | ||
| let parameter = method.methodParameters[i]; | ||
| let jsDoc = synthesizeParameterJSDoc(method.methodParameters[i]); | ||
| let parameterTypedef:any = typeToJSON(parameter.type,jsDoc,{ expandRefs:true, docRoot:"#/components/schemas" }); | ||
| if(parameterTypedef != null && parameterTypedef.type == "object") { | ||
| for(let pname in parameterTypedef.properties) { | ||
| let isRequired = false; | ||
| if(!isURLParam(pname,router,controller,methodPathDecomposition)) { | ||
| if(parameterTypedef.required != null) { | ||
| for(let l = 0;l < parameterTypedef.required.length;l++) { | ||
| if(parameterTypedef.required[l] == pname) isRequired = true; | ||
| } | ||
| } | ||
| parameters.push({ name:pname, in:"query", schema:parameterTypedef.properties[pname], required:isRequired }); | ||
| } | ||
| } | ||
| } | ||
| else if(!isURLParam(parameter.id,router,controller,methodPathDecomposition)) { | ||
| let parmDesc:any = { name:parameter.id, in:"query", schema:parameterTypedef }; | ||
| if(parameterTypedef.required != null && parameterTypedef.required.length > 0) parmDesc.required = parameterTypedef.required; | ||
| parameters.push(parmDesc); | ||
| } | ||
| } | ||
| return parameters; | ||
| } | ||
| function genSwaggerRequestBody(synthesizedTypes:any,router:Router,controller:Controller,method:DecoratedFunction,methodPathDecomposition:PathDecomposition) { | ||
| let parameters = []; | ||
| let parametersEx = []; | ||
| for(let i = 0;i < method.methodParameters.length;i++) { | ||
| let parameter = method.methodParameters[i]; | ||
| let jsDoc = synthesizeParameterJSDoc(method.methodParameters[i]); | ||
| let parameterTypedef:any = typeToJSON(parameter.type,jsDoc,{ schemaNamespace:"swagger", firstclassIntermediates:true, docRoot:"#/components/schemas" }); | ||
| let parameterTypedefEx:any = typeToJSON(parameter.type,jsDoc,{ expandRefs:true, schemaNamespace:"swagger", docRoot:"#/components/schemas" }); | ||
| if(!isURLParam(parameter.id,router,controller,methodPathDecomposition)) { | ||
| parameters.push({ name:parameter.id, required:parameter.required, schema:parameterTypedef }); | ||
| parametersEx.push({ name:parameter.id, required:parameter.required, schema:parameterTypedefEx }); | ||
| } | ||
| } | ||
| if(parameters.length == 1) { | ||
| let properties = {}; | ||
| let propertiesEx = {}; | ||
| let jsonContent; | ||
| let formContent; | ||
| let encoding = {}; | ||
| let encodingPopulated = false; | ||
| if(parameters[0].schema['$ref'] != null) { | ||
| jsonContent = { schema:parameters[0].schema }; | ||
| formContent = { schema:parametersEx[0].schema }; | ||
| } | ||
| else { | ||
| jsonContent = { schema:{ title: `${method.name} plist`, type:"object", properties:properties }}; | ||
| formContent = { schema:{ title: `${method.name} plist`, type:"object", properties:propertiesEx }}; | ||
| properties[parameters[0].name] = parameters[0].schema; | ||
| propertiesEx[parametersEx[0].name] = parametersEx[0].schema; | ||
| } | ||
| for(let property in parametersEx[0].schema.properties) { | ||
| if(parametersEx[0].schema.content != "flat" && (parametersEx[0].schema.properties[property].type == "object" || parametersEx[0].schema.properties[property] == null)) { | ||
| encoding[property] = { contentType:"application/json" }; | ||
| encodingPopulated = true; | ||
| } | ||
| } | ||
| if(encodingPopulated) formContent["encoding"] = encoding; | ||
| let res:any = { content:{ "application/json":jsonContent, "application/x-www-form-urlencoded":formContent }}; | ||
| if(parameters[0].required.length != 0) res.required = parameters[0].required; | ||
| return res; | ||
| } | ||
| else if(parameters.length > 1) { | ||
| let methodName = method.name; | ||
| let rqbName = `${controller.classRef}${methodName.substring(0,1).toUpperCase()}${methodName.substring(1)}Body`; | ||
| let properties = {}; | ||
| let required = []; | ||
| let notAllOptional = false; | ||
| let inline:any = { type:"object", properties:properties }; | ||
| let encoding = {}; | ||
| let encodingPopulated = false; | ||
| for(let i = 0;i < parameters.length;i++) { | ||
| properties[parameters[i].name] = parameters[i].schema; | ||
| if(parameters[i].schema.content != "flat" && (parameters[i].schema.type == "object" || parameters[i].schema.type == null)) { | ||
| encoding[parameters[i].name] = { contentType:"application/json" }; | ||
| encodingPopulated = true; | ||
| } | ||
| if(parameters[i].required) { | ||
| required.push(parameters[i].name); | ||
| notAllOptional = true; | ||
| } | ||
| } | ||
| let jsonContent = { schema:{ "$ref":`#/components/schemas/${rqbName}` }}; | ||
| let formContent = { schema:inline }; | ||
| if(encodingPopulated) formContent["encoding"] = encoding; | ||
| synthesizedTypes[rqbName] = { type:"object", properties:properties, description:`synthesized request body type for ${controller.classRef}.${methodName}` }; | ||
| if(notAllOptional) { | ||
| synthesizedTypes[rqbName].required = required; | ||
| inline.required = required; | ||
| } | ||
| return { | ||
| required:notAllOptional, | ||
| content:{ | ||
| "application/json":jsonContent, | ||
| "application/x-www-form-urlencoded":formContent | ||
| } | ||
| }; | ||
| } | ||
| else return { content:{} }; | ||
| } | ||
| function returnAtom(typeDesc:any) { | ||
| let index = getIndex(typeDesc); | ||
| let contentType = "application/json"; | ||
| let res = {}; | ||
| let schema; | ||
| if(index != null && index.local == "FileRef") { | ||
| let args = (<any>typeDesc).typeArguments; | ||
| if(args != null) { | ||
| contentType = tsany.getTextOfNode(args[0]); | ||
| contentType = contentType.replace(/^"(.*)"$/, '$1'); | ||
| } | ||
| else contentType = "application/octet-stream"; | ||
| schema = { type:"string", format:"binary" }; | ||
| } | ||
| else { | ||
| schema = typeToJSON(typeDesc,null,{ expandRefs:true, schemaNamespace:"swagger", docRoot:"#/components/schemas" }); | ||
| } | ||
| res[contentType] = { schema:schema }; | ||
| return res; | ||
| } | ||
| function updateExplicitStatus(res:any,statusCode:string,componentType:any) { | ||
| let content = returnAtom(componentType); | ||
| if(content != null) { | ||
| let n = parseInt(statusCode); | ||
| let description; | ||
| switch(n) { | ||
| case 200: description = "OK"; break; | ||
| case 201: description = "Created"; break; | ||
| case 202: description = "Accepted"; break; | ||
| case 203: description = "Non-Authoritative Information"; break; | ||
| case 204: description = "No Content"; break; | ||
| case 205: description = "Reset Content"; break; | ||
| case 206: description = "Partial Content"; break; | ||
| case 207: description = "Multi Status"; break; | ||
| case 208: description = "Already Reported"; break; | ||
| case 226: description = "IM Used"; break; | ||
| case 300: description = "Multiple Choices"; break; | ||
| case 302: description = "Found"; break; | ||
| case 303: description = "See Other"; break; | ||
| case 304: description = "Not Modified"; break; | ||
| case 305: description = "Use Proxy"; break; | ||
| case 306: description = "Switch Proxy"; break; | ||
| case 307: description = "Temporary Redirect"; break; | ||
| case 308: description = "Permanent Redirect"; break; | ||
| case 400: description = "Bad Request"; break; | ||
| case 401: description = "Unauthorized"; break; | ||
| case 402: description = "Payment Required"; break; | ||
| case 403: description = "Forbidden"; break; | ||
| case 404: description = "Not Found"; break; | ||
| case 405: description = "Method Not Allowed"; break; | ||
| case 406: description = "Not Acceptable"; break; | ||
| case 407: description = "Proxy Authentication Required"; break; | ||
| case 408: description = "Request Timeout"; break; | ||
| case 409: description = "Conflict"; break; | ||
| case 410: description = "Gone"; break; | ||
| case 411: description = "Length Required"; break; | ||
| case 412: description = "Precondition Failed"; break; | ||
| case 413: description = "Payload Too Large"; break; | ||
| case 414: description = "URI Too Long"; break; | ||
| case 415: description = "Unsupported Media Type"; break; | ||
| case 416: description = "Range Not Satisfiable"; break; | ||
| case 417: description = "Expectation Failed"; break; | ||
| case 418: description = "I'm a teapot"; break; | ||
| case 421: description = "Misdirected Request"; break; | ||
| case 422: description = "Unprocessable Entity"; break; | ||
| case 423: description = "Locked"; break; | ||
| case 424: description = "Failed Dependency"; break; | ||
| case 426: description = "Upgrade Required"; break; | ||
| case 428: description = "Precondition Required"; break; | ||
| case 429: description = "Too Many Request"; break; | ||
| case 431: description = "Request Header Fields Too Large"; break; | ||
| case 451: description = "Unavailable For Legal Reasons"; break; | ||
| case 500: description = "Internal Server Error"; break; | ||
| case 501: description = "Not Implemented"; break; | ||
| case 502: description = "Bad Gateway"; break; | ||
| case 503: description = "Service Unavailable"; break; | ||
| case 504: description = "Gateway Timeout"; break; | ||
| case 505: description = "HTTP Version Not Supported"; break; | ||
| case 506: description = "Variant Also Negotiates"; break; | ||
| case 507: description = "Insufficient Storage"; break; | ||
| case 508: description = "Loop Detected"; break; | ||
| case 510: description = "Not Extended"; break; | ||
| case 511: description = "Network Authentication Required"; break; | ||
| default: description = "Unknown"; break; | ||
| } | ||
| res[statusCode] = { description:description, content:content }; | ||
| } | ||
| else res["204"] = { description:"No Content" }; | ||
| return res; | ||
| } | ||
| function explicitStatus(returnTypeDesc:any) { | ||
| let res = {}; | ||
| let statusCodeDesc = (<any>returnTypeDesc).typeArguments[0]; | ||
| switch(statusCodeDesc.kind) { | ||
| case ts.SyntaxKind.LiteralType: | ||
| { | ||
| let statusCode = checker.getTypeFromTypeNode(statusCodeDesc).value; | ||
| let componentType = (<any>returnTypeDesc).typeArguments[1]; | ||
| updateExplicitStatus(res,statusCode,componentType); | ||
| } | ||
| break; | ||
| case ts.SyntaxKind.UnionType: | ||
| { | ||
| let unionDesc = <ts.UnionTypeNode>statusCodeDesc; | ||
| for(let i = 0;i < unionDesc.types.length;i++) { | ||
| let statusCode = checker.getTypeFromTypeNode(unionDesc.types[i]).value; | ||
| let componentType = (<any>returnTypeDesc).typeArguments[1]; | ||
| updateExplicitStatus(res,statusCode,componentType); | ||
| } | ||
| } | ||
| break; | ||
| } | ||
| return res; | ||
| } | ||
| function returnMerge(resN:any,resX:any) { | ||
| for(let statusCode in resN) { | ||
| if(resX[statusCode] == null) resX[statusCode] = resN[statusCode]; | ||
| else { | ||
| for(let contentType in resN[statusCode].content) { | ||
| if(resX[statusCode].content[contentType] == null) resX[statusCode].content[contentType] = resN[statusCode].content[contentType]; | ||
| else if(contentType == "application/json") { | ||
| if(resX[statusCode].content[contentType].oneOf == null) { | ||
| let tmp = resX[statusCode].content[contentType]; | ||
| resX[statusCode].content[contentType] = { oneOf:[] }; | ||
| resX[statusCode].content.oneOf.push(tmp); | ||
| } | ||
| resX[statusCode].content.oneOf.push(resN); | ||
| } | ||
| else throw("unable to combine non-hierarchial content types with oneOf"); | ||
| } | ||
| } | ||
| } | ||
| } | ||
| function genSwaggerReturn(returnTypeDesc:any,res:any) { | ||
| if(returnTypeDesc == null) return null; | ||
| let returnTypename = getIndex(returnTypeDesc); | ||
| // If the method return type is a promise infer that this is an async function and | ||
| // instead use the subordinate type as the type defined by the swagger doc. | ||
| if(returnTypename == "Promise") { | ||
| let promiseArg = (<any>returnTypeDesc).typeArguments[0]; | ||
| genSwaggerReturn(promiseArg,res); | ||
| } | ||
| else { | ||
| if(isExplicitStatus(returnTypename)) { | ||
| let resX:any = explicitStatus(returnTypeDesc); | ||
| for(let statusCode in resX) res[statusCode] = resX[statusCode]; | ||
| } | ||
| else if(isFileReturn(returnTypename)) { | ||
| let content = returnAtom(returnTypeDesc); | ||
| if(content != null) | ||
| res["200"] = { description:"Successful response", content:content }; | ||
| else res["204"] = { description:"Successful response" }; | ||
| } | ||
| else { | ||
| let isUnion = returnTypeDesc.kind == ts.SyntaxKind.UnionType; | ||
| if(!isUnion && returnTypeDesc.kind == ts.SyntaxKind.TypeReference) { | ||
| let alias = symtabGet(returnTypename).decl; | ||
| if(alias.type) { | ||
| isUnion = alias.type.kind == ts.SyntaxKind.UnionType; | ||
| if(isUnion) returnTypeDesc = alias.type; | ||
| } | ||
| } | ||
| if(isUnion) { | ||
| let unionDesc = <ts.UnionTypeNode>returnTypeDesc; | ||
| let resX = {}; | ||
| let isMultiStatus = false; | ||
| for(let i = 0;i < unionDesc.types.length;i++) { | ||
| let unionElementTypename = getIndex(unionDesc.types[i]); | ||
| if(unionElementTypename != null) { | ||
| if(!isExplicitStatus(unionElementTypename)) { | ||
| let swaggerDef = returnAtom(unionDesc.types[i]); | ||
| if(swaggerDef != null) { | ||
| let resY = {}; | ||
| resY["200"] = swaggerDef; | ||
| returnMerge(resY,resX); | ||
| } | ||
| } | ||
| else { | ||
| let resY = explicitStatus(unionDesc.types[i]); | ||
| returnMerge(resY,resX); | ||
| } | ||
| } | ||
| else { | ||
| let swaggerDef = returnAtom(unionDesc.types[i]); | ||
| if(swaggerDef != null) { | ||
| let resY = {}; | ||
| resY["200"] = swaggerDef; | ||
| returnMerge(resY,resX); | ||
| } | ||
| } | ||
| } | ||
| for(let statusCode in resX) res[statusCode] = resX[statusCode]; | ||
| } | ||
| else { | ||
| if(returnTypeDesc.kind == ts.SyntaxKind.TypeReference) { | ||
| let decl = symtabGet(returnTypename).decl; | ||
| if(decl.type) { | ||
| returnTypeDesc = decl.type; | ||
| returnTypename = getIndex(returnTypeDesc); | ||
| } | ||
| } | ||
| if(isExplicitStatus(returnTypename)) { | ||
| let resX:any = explicitStatus(returnTypeDesc); | ||
| for(let statusCode in resX) res[statusCode] = resX[statusCode]; | ||
| } | ||
| else { | ||
| let content = returnAtom(returnTypeDesc); | ||
| if(content != null) | ||
| res["200"] = { description:"Successful response", content:content }; | ||
| else res["204"] = { description:"Successful response" }; | ||
| } | ||
| } | ||
| } | ||
| } | ||
| } | ||
| /** | ||
| * Generate swagger paths (REST endpoints) given the combination of prefix, controller | ||
| * paths and methods of those controllers. | ||
| * | ||
| * @param {any} def reference to the swagger doc. | ||
| * @param {string} prefix top level path to pre-pend to all paths. | ||
| * @param {Controller[]} array of controller definitions. | ||
| */ | ||
| function genSwaggerPaths(def:any,synthesizedTypes:any,router:Router,controllers:Controller[]): void { | ||
| let paths:Object = {}; | ||
| let p1 = decompositionToPath(router.decomposition,"swagger"); | ||
| for(let i = 0;i < controllers.length;i++) { | ||
| let methods: DecoratedFunction[] = controllers[i].methods; | ||
| let p2 = decompositionToPath(controllers[i].decomposition,"swagger"); | ||
| let comment = controllers[i].comment; | ||
| let tag = controllers[i].classRef; | ||
| // For each controller, iterate over every method and create a path | ||
| // for it. If the method verb decorator contains a path use it, otherwise | ||
| // use the name of the method itself. | ||
| for(let j = 0;j < methods.length;j++) { | ||
| let methodPath = methods[j].name; | ||
| let parameters = []; | ||
| let methodType = methods[j].type; | ||
| let responses = {}; | ||
| let methodComment = methods[j].comment; | ||
| if(methods[j].decoratorArgs.length != 0) methodPath = methods[j].decoratorArgs[0]; | ||
| let methodPathDecomposition = decomposePath(methodPath); | ||
| let p3 = decompositionToPath(methodPathDecomposition,"swagger"); | ||
| // operationId is a unique identifier (across entire doc) for an operation | ||
| let operationId = tag + '_' + methods[j].name; | ||
| let path:any = { tags:[tag], operationId: operationId, responses:responses }; | ||
| let pathId = '/' + p2 + '/' + p3; | ||
| let pathParameters = genSwaggerPathParameters(router,controllers[i],methods[j],methodPathDecomposition); | ||
| if(methodComment != null && methodComment != "") path.description = methodComment; | ||
| genSwaggerReturn(methods[j].returnType,responses); | ||
| if(methodType == "post" || methodType == "all" || methodType == "put" || methodType == "patch") { | ||
| if(pathParameters.length != 0) path.parameters = pathParameters; | ||
| path.requestBody = genSwaggerRequestBody(synthesizedTypes,router,controllers[i],methods[j],methodPathDecomposition); | ||
| } | ||
| else path.parameters = pathParameters.concat(genSwaggerRequestParameters(router,controllers[i],methods[j],methodPathDecomposition)); | ||
| if(p1 != "") pathId = '/' + p1 + pathId; | ||
| if(paths[pathId] == null) paths[pathId] = {}; | ||
| paths[pathId][methodType] = path; | ||
| } | ||
| } | ||
| def.paths = paths; | ||
| } | ||
| /** | ||
| * Generate all paths belonging to a router. The expectation is that currently there will | ||
| * only be a singleton router. | ||
| * | ||
| * @param {any} def reference to the swagger doc. | ||
| * @param {Router} router definition. | ||
| * @param {Controller[]} array of controller definitions. | ||
| */ | ||
| export function genSwaggerRoutes(def:any,synthesizedTypes:any,router:Router,controllers:Controller[]): void { | ||
| let prefix = decompositionToPath(router.decomposition,"swagger"); | ||
| genSwaggerPaths(def,synthesizedTypes,router,controllers); | ||
| } |
| import * as ts from "typescript"; | ||
| import { TypedId, PathDecomposition, DecoratedFunction, Controller, Router } from "./types"; | ||
| const tsany = ts as any; | ||
| let symtab: any = {}; | ||
| let schemaRefIds:any = {}; | ||
| let numIntermediates = 0; | ||
| let checker; | ||
| function getSourceContext(n:ts.Node) { | ||
| let start = n; | ||
| while(n != null && n.parent != null && n.parent.kind != ts.SyntaxKind.SourceFile) n = n.parent; | ||
| if(n != null && n.parent != null) { | ||
| let loc = ts.getLineAndCharacterOfPosition((<ts.SourceFile>n.parent),(<ts.Node>start).pos); | ||
| return { fileName:(<ts.SourceFile>n.parent).fileName, lineNumber:loc.line }; | ||
| } | ||
| } | ||
| function setChecker(program) { | ||
| checker = program.getTypeChecker(); | ||
| } | ||
| function symtabKeyToString(key:any) { | ||
| if(typeof key == "string") return key; | ||
| else if(typeof key == "object") { | ||
| if(key.module != null && key.local != null) return `${key.module}${key.local}`; | ||
| if(key.local != null) return key.local; | ||
| } | ||
| return null; | ||
| } | ||
| function symtabGet(key:any):any { | ||
| let s = symtabKeyToString(key); | ||
| if(s != null) return symtab[s]; | ||
| return null; | ||
| } | ||
| function newSchemaRefId(key:any) { | ||
| if(typeof key == "string") return key; | ||
| if(key.local != null) { | ||
| if(schemaRefIds[key.local] == null) { | ||
| schemaRefIds[key.local] = { ext:1 }; | ||
| return key.local; | ||
| } | ||
| else schemaRefIds[key.local].ext++; | ||
| return `${key.local}-${schemaRefIds[key.local].ext}`; | ||
| } | ||
| } | ||
| function symtabPut(key:any,obj:any):any { | ||
| let s = symtabKeyToString(key); | ||
| if(s != null) { | ||
| symtab[s] = obj; | ||
| symtab[s].schemaRefId = newSchemaRefId(key); | ||
| return obj; | ||
| } | ||
| return null; | ||
| } | ||
| function storeIntermediate(obj:any) { | ||
| let key = { local:`Intermediate${numIntermediates++}`, module:"ts-api" } | ||
| obj.kind = "itype"; | ||
| symtabPut(key,obj); | ||
| return key.local; | ||
| } | ||
| /** | ||
| * This function translates a token found in an AST for a type declaration to the | ||
| * corresponding JSON schema definition. The implementation for some objects is | ||
| * undefined (e.g. Function) and that token is ignored, unrecognized tokens cause | ||
| * an exception. | ||
| * | ||
| * @param {any} o The AST token object. | ||
| * @param {any} jsDoc A reference to the JSDoc object. | ||
| */ | ||
| function tokenObjectToJSON(o:any,jsDoc:any) { | ||
| let res = null; | ||
| let unknown = false; | ||
| switch(o.kind) { | ||
| case ts.SyntaxKind.StringKeyword: | ||
| { | ||
| res = { type:"string" }; | ||
| } | ||
| break; | ||
| case ts.SyntaxKind.NumberKeyword: | ||
| { | ||
| res = { type:"number" }; | ||
| } | ||
| break; | ||
| case ts.SyntaxKind.BooleanKeyword: res = { type:"boolean" }; break; | ||
| case ts.SyntaxKind.AnyKeyword: res = { anyOf:[ { type:"array" }, { type:"object" }, { type:"number" }, { type:"string" }]}; break; | ||
| case ts.SyntaxKind.NullKeyword: res = { type:"null" }; break; | ||
| case ts.SyntaxKind.UndefinedKeyword: break; | ||
| case ts.SyntaxKind.UnknownKeyword: break; | ||
| case ts.SyntaxKind.SymbolKeyword: break; | ||
| case ts.SyntaxKind.ObjectKeyword: res = { type:"object" }; break; | ||
| case ts.SyntaxKind.FunctionType: break; | ||
| case ts.SyntaxKind.VoidKeyword: res = { type:"null" }; break; | ||
| case ts.SyntaxKind.NeverKeyword: break; | ||
| break; | ||
| default: unknown = true; break; | ||
| } | ||
| if(unknown) { | ||
| let sc = getSourceContext(o); | ||
| if(sc != null) | ||
| throw(`cannot convert unknown token (${o.kind}) to JSON\n file = ${sc.fileName} line = ${sc.lineNumber}`); | ||
| throw(`cannot convert unknown token (${o.kind}) to JSON`); | ||
| } | ||
| return res; | ||
| } | ||
| /** | ||
| * This function converts typescript keywords to JSON schema. | ||
| * | ||
| * @param {string} docRoot The root path in the document object for JSDoc | ||
| * definitions. Used to construct $ref values. | ||
| * @param {string} name The name of the typescript type. | ||
| */ | ||
| function mapTypeDescName(docRoot:string,name:string): Object { | ||
| if(name == "Object") return { type:"object" }; | ||
| if(name == "String") return { type:"string" }; | ||
| if(name == "Number") return { type:"number" }; | ||
| if(name == "Boolean") return { type:"boolean" }; | ||
| if(name == "Function") return null; | ||
| return { "$ref":`${docRoot}/${name}` }; | ||
| } | ||
| /** | ||
| * Convert a typescript union declaration to JSON schema; this is supported | ||
| * by use of the keyword anyOf. | ||
| * | ||
| * @param {any} typeDesc The AST subtree describing the union type. | ||
| * @param {any} jsDoc A reference to the current JSDoc document. | ||
| * @param {any} options Optional values effecting the output form. Currently | ||
| * serves as a parameter to the recursive call to typeToJSON. | ||
| */ | ||
| function unionToJSON(typeDesc:any,jsDoc:any,context?:any):Object { | ||
| let unionDesc = <ts.UnionTypeNode>typeDesc; | ||
| let res = { anyOf:[] }; | ||
| for(let i = 0;i < unionDesc.types.length;i++) { | ||
| let unionElement = typeToJSON(unionDesc.types[i],null,context); | ||
| if(unionElement != null) res.anyOf.push(unionElement); | ||
| } | ||
| return res; | ||
| } | ||
| /** | ||
| * Convert a typescript intersection declaration to JSON schema; this is supported | ||
| * by use of the keyword allOf. | ||
| * | ||
| * @param {any} typeDesc The AST subtree describing the intersection type. | ||
| * @param {any} jsDoc A reference to the current JSDoc document. | ||
| * @param {any} options Optional values effecting the output form. Currently | ||
| * serves as a parameter to the recursive call to typeToJSON. | ||
| */ | ||
| function intersectionToJSON(typeDesc:any,jsDoc:any,context?:any):Object { | ||
| let intersectionDesc = <ts.IntersectionTypeNode>typeDesc; | ||
| let res = { allOf:[] }; | ||
| for(let i = 0;i < intersectionDesc.types.length;i++) { | ||
| let intersectionElement = typeToJSON(intersectionDesc.types[i],null,context); | ||
| if(intersectionElement != null) res.allOf.push(intersectionElement); | ||
| } | ||
| return res; | ||
| } | ||
| /** | ||
| * Create the JSON schema for a typescript literal type. Literal types | ||
| * can be expressed using the pattern keyword. | ||
| * | ||
| * @param {any} typeDesc The AST subtree describing the literal. | ||
| * @param {any} jsDoc A reference to the current JSDoc document. | ||
| */ | ||
| function literalToJSON(typeDesc:any,jsDoc:any):Object { | ||
| let type = checker.getTypeFromTypeNode(typeDesc); | ||
| if(type.value != null) { | ||
| let valueType = typeof type.value; | ||
| if(valueType == "string") return { type:"string", pattern:`^${type.value}$` }; | ||
| else if(valueType == "number") { | ||
| let numericValue = parseFloat(type.value); | ||
| return { type:"number", minimum:numericValue, maximum:numericValue }; | ||
| } | ||
| } | ||
| let literal = checker.typeToString(type); | ||
| if(literal == "false" || literal == "true") return { type:"boolean" }; | ||
| let sc = getSourceContext(typeDesc); | ||
| if(sc != null) | ||
| throw(`unknown literal type (${literal})\n file = ${sc.fileName} line = ${sc.lineNumber}`); | ||
| throw(`unknown literal type (${literal})`); | ||
| } | ||
| function typeliteralToJSON(typeDesc:any,jsDoc:any,context?:any):Object { | ||
| let typeliteralDesc = <ts.TypeLiteralNode>typeDesc; | ||
| let properties = {}; | ||
| let required = []; | ||
| let elements = []; | ||
| for(let i = 0;i < typeliteralDesc.members.length;i++) { | ||
| let element = <ts.TypeElement>typeliteralDesc.members[i]; | ||
| if(element.name != null) { | ||
| let propertyName = tsany.getTextOfNode(element.name); | ||
| properties[propertyName] = typeToJSON(element,null,context); | ||
| if(element.questionToken == null) required.push(propertyName); | ||
| } | ||
| else { | ||
| let j = typeToJSON(element,null,context); | ||
| if(j != null) elements.push(j); | ||
| } | ||
| } | ||
| if(Object.keys(properties).length > 0 && elements.length == 0) { | ||
| if(context != null && context.options != null && context.options.firstclassIntermediates) { | ||
| let schema:any = { type:"object", properties:properties }; | ||
| if(required.length > 0) schema.required = required; | ||
| let iname = storeIntermediate({ enclosedBy:context.enclosedBy, schema:schema }); | ||
| return { "$ref":`${context.options.docRoot}/${iname}` }; | ||
| } | ||
| else { | ||
| let schema:any = { type:"object", properties:properties }; | ||
| if(required.length > 0) schema.required = required; | ||
| return schema; | ||
| } | ||
| } | ||
| else if(elements.length != 0 && Object.keys(properties).length == 0) { | ||
| return { anyOf:elements }; | ||
| } | ||
| else if(elements.length == 0 && Object.keys(properties).length == 0) { | ||
| return { type: "object", properties:[] }; | ||
| } | ||
| else { | ||
| let type = checker.getTypeFromTypeNode(typeDesc); | ||
| let literal = checker.typeToString(type); | ||
| let sc = getSourceContext(typeDesc); | ||
| if(sc != null) | ||
| throw(`unable to map typeliteral containing both named and unnamed elements ${literal}\n file = ${sc.fileName} line = ${sc.lineNumber}`); | ||
| throw(`unable to map typeliteral containing both named and unnamed elements ${literal}`); | ||
| } | ||
| } | ||
| function tupleTypeToJSON(typeDesc:any,jsDoc:any,context?:any):Object { | ||
| let tupleDesc = <ts.TupleTypeNode>typeDesc; | ||
| let res = { allOf:[] }; | ||
| for(let i = 0;i < tupleDesc.elementTypes.length;i++) { | ||
| let tupleElement = typeToJSON(tupleDesc.elementTypes[i],null,context); | ||
| if(tupleElement != null) res.allOf.push(tupleElement); | ||
| } | ||
| return res; | ||
| } | ||
| function indexedAccessTypeToJSON(typeDesc:any,jsDoc:any,context?:any):Object { | ||
| let iaDesc = <ts.IndexedAccessTypeNode>typeDesc; | ||
| let indexType = checker.getTypeFromTypeNode(typeDesc.indexType); | ||
| let objectType = checker.getTypeFromTypeNode(typeDesc.objectType); | ||
| let index = checker.typeToString(indexType); | ||
| let objs = checker.typeToString(objectType); | ||
| let res; | ||
| if(index == "ArrayBuffer" && objs == "ArrayBufferTypes") return { type:"string", hint:{ encoding:"base64" }}; | ||
| return typeToJSON(typeDesc.objectType,jsDoc,context); | ||
| } | ||
| function mappedTypeToJSON(typeDesc:any,jsDoc:any,context?:any):Object { | ||
| let mapDesc = <ts.MappedTypeNode>typeDesc; | ||
| let constraint = ts.getEffectiveConstraintOfTypeParameter(mapDesc.typeParameter); | ||
| let res; | ||
| if (typeDesc.nextContainer) { | ||
| //console.log("next: ",typeDesc.nextContainer.type); | ||
| let type = checker.getTypeFromTypeNode(typeDesc.nextContainer.type); | ||
| let types = checker.typeToString(type); | ||
| //console.log("subordinate type: ",types); | ||
| //console.log("constraint: ",constraint); | ||
| //console.log("desc: ",typeDesc); | ||
| return typeToJSON(typeDesc.nextContainer.type,jsDoc,context); | ||
| } | ||
| return {}; | ||
| } | ||
| function conditionalTypeToJSON(typeDesc:any,jsDoc:any,context?:any):Object { | ||
| let conditionalDesc = <ts.ConditionalTypeNode>typeDesc; | ||
| let type = checker.getTypeFromTypeNode(typeDesc); | ||
| ///console.log("conditional type = ",checker.typeToString(type)); | ||
| return typeToJSON(conditionalDesc.extendsType,jsDoc,context); | ||
| } | ||
| /** | ||
| * This function adds the specified value tag to a JSON schema component. | ||
| * | ||
| * @param {any} schemaObject Reference to the schema component. | ||
| * @param {string} title The value attribute name. | ||
| * @param {any} value The value to set. | ||
| */ | ||
| function applyValueTag(schemaObject: any,title: string,value: any): void { | ||
| if(schemaObject.type != null && schemaObject.type != "null") schemaObject[title] = value; | ||
| else if(schemaObject.oneOf != null) { | ||
| for(let i = 0;i < schemaObject.oneOf.length;i++) { | ||
| if(schemaObject.oneOf[i].type != null && schemaObject.oneOf[i].type != "null") schemaObject.oneOf[i][title] = value; | ||
| } | ||
| } | ||
| } | ||
| /** | ||
| * This function adds typing infomation to the speficied JSON schema component. | ||
| * | ||
| * @param {any} schemaObject Reference to the schema component. | ||
| * @param {string} name The typename. | ||
| */ | ||
| function applyTypenameTag(schemaObject: any,name: string): void { | ||
| if(schemaObject.type != null && schemaObject.type != "null") schemaObject.type = name; | ||
| else if(schemaObject.oneOf != null) { | ||
| for(let i = 0;i < schemaObject.oneOf.length;i++) { | ||
| if(schemaObject.oneOf[i].type != null && schemaObject.oneOf[i].type != "null") schemaObject.oneOf[i].type = name; | ||
| } | ||
| } | ||
| } | ||
| /** | ||
| * This function adds a tag to a JSON schema component. The type of tag to apply | ||
| * is inferred from the contents of the tag. If the tag is not applicable to the | ||
| * type, then an error is raised. If the type is an array, the elemement type | ||
| * is used where applicable. | ||
| * | ||
| * @param {any} schemaObject Reference to the schema component. | ||
| * @param {any} tag The tag to apply. | ||
| */ | ||
| function applyTag(schemaObject: any,tag: any): void { | ||
| if(tag == null) return; | ||
| if(tag.title == "minimum" || tag.title == "maximum") { | ||
| if(schemaObject.type == "array") applyTag(schemaObject.items,tag); | ||
| else if(schemaObject.type != "number") throw(`@${tag.title} can only be applied to numbers`); | ||
| applyValueTag(schemaObject,tag.title,parseInt(tag.description)); | ||
| } | ||
| else if(tag.title == "minLength" || tag.title == "maxLength") { | ||
| if(schemaObject.type == "array") applyTag(schemaObject.items,tag); | ||
| else if(schemaObject.type != "string") throw(`@${tag.title} can only be applied to strings`); | ||
| applyValueTag(schemaObject,tag.title,parseInt(tag.description)); | ||
| } | ||
| else if(tag.title == "minItems" || tag.title == "maxItems") { | ||
| if(schemaObject.type != "array") throw(`@${tag.title} can only be applied to arrays`); | ||
| applyValueTag(schemaObject,tag.title,parseInt(tag.description)); | ||
| } | ||
| else if(tag.title == "format" || tag.title == "pattern") { | ||
| if(schemaObject.type == "array") applyTag(schemaObject.items,tag); | ||
| else if(schemaObject.type != "string") throw(`@format can only be applied to strings`); | ||
| let value = tag.description.replace(/^{(.*)}$/,"$1"); | ||
| applyValueTag(schemaObject,tag.title,value); | ||
| } | ||
| else if(tag.title == "precision") { | ||
| if(schemaObject.type == "array") applyTag(schemaObject.items,tag); | ||
| else if(schemaObject.type != "number") throw(`@${tag.title} can only be applied to numbers`); | ||
| schemaObject.precision = parseInt(tag.description); | ||
| } | ||
| else if(tag.title == "type") { | ||
| if(schemaObject.type == "array") applyTag(schemaObject.items,tag); | ||
| else if(tag.type.type == "NameExpression") applyTypenameTag(schemaObject,tag.type.name); | ||
| } | ||
| } | ||
| function isTypeNode(desc:ts.TypeNode|ts.Symbol):boolean { | ||
| try { | ||
| (<ts.Node>desc).getSourceFile(); | ||
| return ts.isTypeNode(<ts.Node>desc); | ||
| } | ||
| catch(e) { | ||
| return false; | ||
| } | ||
| } | ||
| function getIndex(desc:ts.TypeNode|ts.Symbol) { | ||
| if(desc == null) return null; | ||
| let FQN; | ||
| let index; | ||
| if(isTypeNode(desc)) { | ||
| let typeName = (<any>desc).typeName; | ||
| try { | ||
| let symbol1 = checker.getSymbolAtLocation(typeName); | ||
| let symbol2; | ||
| try { symbol2 = checker.getAliasedSymbol(symbol1); } catch(e) {} | ||
| let local = tsany.getTextOfNode(typeName); | ||
| index = local; | ||
| if(symbol2 == null) FQN = checker.getFullyQualifiedName(symbol1); | ||
| else FQN = checker.getFullyQualifiedName(symbol2); | ||
| } | ||
| catch(e) { | ||
| if(typeName == null) return null; | ||
| let type = checker.getTypeFromTypeNode(<any>desc); | ||
| let symbol1 = (<any>desc).typeName.symbol; | ||
| let symbol2; | ||
| try { symbol2 = checker.getAliasedSymbol(symbol1); } catch(e) {} | ||
| if(symbol2 == null) FQN = checker.getFullyQualifiedName(symbol1); | ||
| else FQN = checker.getFullyQualifiedName(symbol2); | ||
| } | ||
| } | ||
| else { | ||
| let symbol2; | ||
| try { symbol2 = checker.getAliasedSymbol(desc); } catch(e) {} | ||
| if(symbol2 == null) FQN = checker.getFullyQualifiedName(desc); | ||
| else FQN = checker.getFullyQualifiedName(symbol2); | ||
| } | ||
| if(FQN != "__type") { | ||
| let components = FQN.split('"'); | ||
| if(components.length == 1) index = components[0]; | ||
| else index = { module:components[1], local:components[2].substring(1) }; | ||
| } | ||
| return index; | ||
| } | ||
| /** | ||
| * This function is the main entry point for converting a AST subtree describing a | ||
| * type declaration to its analogous JSON schema definition. Some typescript features | ||
| * are not mappable currently (e.g. functions), while some are simply not implemented | ||
| * yet. The typescript parser also collects JSDoc style comments associated with a | ||
| * type declaration and exposes that information in the AST as well. These comments | ||
| * are also part of the output JSON schema. The context of the use of the JSON schema | ||
| * can also effect the structure of the schema (e.g. use references to another part of | ||
| * the containing document, or expand fully all references). Such infomation is passed | ||
| * using options. | ||
| * | ||
| * @param {any} typeDesc Reference to the AST substree describing the type for which to | ||
| * create the JSON schema. | ||
| * @param {any} jsDoc The associated JSDoc comment. | ||
| * @param {any} options Affects the rules governing the structure of the resulting schema. | ||
| */ | ||
| function typeToJSON(typeDesc:any,jsDoc:any,context?:any):Object { | ||
| let res; | ||
| let type = checker.getTypeFromTypeNode(typeDesc); | ||
| if(context != null && context.options == null) context = { options:context }; | ||
| if(typeDesc == null) return { type:"object" }; | ||
| if(typeDesc.constructor.name == 'NodeObject') { | ||
| let unknown = false; | ||
| let docRoot = "#/definitions"; | ||
| let schemaNamespace = "check"; | ||
| if(context != null && context.options != null && context.options.docRoot != null) docRoot = context.options.docRoot; | ||
| if(context != null && context.options != null && context.options.schemaNamespace != null) schemaNamespace = context.options.schemaNamespace; | ||
| switch(typeDesc.kind) { | ||
| case ts.SyntaxKind.ArrayType: res = { type:"array", items:typeToJSON(typeDesc.elementType,null,context) }; break; | ||
| case ts.SyntaxKind.TypeReference: | ||
| { | ||
| let index = getIndex(typeDesc); | ||
| if(index == "Array") { | ||
| let arg = (<any>typeDesc).typeArguments[0]; | ||
| res = { type:"array", items:typeToJSON(arg,jsDoc,context) } | ||
| } | ||
| else if(index == "Date") { | ||
| res = { oneOf:[{ type:"string", format:"date" }, { type:"string", format:"date-time" }], toDate:true, content:"flat" }; | ||
| } | ||
| else { | ||
| let name = index; | ||
| if(typeof name != "string") { | ||
| let sentry:any = symtabGet(index); | ||
| if(sentry != null) name = sentry.schemaRefId; | ||
| else name = null; | ||
| } | ||
| res = mapTypeDescName(docRoot,name); | ||
| if(res != null && res['$ref'] != null && context != null && context.options != null && context.options.expandRefs) { | ||
| let sentry:any = symtabGet(index); | ||
| if(sentry == null) { | ||
| let sc = getSourceContext(typeDesc); | ||
| if(sc != null) { | ||
| let _a:any = null; | ||
| console.log(_a.b); | ||
| throw(`undefined type reference ${index}\n file = ${sc.fileName} line = ${sc.lineNumber}`); | ||
| } | ||
| throw(`undefined type reference ${index}`); | ||
| } | ||
| res = sentry.schema[schemaNamespace]; | ||
| } | ||
| } | ||
| } | ||
| break; | ||
| case ts.SyntaxKind.PropertySignature: | ||
| { | ||
| let propertySignatureDesc:ts.PropertySignature = <ts.PropertySignature>typeDesc; | ||
| if(propertySignatureDesc.type != null) res = typeToJSON(propertySignatureDesc.type,jsDoc,context); | ||
| else res = null; | ||
| } | ||
| break; | ||
| case ts.SyntaxKind.CallSignature: /* console.log(`ignoring call signature type ${checker.typeToString(type)}`); */ break; | ||
| case ts.SyntaxKind.MethodSignature: /* console.log(`ignoring method signature type ${checker.typeToString(type)}`); */ break; | ||
| case ts.SyntaxKind.FunctionType: /* console.log(`ignoring function type ${checker.typeToString(type)}`); */ break; | ||
| case ts.SyntaxKind.ConstructorType: /* console.log(`ignoring constructor type ${checker.typeToString(type)}`); */ break; | ||
| case ts.SyntaxKind.TypeQuery: /* console.log(`ignoring type query ${checker.typeToString(type)}`); */ break; | ||
| case ts.SyntaxKind.ParenthesizedType: /* console.log(`ignoring paranthesized type ${checker.typeToString(type)}`); */ break; | ||
| case ts.SyntaxKind.IndexSignature: /* console.log(`ignoring index signature ${checker.typeToString(type)}`); */ break; | ||
| case ts.SyntaxKind.TypeOperator: /* console.log(`ignoring type operator ${checker.typeToString(type)}`); */ break; | ||
| case ts.SyntaxKind.UnionType: res = unionToJSON(typeDesc,jsDoc,context); break; | ||
| case ts.SyntaxKind.LiteralType: res = literalToJSON(typeDesc,jsDoc); break; | ||
| case ts.SyntaxKind.IntersectionType: res = intersectionToJSON(typeDesc,jsDoc,context); break; | ||
| case ts.SyntaxKind.ConditionalType: res = conditionalTypeToJSON(typeDesc,jsDoc,context); break; | ||
| case ts.SyntaxKind.TypeLiteral: res = typeliteralToJSON(typeDesc,jsDoc,context); break; | ||
| case ts.SyntaxKind.MappedType: res = mappedTypeToJSON(typeDesc,jsDoc,context); break; | ||
| case ts.SyntaxKind.TupleType: res = tupleTypeToJSON(typeDesc,jsDoc,context); break; | ||
| case ts.SyntaxKind.IndexedAccessType: res = indexedAccessTypeToJSON(typeDesc,jsDoc,context); break; | ||
| default: unknown = true; break; | ||
| } | ||
| if(unknown) { | ||
| let sc = getSourceContext(typeDesc); | ||
| if(sc != null) { | ||
| /* Useful to debug never before seen types, usually not interesting enough to leave it in for users | ||
| let uType = checker.getTypeFromTypeNode(typeDesc); | ||
| let typeText = checker.typeToString(uType); | ||
| console.log(typeText); | ||
| */ | ||
| throw(`cannot convert unknown type (${typeDesc.kind}) to JSON\n file = ${sc.fileName} line = ${sc.lineNumber}`); | ||
| } | ||
| throw(`cannot convert unknown type (${typeDesc.kind}) to JSON`); | ||
| } | ||
| } | ||
| else if(typeDesc.constructor.name == 'TokenObject') res = tokenObjectToJSON(typeDesc,jsDoc); | ||
| else { | ||
| let sc = getSourceContext(typeDesc); | ||
| if(sc != null) | ||
| throw(`unknown type (${typeDesc.constructor.name})\n file = ${sc.fileName} line = ${sc.lineNumber}`); | ||
| throw(`unknown type (${typeDesc.constructor.name})`); | ||
| } | ||
| if(res) { | ||
| let symbol = type.symbol; | ||
| if(jsDoc != null && jsDoc.length != 0) { | ||
| for(let i = 0;i < jsDoc.length;i++) { | ||
| if(jsDoc[i].tags != null && jsDoc[i].tags.length != 0) { | ||
| for(let j = 0;j < jsDoc[i].tags.length;j++) applyTag(res,jsDoc[i].tags[j]); | ||
| } | ||
| } | ||
| } | ||
| if(symbol) res.description = ts.displayPartsToString(symbol.getDocumentationComment(checker)); | ||
| } | ||
| return res; | ||
| } | ||
| export { | ||
| checker, | ||
| getIndex, | ||
| mapTypeDescName, | ||
| setChecker, | ||
| symtab, | ||
| symtabGet, | ||
| symtabPut, | ||
| typeToJSON | ||
| }; |
| import * as ts from "typescript"; | ||
| import * as doctrine from "doctrine"; | ||
| import * as path from "path"; | ||
| const tsany = ts as any; | ||
| import { TypedId, PathDecomposition, DecoratedFunction, Controller, Router } from "./types"; | ||
| import { checker, getIndex, mapTypeDescName, symtab, symtabGet, symtabPut, typeToJSON } from "./symtab"; | ||
| /** | ||
| * This function marks all component types of a union type that is relevant as also relevant. | ||
| * | ||
| * @param {any} typeDesc Reference to the AST substree describing the type. | ||
| * @param {any} jsDoc The associated JSDoc comment. | ||
| * @param {any} options Affects the rules governing the recursion. | ||
| */ | ||
| function markUnionAsRelevant(typeDesc:any,jsDoc:any,options?:any) { | ||
| let unionDesc = <ts.UnionTypeNode>typeDesc; | ||
| for(let i = 0;i < unionDesc.types.length;i++) markAsRelevant(unionDesc.types[i],null,options); | ||
| } | ||
| /** | ||
| * This function marks all component types of an intersection type that is relevant as also relevant. | ||
| * | ||
| * @param {any} typeDesc Reference to the AST substree describing the type. | ||
| * @param {any} jsDoc The associated JSDoc comment. | ||
| * @param {any} options Affects the rules governing the recursion. | ||
| */ | ||
| function markIntersectionAsRelevant(typeDesc:any,jsDoc:any,options?:any) { | ||
| let intersectionDesc = <ts.IntersectionTypeNode>typeDesc; | ||
| for(let i = 0;i < intersectionDesc.types.length;i++) markAsRelevant(intersectionDesc.types[i],null,options); | ||
| } | ||
| /** | ||
| * This function marks a type as relevant. The purpose of marking a type relevant is to | ||
| * reduce the number of elements that appear in a describing document. Otherwise not only would | ||
| * al declared types by output, so too would all typescript built-in types which would lead | ||
| * to an unnecessarily enormous document. The expectation is that any class that is annotated | ||
| * with a decorator relevant to this project and any type used in a method that is likewise | ||
| * decorated as well as all of the types that help define those aformentioned types would be | ||
| * relevant in this way. Thus this function is call for those types and then recursively | ||
| * calls itself for an component types. | ||
| * | ||
| * @param {any} typeDesc Reference to the AST substree describing the type. | ||
| * @param {any} jsDoc The associated JSDoc comment. | ||
| * @param {any} options Affects the rules governing the recursion. | ||
| */ | ||
| function markAsRelevant(typeDesc:any,jsDoc:any,options?:any) { | ||
| if(typeDesc.constructor.name == 'NodeObject') { | ||
| switch(typeDesc.kind) { | ||
| case ts.SyntaxKind.ArrayType: markAsRelevant(typeDesc.elementType,jsDoc,options); break; | ||
| case ts.SyntaxKind.TypeReference: | ||
| { | ||
| let alias = <ts.TypeAliasDeclaration>typeDesc; | ||
| let index = getIndex(typeDesc); | ||
| let args = (<any>typeDesc).typeArguments; | ||
| let ref:any = symtabGet(index); | ||
| if(ref == null) { | ||
| throw(`undefined type ${index} in relevancy tree`); | ||
| } | ||
| ref.relevant = true; | ||
| if(args != null) { | ||
| for(let i = 0;i < args.length;i++) markAsRelevant(args[i],jsDoc,options); | ||
| } | ||
| for(let key in ref.members) { | ||
| markAsRelevant(ref.members[key].type,jsDoc,options); | ||
| } | ||
| if(ref.decl != null && ref.decl.type != null) markAsRelevant(ref.decl.type,jsDoc,options); | ||
| if(ref.inherits != null) { | ||
| for(let i = 0;i < ref.inherits.length;i++) { | ||
| let baseEntry = symtabGet(ref.inherits[i]); | ||
| markAsRelevant(baseEntry.typeDesc,baseEntry.jsDoc,baseEntry.options); | ||
| } | ||
| } | ||
| } | ||
| break; | ||
| case ts.SyntaxKind.UnionType: markUnionAsRelevant(typeDesc,jsDoc,options); break; | ||
| case ts.SyntaxKind.IntersectionType: markIntersectionAsRelevant(typeDesc,jsDoc,options); break; | ||
| default: break; | ||
| } | ||
| } | ||
| } | ||
| export function synthesizeParameterJSDoc(parm:TypedId) { | ||
| let jsDoc; | ||
| let jsDocSrc = []; | ||
| let type1 = ["format","pattern","type"]; | ||
| let type2 = ["minimum","maximum","minLength","maxLength","minItems","maxItems","precision"]; | ||
| if(parm.decorators != null ) { | ||
| for(let decoratorName in parm.decorators) { | ||
| if(type1.indexOf(decoratorName) > -1 && parm.decorators[decoratorName].length >= 1) { | ||
| if(jsDocSrc.length == 0) jsDocSrc.push('/**'); | ||
| jsDocSrc.push(` * @${decoratorName} {${parm.decorators[decoratorName][0]}}`); | ||
| } | ||
| else if(type2.indexOf(decoratorName) > -1 && parm.decorators[decoratorName].length >= 1) { | ||
| if(jsDocSrc.length == 0) jsDocSrc.push('/**'); | ||
| jsDocSrc.push(` * @${decoratorName} ${parm.decorators[decoratorName][0]}`); | ||
| } | ||
| } | ||
| if(jsDocSrc.length != 0) { | ||
| jsDocSrc.push(" */"); | ||
| jsDoc = doctrine.parse(jsDocSrc.join('\n'),{ unwrap:true }); | ||
| if(jsDoc != null) jsDoc = [jsDoc]; | ||
| } | ||
| } | ||
| return jsDoc; | ||
| } | ||
| export function findRelevant(method: DecoratedFunction,options?:any) { | ||
| markAsRelevant(method.returnType,null,options); | ||
| for(let i = 0;i < method.methodParameters.length;i++) { | ||
| let x = typeToJSON(method.methodParameters[i].type,null,options); | ||
| if(x != null) markAsRelevant(method.methodParameters[i].type,null,options); | ||
| } | ||
| } | ||
| /** | ||
| * This function constructs the JSON schema corresponding to the method parameter | ||
| * list. This is accomplished by contstructing the schema corresponding to a virtual | ||
| * aggregate type whose members are each a parameter to the method. To apply a JSON | ||
| * schema type checker is a matter of contructing an intermediate form corresponding | ||
| * to that virtual type -- this is done by the generated function argsToSchema found | ||
| * in __check.js. Each parameter type is marked to include in the reference schema | ||
| * definitions. | ||
| * | ||
| * @param {DecoratedFunction} method the definition of the method having the parameter | ||
| * list for which the schema is to be contstructed. | ||
| * @param {any} options affects the rules for schema creation. | ||
| * | ||
| */ | ||
| export function parameterListToJSON(method: DecoratedFunction,options?:any):Object { | ||
| let props = {}; | ||
| let parameterNames = []; | ||
| let required = []; | ||
| let passthrough = false; | ||
| if(method.methodParameters.length == 1) { | ||
| let jsDoc = synthesizeParameterJSDoc(method.methodParameters[0]); | ||
| let jsonValue:any = typeToJSON(method.methodParameters[0].type,jsDoc,options); | ||
| if(jsonValue) { | ||
| let augmentedOptions = { expandRefs:true }; | ||
| for(let key in options) { | ||
| if(key != "expandRefs") augmentedOptions = options[key]; | ||
| } | ||
| jsonValue = typeToJSON(method.methodParameters[0].type,jsDoc,augmentedOptions); | ||
| if(jsonValue.type == "object") { | ||
| for(let p in jsonValue.properties) { | ||
| props[p] = jsonValue.properties[p]; | ||
| parameterNames.push(p); | ||
| } | ||
| required = jsonValue.required; | ||
| passthrough = true; | ||
| } | ||
| else { | ||
| let parameterName = method.methodParameters[0].id; | ||
| props[parameterName] = jsonValue; | ||
| parameterNames.push(parameterName); | ||
| if(parameterName) required.push(parameterName); | ||
| } | ||
| } | ||
| } | ||
| else { | ||
| for(let i = 0;i < method.methodParameters.length;i++) { | ||
| let jsDoc = synthesizeParameterJSDoc(method.methodParameters[i]); | ||
| let jsonValue = typeToJSON(method.methodParameters[i].type,jsDoc,options); | ||
| if(jsonValue) props[method.methodParameters[i].id] = jsonValue; | ||
| } | ||
| for(let i = 0;i < method.methodParameters.length;i++) { | ||
| let parameterName = method.methodParameters[i].id; | ||
| parameterNames.push(parameterName); | ||
| if(method.methodParameters[i].required) required.push(parameterName); | ||
| } | ||
| } | ||
| let res:any = { | ||
| classRef: `${method.classRef}`, | ||
| method: `${method.name}`, | ||
| parameterNames: parameterNames, | ||
| passthrough:passthrough, | ||
| schema: { | ||
| title: `${method.name} plist`, | ||
| description: `Parameter list for ${method.name}`, | ||
| type: "object", | ||
| properties: props | ||
| } | ||
| }; | ||
| if(required != null && required.length > 0) res.required = required; | ||
| return res; | ||
| } | ||
| /** | ||
| * This function loops over the parameter list of a method and returns an array of | ||
| * parameter describing interface objects. | ||
| * | ||
| * @param {any} parms The AST subtree describing the parameter list. | ||
| */ | ||
| export function traverseParameterList(parms: any,decoratorMeta:any): TypedId[] { | ||
| let parameterList:TypedId[] = []; | ||
| for(let i = 0;i < parms.length;i++) { | ||
| let required = true; | ||
| if(parms[i].questionToken != null) required = false; | ||
| parameterList.push(<TypedId>{ id:parms[i].name.text, type:parms[i].type, decorators:decoratorMeta[parms[i].name.text], required:required }); | ||
| } | ||
| return parameterList; | ||
| } | ||
| /** | ||
| * This function is called after the first pass of the AST is completed. It augments | ||
| * the classes found in the global symbol table that was constructed in part in pass 1 | ||
| * and annotated by @controller with the methods that belong to that class. | ||
| * | ||
| * @param {DecoratedFunction[]} endpoints an array of all of the relevant annotated | ||
| * methods. | ||
| */ | ||
| export function connectMethods(endpoints:DecoratedFunction[]): void { | ||
| for(let i = 0;i < endpoints.length;i++) { | ||
| if(endpoints[i].index != null) { | ||
| let controller:any = symtabGet(endpoints[i].index); | ||
| if(controller != null) { | ||
| if(controller.methods != null) controller.methods.push(endpoints[i]); | ||
| else console.log(`Ignoring endpoint ${endpoints[i].name} of ${endpoints[i].classRef}`); | ||
| } | ||
| } | ||
| } | ||
| } | ||
| function isMagic(typeDesc:any) { | ||
| if(typeDesc == null) return false; | ||
| let typeName = typeDesc.name.text; | ||
| if(typeName == "Res" || typeName == "FileRef") return true; | ||
| let isUnion = typeDesc.kind == ts.SyntaxKind.UnionType; | ||
| if(!isUnion && typeDesc.kind == ts.SyntaxKind.TypeAliasDeclaration) { | ||
| while(typeDesc.kind == ts.SyntaxKind.TypeAliasDeclaration) { | ||
| let componentDesc = symtabGet(typeName); | ||
| if(componentDesc == null) break; | ||
| let alias = componentDesc.decl; | ||
| if(alias.type != null) { | ||
| typeDesc = alias.type; | ||
| isUnion = alias.type.kind == ts.SyntaxKind.UnionType; | ||
| } | ||
| else break; | ||
| if(isUnion) break; | ||
| let typename = getIndex(typeDesc); | ||
| if(isExplicitStatus(typename)) return true; | ||
| } | ||
| } | ||
| if(!isUnion) return false; | ||
| let unionDesc = <ts.UnionTypeNode>typeDesc; | ||
| let isMultiStatus = false; | ||
| for(let i = 0;i < unionDesc.types.length;i++) { | ||
| let unionElementTypename = getIndex(unionDesc.types[i]); | ||
| if(unionElementTypename != null && isExplicitStatus(unionElementTypename)) return true; | ||
| } | ||
| return false; | ||
| } | ||
| export function isExplicitStatus(index) { | ||
| if(index == null) return false; | ||
| if(typeof index == "string") return index == "Res"; | ||
| else if(index.local == "Res" && index.module.match(/.*ts-api.*/)) return true; | ||
| return false; | ||
| } | ||
| export function isFileReturn(index) { | ||
| if(index == null) return false; | ||
| if(typeof index == "string") return index == "FileRef"; | ||
| else if(index.local == "FileRef" && index.module.match(/.*ts-api.*/)) return true; | ||
| return false; | ||
| } | ||
| /** | ||
| * This function creates the JSON schema reference document that corresponds to | ||
| * all marked (relevant) types defined in the global symbol table created from the | ||
| * traversal of the AST of the typescript sources. | ||
| * | ||
| */ | ||
| export function symtabToSchemaDefinitions(schemaNamespace:string,docRoot:string,expandOptions?:any): Object { | ||
| let res = {}; | ||
| for(let skey in symtab) { | ||
| let sentry = symtab[skey]; | ||
| if(sentry.kind == "type" && sentry.relevant) { | ||
| let required = []; | ||
| let decl = sentry.decl; | ||
| if(!isMagic(decl)) { | ||
| let schemaRefId = sentry.schemaRefId; | ||
| let allOf; | ||
| if(decl.kind == ts.SyntaxKind.InterfaceDeclaration || decl.kind == ts.SyntaxKind.ClassDeclaration) { | ||
| res[schemaRefId] = { type:"object", properties:{} }; | ||
| for(let mkey in sentry.members) { | ||
| res[schemaRefId].properties[mkey] = sentry.members[mkey].desc[schemaNamespace]; | ||
| if(!sentry.members[mkey].optional) required.push(mkey); | ||
| } | ||
| if(sentry.inherits != null && sentry.inherits.length > 0) { | ||
| allOf = []; | ||
| for(let i = 0;i < sentry.inherits.length;i++) { | ||
| let hindex = sentry.inherits[i]; | ||
| let hentry = symtabGet(hindex); | ||
| allOf.push(mapTypeDescName(docRoot,hentry.schemaRefId)); | ||
| } | ||
| } | ||
| } | ||
| else if(decl.type != null) { | ||
| let options = { schemaNamespace:schemaNamespace, docRoot:docRoot }; | ||
| for(let option in expandOptions) options[option] = expandOptions[option]; | ||
| res[schemaRefId] = typeToJSON(decl.type,sentry.jsDoc,{ enclosedBy:skey, options:options }); | ||
| } | ||
| if(required.length > 0) res[schemaRefId].required = required; | ||
| if(sentry.comment != null) res[schemaRefId].description = sentry.comment; | ||
| if(sentry.schema == null) sentry.schema = {}; | ||
| if(allOf != null) { | ||
| allOf.push(res[schemaRefId]); | ||
| res[schemaRefId] = { allOf:allOf }; | ||
| } | ||
| sentry.schema[schemaNamespace] = res[schemaRefId]; | ||
| } | ||
| } | ||
| } | ||
| // Now traverse again, and this time look for the itypes, all the processing has been | ||
| // done in the previous traversal, so just output the generated def. | ||
| if(expandOptions != null && expandOptions.firstclassIntermediates) { | ||
| for(let skey in symtab) { | ||
| let sentry = symtab[skey]; | ||
| if(sentry.kind == "itype") { | ||
| let esentry = symtabGet(sentry.enclosedBy); | ||
| if(esentry != null && esentry.relevant) { | ||
| let schemaRefId = sentry.schemaRefId; | ||
| res[schemaRefId] = sentry.schema; | ||
| } | ||
| } | ||
| } | ||
| } | ||
| return res; | ||
| } | ||
| /** | ||
| * Detects a url param variable in a path, returns metadata of the path. | ||
| * | ||
| * @param path {string} the path of a URL associated decorator (router,controller,method). | ||
| */ | ||
| export function decomposePath(path:string): PathDecomposition { | ||
| let delimited = path.split('/'); | ||
| let urlParams = {} | ||
| let pathComponents = []; | ||
| for(let i = 0;i < delimited.length;i++) { | ||
| if(delimited[i] != '') { | ||
| if(delimited[i].match(/:.*/)) { | ||
| let base = delimited[i].replace(/:/g,"") | ||
| pathComponents.push(base); | ||
| urlParams[base] = true; | ||
| } | ||
| else pathComponents.push(delimited[i]); | ||
| } | ||
| } | ||
| return { pathComponents:pathComponents, urlParams:urlParams }; | ||
| } | ||
| /** | ||
| * Compiles the list of controller definitions by iterating over | ||
| * the global pass 1 typescript source symbol table and creating a record | ||
| * for each entry marked with type "controller". | ||
| */ | ||
| export function symtabToControllerDefinitions(): Controller[] { | ||
| let res:Controller[] = []; | ||
| for(let skey in symtab) { | ||
| let sentry = symtab[skey]; | ||
| if(sentry.kind == "controller") { | ||
| let classRef = sentry.schemaRefId; | ||
| let path = classRef; | ||
| let comment = sentry.comment; | ||
| let fileName = sentry.fileName; | ||
| if(sentry.args != null && sentry.args[0] != null) path = sentry.args[0]; | ||
| res.push({ | ||
| args:sentry.args, | ||
| classRef:classRef, | ||
| comment:comment, | ||
| fileName:fileName, | ||
| methods:sentry.methods, | ||
| decomposition:decomposePath(path) | ||
| }); | ||
| } | ||
| } | ||
| return res; | ||
| } | ||
| /** | ||
| * Like above, compiles the list of router definitions by iterating over | ||
| * the global pass 1 typescript source symbol table and creating a record | ||
| * for each entry marked with type "router". | ||
| */ | ||
| export function symtabToRouterDefinitions(): Router[] { | ||
| let res:Router[] = []; | ||
| for(let skey in symtab) { | ||
| let sentry = symtab[skey]; | ||
| if(sentry.kind == "router") { | ||
| let className = sentry.schemaRefId; | ||
| let path = className; | ||
| let comment = sentry.comment; | ||
| let fileName = sentry.fileName; | ||
| if(sentry.args != null && sentry.args[0] != null) path = sentry.args[0]; | ||
| let pathComponents = path.split('/'); | ||
| let urlParams:string[] = []; | ||
| for(let i = 0;i < pathComponents.length;i++) { | ||
| if(pathComponents[i].match(/:.*/)) urlParams.push(pathComponents[i].replace(/:/g,"")); | ||
| } | ||
| res.push({ | ||
| args:sentry.args, | ||
| className:className, | ||
| comment:comment, | ||
| fileName:fileName, | ||
| decomposition:decomposePath(path) | ||
| }); | ||
| } | ||
| } | ||
| return res; | ||
| } | ||
| export function isURLParam(id:string,router:Router,controller:Controller,methodPathDecomposition:PathDecomposition):boolean { | ||
| return router.decomposition.urlParams[id] || controller.decomposition.urlParams[id] || methodPathDecomposition.urlParams[id]; | ||
| } | ||
| /** | ||
| * Generates the the function "argsToSchema" in __check.js. This function | ||
| * is generated 1 time for each relevant method, and so it not a single exported | ||
| * function but rather a named member of a checking class contained by an | ||
| * enclosing object indexed by the classname of the class of which it is a member. | ||
| * The purpose of this generated function when run is to create the input to the JSON | ||
| * schema checker that corresponds to the parameters of that method. It is used | ||
| * by the verb decorator (see verb.ts). | ||
| * | ||
| * let check = binding.check[(<any>target.constructor).name + "." + key]; | ||
| * let valid = check.validate(check.argsToSchema(arguments)); | ||
| * | ||
| * @param {any} parameterNames the list of paremter names. | ||
| */ | ||
| function genArgsToSchema(parameterNames: any,passthrough:boolean): string { | ||
| let s = ''; | ||
| s += `function(a) {\n`; | ||
| if(passthrough) s += ` let o = a[0];\n`; | ||
| else { | ||
| s += ` let o = {};\n\n`; | ||
| for(let i = 0;i < parameterNames.length;i++) { | ||
| s += ` o['${parameterNames[i]}'] = a[${i}];\n`; | ||
| } | ||
| } | ||
| s += ` return o;\n }`; | ||
| return s; | ||
| } | ||
| /** | ||
| * Generates the the function "schemaToArgs" in __check.js. This function | ||
| * (as above) is generated 1 time for each relevant method, and likewise is | ||
| * meant to reverse the effect of the above method. This is to allow ajv | ||
| * transformation side effects in validate to propogate forwared so it's not | ||
| * simply a metter of just using the original argument list. | ||
| * | ||
| * @param {any} parameterNames the list of paremter names. | ||
| */ | ||
| function genSchemaToArgs(parameterNames: any,passthrough:boolean): string { | ||
| let s = ''; | ||
| s += `function(o) {\n`; | ||
| if(passthrough) s += ` let a = [o];\n\n`; | ||
| else { | ||
| s += ` let a = [];\n\n`; | ||
| for(let i = 0;i < parameterNames.length;i++) { | ||
| s += ` a[${i}] = o['${parameterNames[i]}'];\n`; | ||
| } | ||
| } | ||
| s += ` return a;\n }`; | ||
| return s; | ||
| } | ||
| /** | ||
| * Generates a member of the check object for a method. Each entry contains a reference | ||
| * JSON schema labeled 'schema', the function argsToSchema which creates the arguments | ||
| * to the checker, and validate which is the validator. Each entry in indexed by the | ||
| * unique combination of className.methodName. | ||
| * | ||
| * @param className Name of the (controller) class. | ||
| * @param methodName Name of the method. | ||
| * @param parameterNames list of each formal parameter to the method. | ||
| * @param schema the JSON schema of all of the relevant type definitions. | ||
| */ | ||
| export function genMethodEntry(classRef,methodName,parameterNames,schema,passthrough:boolean): string { | ||
| let s = `\nexports["${classRef}.${methodName}"] = {\n`; | ||
| if(schema.type == "object") { | ||
| let numParameters = 0; | ||
| let child; | ||
| let childName; | ||
| for(let p in schema.properties) { | ||
| child = schema.properties[p]; | ||
| childName = p; | ||
| numParameters++; | ||
| } | ||
| } | ||
| let schemaFormatted = JSON.stringify(schema,null,2); | ||
| schemaFormatted = schemaFormatted.replace(/\n/g,"\n "); | ||
| s += ` schema:compositeWithDefinitions(${schemaFormatted}),\n`; | ||
| s += ` argsToSchema:${genArgsToSchema(parameterNames,passthrough)},\n`; | ||
| s += ` schemaToArgs:${genSchemaToArgs(parameterNames,passthrough)},\n`; | ||
| s += ` validate:validate(${schemaFormatted})\n`; | ||
| s += `};\n`; | ||
| return s; | ||
| } | ||
| /** | ||
| * Adds an entry for a controller to the global typescript source symbol table. | ||
| * | ||
| * @param {string} className the name of the class annotated by @controller. | ||
| * @param {string} fileName the name of the file containing the controller definition. | ||
| * @param {string} comment a JSDoc type comment of the controller. | ||
| */ | ||
| export function addController(index:any,fileName: string,comment: string): void { | ||
| symtabPut(index,{ kind:"controller", fileName:fileName, comment:comment, methods:[], args:[] }); | ||
| } | ||
| /** | ||
| * Adds an entry for a router to the global typescript source symbol table. | ||
| * | ||
| * @param {string} className the name of the class annotated by @router. | ||
| * @param {string} fileName the name of the file containing the router definition. | ||
| * @param {string} comment a JSDoc type comment of the router. | ||
| */ | ||
| export function addRouter(index:any,fileName: string,comment: string): void { | ||
| symtabPut(index,{ kind:"router", fileName:fileName, comment:comment, args:[] }); | ||
| } | ||
| /** | ||
| * Output a path of appropriate type-style by concetenating the components some of which | ||
| * might also be urlParam type components. | ||
| * | ||
| * @param decomposition {PathDecomposition} The decomposed form of a path -- broken down into components. | ||
| & @param pathType: Either swagger or express | ||
| */ | ||
| export function decompositionToPath(decomposition:PathDecomposition,pathType:"swagger"|"express"):string { | ||
| let path = ""; | ||
| for(let i = 0;i < decomposition.pathComponents.length;i++) { | ||
| let component = decomposition.pathComponents[i]; | ||
| if(path != "") path = path + '/'; | ||
| if(decomposition.urlParams[component]) { | ||
| if(pathType == "swagger") path = path + '{' + component + '}'; | ||
| else path = path + ':' + component; | ||
| } | ||
| else path = path + component; | ||
| } | ||
| return path; | ||
| } |
| import * as ts from "typescript"; | ||
| const tsany = ts as any; | ||
| /** | ||
| * Interface for recording the elements of a method parameter list | ||
| */ | ||
| export interface TypedId { | ||
| id: string, | ||
| type: Object, | ||
| required: boolean, | ||
| decorators: any[] | ||
| }; | ||
| /** | ||
| * Simple object for holding the processing of a path; principally for | ||
| * the result of url param detection and component assignement. | ||
| */ | ||
| export interface PathDecomposition { | ||
| pathComponents:string[], | ||
| urlParams:Object | ||
| } | ||
| /** | ||
| * Interface for collection of relevant information about class methods | ||
| * annotated with REST verb decorators (e.g. @get, @post, etc). | ||
| * | ||
| */ | ||
| export interface DecoratedFunction { | ||
| name: string, | ||
| index: string | Object, | ||
| classRef: string, | ||
| comment: string, | ||
| decoratorArgs: any[], | ||
| methodParameters: TypedId[], | ||
| returnType: ts.TypeNode, | ||
| type: string | ||
| }; | ||
| /** | ||
| * Interface for collection of relevant information about classes annotated | ||
| * by the @controller decorator. | ||
| * | ||
| */ | ||
| export interface Controller { | ||
| args: any[], | ||
| classRef: string, | ||
| fileName: string, | ||
| comment: string, | ||
| methods: DecoratedFunction[], | ||
| decomposition: PathDecomposition | ||
| } | ||
| /** | ||
| * Interface for collection of relevant information about classes annotated | ||
| * by the @router decorator. | ||
| * | ||
| */ | ||
| export interface Router { | ||
| args: any[], | ||
| className: string, | ||
| fileName: string, | ||
| comment: string, | ||
| decomposition: PathDecomposition | ||
| } |
| import ControllerProperties from './ControllerProperties'; | ||
| /** | ||
| * ControllerBase | ||
| * | ||
| * A baseclass to coordinate ts-api REST endpoint callback and typechecks | ||
| * by simply declaring a string valued id. The class also declares a placeholder | ||
| * for coordination via context. Controller classes should derive from this | ||
| * class. Derived classes will automatically be constructed from these values. | ||
| */ | ||
| export default class ControllerBase { | ||
| protected properties: ControllerProperties; | ||
| public path: string; | ||
| constructor(properties:ControllerProperties) { | ||
| this.properties = properties; | ||
| } | ||
| getEndpointSignatureBinding() { return this.properties.binding; } | ||
| getProperties() { return this.properties; } | ||
| } |
| import EndpointCheckBinding from './EndpointCheckBinding'; | ||
| export default class ControllerInitializer { | ||
| public binding: EndpointCheckBinding; | ||
| public context: any; | ||
| public req: any; | ||
| public res: any; | ||
| public next: Function; | ||
| constructor(binding: EndpointCheckBinding,context:any,req:any,res:any,next:Function) { | ||
| this.binding = binding; | ||
| this.context = context; | ||
| this.req = req; | ||
| this.res = res; | ||
| this.next = next; | ||
| } | ||
| } |
| import verb from "./verb"; | ||
| export default function all(path?:string,errorHandler?:Function) { | ||
| return function(target:any,key:string,descriptor:TypedPropertyDescriptor<any>) { | ||
| if(descriptor === undefined) descriptor = Object.getOwnPropertyDescriptor(target,key); | ||
| descriptor.value = verb(target,key,descriptor.value,errorHandler); | ||
| return descriptor; | ||
| } | ||
| } |
| import 'reflect-metadata'; | ||
| /** | ||
| * Wrap the original controller definition with a function | ||
| * that will first save relevant infomation about the path | ||
| * in a member property before invoking the original | ||
| * constructor | ||
| */ | ||
| export default function controller(path: string) { | ||
| return function(target: any) { | ||
| var original = target; | ||
| var f:any = function(...args) { | ||
| let newPath = path; | ||
| if(newPath.charAt(0) != '/') newPath = '/' + newPath; | ||
| if(newPath.charAt(newPath.length - 1) == '/') newPath = newPath.substring(0,newPath.length - 1); | ||
| const result = new original(...args); | ||
| result.path = newPath; | ||
| return result; | ||
| } | ||
| // copy prototype so intanceof operator still works | ||
| f.prototype = original.prototype; | ||
| // return new constructor (will override original) | ||
| return f; | ||
| }; | ||
| } |
| import verb from "./verb"; | ||
| export default function del(path?:string,errorHandler?:Function) { | ||
| return function(target:any,key:string,descriptor:TypedPropertyDescriptor<any>) { | ||
| if(descriptor === undefined) descriptor = Object.getOwnPropertyDescriptor(target,key); | ||
| descriptor.value = verb(target,key,descriptor.value,errorHandler); | ||
| return descriptor; | ||
| } | ||
| } |
| import verb from "./verb"; | ||
| export default function get(path?:string,errorHandler?:Function) { | ||
| return function(target:any,key:string,descriptor:TypedPropertyDescriptor<any>) { | ||
| if(descriptor === undefined) descriptor = Object.getOwnPropertyDescriptor(target,key); | ||
| descriptor.value = verb(target,key,descriptor.value,errorHandler); | ||
| return descriptor; | ||
| } | ||
| } |
| import all from "./all"; | ||
| import controller from "./controller"; | ||
| import del from "./del"; | ||
| import get from "./get"; | ||
| import post from "./post"; | ||
| import put from "./put"; | ||
| import router from "./router"; | ||
| import urlParam from "./urlParam"; | ||
| import { minimum,maximum,minItems,maxItems,minLength,maxLength,precision,format,pattern,type } from "./parm"; | ||
| export { | ||
| all, | ||
| controller, | ||
| del, | ||
| format, | ||
| get, | ||
| maxItems, | ||
| maxLength, | ||
| maximum, | ||
| minItems, | ||
| minLength, | ||
| minimum, | ||
| pattern, | ||
| post, | ||
| precision, | ||
| put, | ||
| router, | ||
| type, | ||
| urlParam | ||
| }; |
| import 'reflect-metadata'; | ||
| export function minimum(n:number) { | ||
| return function(target:any,propertyKey:string,parameterIndex: number) {} | ||
| } | ||
| export function maximum(n:number) { | ||
| return function(target:any,propertyKey:string,parameterIndex: number) {} | ||
| } | ||
| export function minLength(n:number) { | ||
| return function(target:any,propertyKey:string,parameterIndex: number) {} | ||
| } | ||
| export function maxLength(n:number) { | ||
| return function(target:any,propertyKey:string,parameterIndex: number) {} | ||
| } | ||
| export function minItems(n:number) { | ||
| return function(target:any,propertyKey:string,parameterIndex: number) {} | ||
| } | ||
| export function maxItems(n:number) { | ||
| return function(target:any,propertyKey:string,parameterIndex: number) {} | ||
| } | ||
| export function precision(n:number) { | ||
| return function(target:any,propertyKey:string,parameterIndex: number) {} | ||
| } | ||
| export function format(s:string) { | ||
| return function(target:any,propertyKey:string,parameterIndex: number) {} | ||
| } | ||
| export function pattern(s:string) { | ||
| return function(target:any,propertyKey:string,parameterIndex: number) {} | ||
| } | ||
| export function type(s:string) { | ||
| return function(target:any,propertyKey:string,parameterIndex: number) {} | ||
| } | ||
| import verb from "./verb"; | ||
| export default function post(path?:string,errorHandler?:Function) { | ||
| return function(target:any,key:string,descriptor:TypedPropertyDescriptor<any>) { | ||
| if(descriptor === undefined) descriptor = Object.getOwnPropertyDescriptor(target,key); | ||
| descriptor.value = verb(target,key,descriptor.value,errorHandler); | ||
| return descriptor; | ||
| } | ||
| } |
| import verb from "./verb"; | ||
| export default function put(path?:string,errorHandler?:Function) { | ||
| return function(target:any,key:string,descriptor:TypedPropertyDescriptor<any>) { | ||
| if(descriptor === undefined) descriptor = Object.getOwnPropertyDescriptor(target,key); | ||
| descriptor.value = verb(target,key,descriptor.value,errorHandler); | ||
| return descriptor; | ||
| } | ||
| } |
| import 'reflect-metadata'; | ||
| /** | ||
| * Wrap the original router definition with a function | ||
| * that will first save relevant infomation about the path | ||
| * prefix in a member property before invoking the original | ||
| * constructor | ||
| */ | ||
| export default function router(prefix: string) { | ||
| return function(target: any) { | ||
| var original = target; | ||
| var f:any = function(...args) { | ||
| let newPrefix = prefix || ''; | ||
| if(newPrefix.charAt(0) != '/') newPrefix = '/' + newPrefix; | ||
| if(newPrefix.charAt(newPrefix.length - 1) == '/') newPrefix = newPrefix.substring(0,newPrefix.length - 1); | ||
| const result = new original(...args); | ||
| result.prefix = newPrefix; | ||
| return result; | ||
| } | ||
| // copy prototype so intanceof operator still works | ||
| f.prototype = original.prototype; | ||
| // return new constructor (will override original) | ||
| return f; | ||
| }; | ||
| } |
| import "reflect-metadata"; | ||
| export default function urlParam(component:string) { | ||
| return function(target:any,propertyKey:string|symbol,parameterIndex:number):void { | ||
| const parms = Reflect.getOwnMetadata("urlParam",target,propertyKey) || []; | ||
| parms.push(parameterIndex); | ||
| Reflect.defineMetadata("urlParam",parms,target,propertyKey); | ||
| } | ||
| } |
| const Promise = require('bluebird'); | ||
| /** | ||
| * A decorator for REST endpoints. Use the typescript decorator system to | ||
| * automatically apply typechecking. Assume that the controller for which this | ||
| * decorator applies to it's methods follows the form defined by ControllerBase | ||
| * and itself hase been annotated by @controller. If that is true, then a reference | ||
| * to that controller class will be provided to an argument to this function. Use | ||
| * the controller reference to gain access to the function that defines the check as | ||
| * well as the JSON schema to use as an argument. Return a function that will first | ||
| * perform that check, and if the check passes then execute the method on which this | ||
| * decorator has been applied. Otherwise throw an error. Assume that the exception | ||
| * will be caught appropriately -- it will because this function will be invoked in the | ||
| * context of analogously renerated file __routes.js. Provide for the possibility | ||
| * of a user defined function for error processing which can itself either return | ||
| * a status code or throw an error. | ||
| * | ||
| * @param {any} target reference to containing class of the decorated method | ||
| * @param {string} key the method name | ||
| * @param {any} originalMethod reference to the decorated method | ||
| * @param {Function} errorHandler A user defined error handler. | ||
| */ | ||
| export default function verb(target:any,key:string,originalMethod:any,errorHandler:Function) { | ||
| return function() { | ||
| let binding = this.getEndpointSignatureBinding(); | ||
| let controller = this; | ||
| let args = []; | ||
| if(binding != null) { | ||
| let check = binding.check[(<any>target.constructor).name + "." + key]; | ||
| let argObject = check.argsToSchema(arguments); | ||
| let valid = check.validate(argObject); | ||
| if(!valid) { | ||
| let err = check.validate.errors[0]; | ||
| throw({ status:400, message:"parameterList" + err.dataPath + " " + err.message }); | ||
| } | ||
| // generate args from schema because ajv might have transformed the original | ||
| args = check.schemaToArgs(argObject); | ||
| } | ||
| else { | ||
| for(var i = 0;i < arguments.length;i++) args[i - 0] = arguments[i]; | ||
| } | ||
| try { | ||
| // note usage of originalMethod here | ||
| let obj = originalMethod.apply(controller,args); | ||
| // If the original method is async, then resolve the promise before returning | ||
| if(obj != null) { | ||
| if(obj.constructor.name == 'Promise') { | ||
| let promise = new Promise(function(resolve,reject) { | ||
| obj.then( | ||
| function(value) { resolve(value) }, | ||
| function(reason) { | ||
| if(errorHandler != null) { | ||
| try { | ||
| let properties = controller.getProperties(); | ||
| let errorHandlerResult = errorHandler(reason,properties.req,properties.res,properties.next); | ||
| if(errorHandlerResult != null && typeof errorHandlerResult == "object") { | ||
| if(errorHandlerResult.status == null) errorHandlerResult.status = 500; | ||
| reject(errorHandlerResult); | ||
| } | ||
| else reject({ status:500, message:errorHandlerResult }); | ||
| } | ||
| catch(e) { reject(e); } | ||
| } | ||
| else { | ||
| if(typeof reason == 'object') reason.status = 500; | ||
| reject(reason); | ||
| } | ||
| } | ||
| ); | ||
| }); | ||
| return promise; | ||
| } | ||
| } | ||
| return new Promise(function(resolve,reject) { resolve(obj); }); | ||
| } | ||
| catch(e) { | ||
| if(errorHandler != null) { | ||
| let properties = controller.getProperties(); | ||
| let errorHandlerResult = errorHandler(e,properties.req,properties.res,properties.next); | ||
| if(errorHandlerResult != null && typeof errorHandlerResult == "object") { | ||
| if(errorHandlerResult.status == null) errorHandlerResult.status = 500; | ||
| throw(errorHandlerResult); | ||
| } | ||
| else throw({ status:500, message:errorHandlerResult }); | ||
| } | ||
| throw(e); | ||
| } | ||
| } | ||
| } |
| const uuid = require('uuid/v1'); | ||
| export default class EndpointCheckBinding { | ||
| id: string; | ||
| check: any; | ||
| constructor(check: any) { | ||
| this.check = check; | ||
| this.id = uuid(); | ||
| } | ||
| } |
+35
| import * as swaggerUi from 'swagger-ui-express'; | ||
| import * as serveStatic from 'serve-static'; | ||
| export { default as ControllerBase } from "./ControllerBase"; | ||
| export { default as ControllerProperties } from "./ControllerProperties"; | ||
| export { default as RouterBase } from "./RouterBase"; | ||
| export { default as EndpointCheckBinding } from "./EndpointCheckBinding"; | ||
| export { default as response } from "./response"; | ||
| export { swaggerUi }; | ||
| export { serveStatic }; | ||
| export { | ||
| all, | ||
| controller, | ||
| del, | ||
| format, | ||
| get, | ||
| maxItems, | ||
| maxLength, | ||
| maximum, | ||
| minItems, | ||
| minLength, | ||
| minimum, | ||
| pattern, | ||
| post, | ||
| precision, | ||
| put, | ||
| router, | ||
| type, | ||
| urlParam | ||
| } from "./decorators"; | ||
| export { FileRef, StatusCodes, Res } from "./magic"; | ||
| import {from_str} from "typescript-util-core"; | ||
| from_str().then(e=> {}).catch(e=> {}).finally(()=> {}); |
| export type FileRef<m extends string> = { | ||
| filename?:string, | ||
| displayName?:string, | ||
| mimeType?:m | ||
| }; |
| export { StatusCodes, Res } from "./Res"; | ||
| export { FileRef } from "./FileRef"; |
| export type StatusCodes = | ||
| 200|201|202|203|204|205|206|207|208|226| | ||
| 300|301|302|303|304|305|306|307|308| | ||
| 400|401|402|403|404|405|406|407|408|409|410| | ||
| 411|412|413|414|415|416|417|418|421|422|423| | ||
| 424|426|428|429|431|451| | ||
| 500|501|502|503|504|505|506|507|508|510|511; | ||
| export type Res<c extends StatusCodes,T> = { | ||
| body: T; | ||
| statusCode: c; | ||
| } |
+26
| export function src(redocSrc) { return ` | ||
| <!DOCTYPE html> | ||
| <html> | ||
| <head> | ||
| <title>ReDoc</title> | ||
| <!-- needed for adaptive design --> | ||
| <meta charset="utf-8"/> | ||
| <meta name="viewport" content="width=device-width, initial-scale=1"> | ||
| <link href="https://fonts.googleapis.com/css?family=Montserrat:300,400,700|Roboto:300,400,700" rel="stylesheet"> | ||
| <!-- | ||
| ReDoc doesn't change outer page styles | ||
| --> | ||
| <style> | ||
| body { | ||
| margin: 0; | ||
| padding: 0; | ||
| } | ||
| </style> | ||
| </head> | ||
| <body> | ||
| <redoc spec-url='${redocSrc}'></redoc> | ||
| <script src="https://cdn.jsdelivr.net/npm/redoc@next/bundles/redoc.standalone.js"> </script> | ||
| </body> | ||
| </html>`; | ||
| } |
| const uuidv1 = require('uuid/v1'); | ||
| const path = require('path'); | ||
| /** | ||
| * General REST processing in case of an error | ||
| */ | ||
| function error(e:any,req:any,res:any,next:any) { | ||
| if(res._header == null) { | ||
| if(e.stack) { | ||
| let ref = uuidv1(); | ||
| let status = 500; | ||
| if(e.status) status = e.status; | ||
| console.log(`response error ${ref}:`,e.stack); | ||
| res.status(status).send(`<pre>\nerror: ref ${ref}, check logs for further information\n</pre>`); | ||
| } | ||
| else { | ||
| if(e.status != null) res.status(e.status).send({ error:e }); | ||
| else next(e); | ||
| } | ||
| } | ||
| } | ||
| /** | ||
| * REST processing in case of endpoint success | ||
| */ | ||
| function success(obj:any,req:any,res:any,next:any) { | ||
| if(res._header == null) { | ||
| if(obj == null) console.error("API return null result"); | ||
| else { | ||
| if(obj.statusCode != null) res.status(obj.statusCode); | ||
| if(obj.filename != null) { | ||
| let resolvedPath = path.resolve(obj.filename); | ||
| if(obj.displayName != null) | ||
| res.download(resolvedPath,obj.displayName,function(err) { if(err != null) next(err); }); | ||
| else | ||
| res.download(resolvedPath,function(err) { if(err != null) next(err); }); | ||
| } | ||
| else { | ||
| if(obj.body != null) res.send(obj.body); | ||
| else res.send(obj); | ||
| } | ||
| } | ||
| } | ||
| } | ||
| export default { error,success }; |
| const express = require("express"); | ||
| export default class RouterBase { | ||
| root:any; | ||
| routers:any; | ||
| public prefix: string; | ||
| public context: any; | ||
| constructor(context:any) { | ||
| this.context = context; | ||
| this.routers = {}; | ||
| this.root = express.Router(); | ||
| } | ||
| getExpressRouter(name?:string) { | ||
| if(name == null) return this.root; | ||
| return this.routers[name]; | ||
| } | ||
| addRouter(path:string,name:string,options):void { | ||
| this.routers[name] = express.Router(options); | ||
| this.root.use(path,this.routers[name]); | ||
| }; | ||
| } |
| const expect = require('chai').expect; | ||
| const index = require('../dist/index.js'); | ||
| describe('hello world', () => { | ||
| it('should return true', () => { | ||
| expect(true).to.equal(true); | ||
| }); | ||
| }); |
| { | ||
| "compilerOptions": { | ||
| "outDir": "./dist", | ||
| "rootDir": "./src", | ||
| // Module settings | ||
| "module": "CommonJS", // <-- Use CommonJS to support require() | ||
| "moduleResolution": "node", // Node-style module resolution | ||
| "target": "esnext", | ||
| "lib": [ | ||
| "esnext", | ||
| "dom" | ||
| ], | ||
| // Output | ||
| "sourceMap": true, | ||
| "declaration": true, | ||
| "declarationMap": true, | ||
| // Type checking | ||
| "strict": false, // <-- disable strict mode | ||
| "noUncheckedIndexedAccess": false, | ||
| "exactOptionalPropertyTypes": false, | ||
| // Other recommended options | ||
| "jsx": "react-jsx", | ||
| "isolatedModules": true, | ||
| "skipLibCheck": true | ||
| }, | ||
| "include": ["src"], | ||
| "exclude": ["dist", "node_modules", "test", "ui"] | ||
| } |
+11
-9
@@ -1,9 +0,11 @@ | ||
| export { isClientErrorStatus, isRedirectStatus, isServerErrorStatus, isSuccessStatus, } from "./status.js"; | ||
| export { HttpError } from "./errors.js"; | ||
| export { fetchJson, type FetchJsonOptions, } from "./fetch-json.js"; | ||
| import "typescript-util-core"; | ||
| export { mergeHeaders, withJsonBody, } from "./headers.js"; | ||
| export { parseJson, safeParseJson, type JsonPrimitive, type JsonValue, } from "./json.js"; | ||
| export { toSearchParams, withQuery, type QueryPrimitive, type QueryValue, } from "./query-string.js"; | ||
| export { err, ok, type ApiResult, } from "./types.js"; | ||
| //# sourceMappingURL=index.d.ts.map | ||
| import * as swaggerUi from 'swagger-ui-express'; | ||
| import * as serveStatic from 'serve-static'; | ||
| export { default as ControllerBase } from "./ControllerBase"; | ||
| export { default as ControllerProperties } from "./ControllerProperties"; | ||
| export { default as RouterBase } from "./RouterBase"; | ||
| export { default as EndpointCheckBinding } from "./EndpointCheckBinding"; | ||
| export { default as response } from "./response"; | ||
| export { swaggerUi }; | ||
| export { serveStatic }; | ||
| export { all, controller, del, format, get, maxItems, maxLength, maximum, minItems, minLength, minimum, pattern, post, precision, put, router, type, urlParam } from "./decorators"; | ||
| export { FileRef, StatusCodes, Res } from "./magic"; |
+35
-8
@@ -1,9 +0,36 @@ | ||
| export { isClientErrorStatus, isRedirectStatus, isServerErrorStatus, isSuccessStatus, } from "./status.js"; | ||
| export { HttpError } from "./errors.js"; | ||
| export { fetchJson, } from "./fetch-json.js"; | ||
| import "typescript-util-core"; | ||
| export { mergeHeaders, withJsonBody, } from "./headers.js"; | ||
| export { parseJson, safeParseJson, } from "./json.js"; | ||
| export { toSearchParams, withQuery, } from "./query-string.js"; | ||
| export { err, ok, } from "./types.js"; | ||
| "use strict"; | ||
| Object.defineProperty(exports, "__esModule", { value: true }); | ||
| var swaggerUi = require("swagger-ui-express"); | ||
| exports.swaggerUi = swaggerUi; | ||
| var serveStatic = require("serve-static"); | ||
| exports.serveStatic = serveStatic; | ||
| var ControllerBase_1 = require("./ControllerBase"); | ||
| exports.ControllerBase = ControllerBase_1.default; | ||
| var ControllerProperties_1 = require("./ControllerProperties"); | ||
| exports.ControllerProperties = ControllerProperties_1.default; | ||
| var RouterBase_1 = require("./RouterBase"); | ||
| exports.RouterBase = RouterBase_1.default; | ||
| var EndpointCheckBinding_1 = require("./EndpointCheckBinding"); | ||
| exports.EndpointCheckBinding = EndpointCheckBinding_1.default; | ||
| var response_1 = require("./response"); | ||
| exports.response = response_1.default; | ||
| var decorators_1 = require("./decorators"); | ||
| exports.all = decorators_1.all; | ||
| exports.controller = decorators_1.controller; | ||
| exports.del = decorators_1.del; | ||
| exports.format = decorators_1.format; | ||
| exports.get = decorators_1.get; | ||
| exports.maxItems = decorators_1.maxItems; | ||
| exports.maxLength = decorators_1.maxLength; | ||
| exports.maximum = decorators_1.maximum; | ||
| exports.minItems = decorators_1.minItems; | ||
| exports.minLength = decorators_1.minLength; | ||
| exports.minimum = decorators_1.minimum; | ||
| exports.pattern = decorators_1.pattern; | ||
| exports.post = decorators_1.post; | ||
| exports.precision = decorators_1.precision; | ||
| exports.put = decorators_1.put; | ||
| exports.router = decorators_1.router; | ||
| exports.type = decorators_1.type; | ||
| exports.urlParam = decorators_1.urlParam; | ||
| //# sourceMappingURL=index.js.map |
@@ -1,1 +0,1 @@ | ||
| {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,mBAAmB,EACnB,gBAAgB,EAChB,mBAAmB,EACnB,eAAe,GAChB,MAAM,aAAa,CAAC;AACrB,OAAO,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC;AACxC,OAAO,EACL,SAAS,GAEV,MAAM,iBAAiB,CAAC;AACzB,OAAO,sBAAsB,CAAC;AAC9B,OAAO,EACL,YAAY,EACZ,YAAY,GACb,MAAM,cAAc,CAAC;AACtB,OAAO,EACL,SAAS,EACT,aAAa,GAGd,MAAM,WAAW,CAAC;AACnB,OAAO,EACL,cAAc,EACd,SAAS,GAGV,MAAM,mBAAmB,CAAC;AAC3B,OAAO,EACL,GAAG,EACH,EAAE,GAEH,MAAM,YAAY,CAAC"} | ||
| {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";;AAAA,8CAAgD;AAOvC,8BAAS;AANlB,0CAA4C;AAOnC,kCAAW;AANpB,mDAA6D;AAApD,0CAAA,OAAO,CAAkB;AAClC,+DAAyE;AAAhE,sDAAA,OAAO,CAAwB;AACxC,2CAAqD;AAA5C,kCAAA,OAAO,CAAc;AAC9B,+DAAyE;AAAhE,sDAAA,OAAO,CAAwB;AACxC,uCAAiD;AAAxC,8BAAA,OAAO,CAAY;AAG5B,2CAmBsB;AAlBpB,2BAAA,GAAG,CAAA;AACH,kCAAA,UAAU,CAAA;AACV,2BAAA,GAAG,CAAA;AACH,8BAAA,MAAM,CAAA;AACN,2BAAA,GAAG,CAAA;AACH,gCAAA,QAAQ,CAAA;AACR,iCAAA,SAAS,CAAA;AACT,+BAAA,OAAO,CAAA;AACP,gCAAA,QAAQ,CAAA;AACR,iCAAA,SAAS,CAAA;AACT,+BAAA,OAAO,CAAA;AACP,+BAAA,OAAO,CAAA;AACP,4BAAA,IAAI,CAAA;AACJ,iCAAA,SAAS,CAAA;AACT,2BAAA,GAAG,CAAA;AACH,8BAAA,MAAM,CAAA;AACN,4BAAA,IAAI,CAAA;AACJ,gCAAA,QAAQ,CAAA"} |
+32
-47
| { | ||
| "name": "api-ts-utils", | ||
| "version": "3.2.2", | ||
| "description": "TypeScript utilities for HTTP APIs on Node.js (fetch, JSON, query strings, status helpers)", | ||
| "license": "MIT", | ||
| "type": "module", | ||
| "main": "./dist/index.js", | ||
| "types": "./dist/index.d.ts", | ||
| "exports": { | ||
| ".": { | ||
| "types": "./dist/index.d.ts", | ||
| "import": "./dist/index.js", | ||
| "default": "./dist/index.js" | ||
| } | ||
| "version": "3.4.7", | ||
| "description": "Create documented REST API using controllers and interfaces in typescript", | ||
| "main": "dist", | ||
| "types": "dist", | ||
| "repository": { | ||
| "type": "git", | ||
| "url": "git+ssh://git@github.com/waTeim/ts-api.git" | ||
| }, | ||
| "sideEffects": false, | ||
| "files": [ | ||
| "dist" | ||
| ], | ||
| "engines": { | ||
| "node": ">=18" | ||
| "dependencies": { | ||
| "@types/node": "^13.5.0", | ||
| "@types/swagger-ui-express": "^3.0.0", | ||
| "ajv": "^6.8.1", | ||
| "bluebird": "^3.5.1", | ||
| "commander": "^2.15.1", | ||
| "doctrine": "^2.1.0", | ||
| "express": "^4.16.3", | ||
| "find-root": "^1.1.0", | ||
| "glob": "^7.1.2", | ||
| "mkdirp": "^0.5.1", | ||
| "reflect-metadata": "^0.1.12", | ||
| "swagger-ui-express": "^4.0.1", | ||
| "typescript-util-core": "7.1.3", | ||
| "typescript": "3.7.5", | ||
| "uuid": "^3.3.2" | ||
| }, | ||
| "scripts": { | ||
| "build": "tsc -p tsconfig.build.json", | ||
| "clean": "rm -rf dist", | ||
| "prepublishOnly": "npm run build" | ||
| "test": "mocha --reporter spec", | ||
| "build": "tsc" | ||
| }, | ||
| "dependencies": { | ||
| "axios": "^1.9.0", | ||
| "dotenv": "^16.5.0", | ||
| "http-status-codes": "^2.3.0", | ||
| "jose": "^6.0.11", | ||
| "ms": "^2.1.3", | ||
| "p-retry": "^6.2.1", | ||
| "pino": "^9.6.0", | ||
| "qs": "^6.14.0", | ||
| "typescript-util-core": "^3.5.0", | ||
| "uuid": "^11.1.0", | ||
| "zod": "^3.24.4" | ||
| "bin": { | ||
| "cg": "bin/cg" | ||
| }, | ||
| "author": "Jeff Waller", | ||
| "license": "Apache 2.0", | ||
| "devDependencies": { | ||
| "@types/node": "^22.15.3", | ||
| "@types/qs": "^6.14.0", | ||
| "typescript": "^5.8.3" | ||
| }, | ||
| "keywords": [ | ||
| "api", | ||
| "typescript", | ||
| "fetch", | ||
| "http", | ||
| "utils", | ||
| "nodejs", | ||
| "json", | ||
| "url" | ||
| ] | ||
| "chai": "^4.2.0", | ||
| "mocha": "^5.2.0" | ||
| } | ||
| } |
| export declare class HttpError extends Error { | ||
| readonly status: number; | ||
| readonly statusText: string; | ||
| readonly url: string; | ||
| readonly bodyText?: string | undefined; | ||
| readonly name = "HttpError"; | ||
| constructor(status: number, statusText: string, url: string, bodyText?: string | undefined, options?: ErrorOptions); | ||
| } | ||
| //# sourceMappingURL=errors.d.ts.map |
| {"version":3,"file":"errors.d.ts","sourceRoot":"","sources":["../src/errors.ts"],"names":[],"mappings":"AAAA,qBAAa,SAAU,SAAQ,KAAK;IAGhC,QAAQ,CAAC,MAAM,EAAE,MAAM;IACvB,QAAQ,CAAC,UAAU,EAAE,MAAM;IAC3B,QAAQ,CAAC,GAAG,EAAE,MAAM;IACpB,QAAQ,CAAC,QAAQ,CAAC,EAAE,MAAM;IAL5B,QAAQ,CAAC,IAAI,eAAe;gBAEjB,MAAM,EAAE,MAAM,EACd,UAAU,EAAE,MAAM,EAClB,GAAG,EAAE,MAAM,EACX,QAAQ,CAAC,EAAE,MAAM,YAAA,EAC1B,OAAO,CAAC,EAAE,YAAY;CAOzB"} |
| export class HttpError extends Error { | ||
| status; | ||
| statusText; | ||
| url; | ||
| bodyText; | ||
| name = "HttpError"; | ||
| constructor(status, statusText, url, bodyText, options) { | ||
| super(`HTTP ${status} ${statusText} for ${url}${bodyText ? `: ${truncate(bodyText, 200)}` : ""}`, options); | ||
| this.status = status; | ||
| this.statusText = statusText; | ||
| this.url = url; | ||
| this.bodyText = bodyText; | ||
| } | ||
| } | ||
| function truncate(s, max) { | ||
| return s.length <= max ? s : `${s.slice(0, max)}…`; | ||
| } | ||
| //# sourceMappingURL=errors.js.map |
| {"version":3,"file":"errors.js","sourceRoot":"","sources":["../src/errors.ts"],"names":[],"mappings":"AAAA,MAAM,OAAO,SAAU,SAAQ,KAAK;IAGvB;IACA;IACA;IACA;IALF,IAAI,GAAG,WAAW,CAAC;IAC5B,YACW,MAAc,EACd,UAAkB,EAClB,GAAW,EACX,QAAiB,EAC1B,OAAsB;QAEtB,KAAK,CACH,QAAQ,MAAM,IAAI,UAAU,QAAQ,GAAG,GAAG,QAAQ,CAAC,CAAC,CAAC,KAAK,QAAQ,CAAC,QAAQ,EAAE,GAAG,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,EAAE,EAC1F,OAAO,CACR,CAAC;QATO,WAAM,GAAN,MAAM,CAAQ;QACd,eAAU,GAAV,UAAU,CAAQ;QAClB,QAAG,GAAH,GAAG,CAAQ;QACX,aAAQ,GAAR,QAAQ,CAAS;IAO5B,CAAC;CACF;AAED,SAAS,QAAQ,CAAC,CAAS,EAAE,GAAW;IACtC,OAAO,CAAC,CAAC,MAAM,IAAI,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,KAAK,CAAC,CAAC,EAAE,GAAG,CAAC,GAAG,CAAC;AACrD,CAAC"} |
| export type FetchJsonOptions = RequestInit & { | ||
| /** Optional parser; default reads `response.json()` as unknown. */ | ||
| parse?: (response: Response) => Promise<unknown>; | ||
| }; | ||
| /** | ||
| * `fetch` then ensure `response.ok`, optionally parse JSON (default), and return typed data via `guard`. | ||
| * Throws `HttpError` on non-OK responses (body text is captured when available). | ||
| */ | ||
| export declare function fetchJson<T>(input: string | URL | Request, guard: (value: unknown) => value is T, init?: FetchJsonOptions): Promise<T>; | ||
| //# sourceMappingURL=fetch-json.d.ts.map |
| {"version":3,"file":"fetch-json.d.ts","sourceRoot":"","sources":["../src/fetch-json.ts"],"names":[],"mappings":"AAEA,MAAM,MAAM,gBAAgB,GAAG,WAAW,GAAG;IAC3C,mEAAmE;IACnE,KAAK,CAAC,EAAE,CAAC,QAAQ,EAAE,QAAQ,KAAK,OAAO,CAAC,OAAO,CAAC,CAAC;CAClD,CAAC;AAEF;;;GAGG;AACH,wBAAsB,SAAS,CAAC,CAAC,EAC/B,KAAK,EAAE,MAAM,GAAG,GAAG,GAAG,OAAO,EAC7B,KAAK,EAAE,CAAC,KAAK,EAAE,OAAO,KAAK,KAAK,IAAI,CAAC,EACrC,IAAI,CAAC,EAAE,gBAAgB,GACtB,OAAO,CAAC,CAAC,CAAC,CAyBZ"} |
| import { HttpError } from "./errors.js"; | ||
| /** | ||
| * `fetch` then ensure `response.ok`, optionally parse JSON (default), and return typed data via `guard`. | ||
| * Throws `HttpError` on non-OK responses (body text is captured when available). | ||
| */ | ||
| export async function fetchJson(input, guard, init) { | ||
| const { parse: customParse, ...requestInit } = init ?? {}; | ||
| const response = await fetch(input, requestInit); | ||
| if (!response.ok) { | ||
| let bodyText; | ||
| try { | ||
| bodyText = await response.text(); | ||
| } | ||
| catch { | ||
| bodyText = undefined; | ||
| } | ||
| const url = typeof input === "string" | ||
| ? input | ||
| : input instanceof URL | ||
| ? input.href | ||
| : input.url; | ||
| throw new HttpError(response.status, response.statusText, url, bodyText); | ||
| } | ||
| const raw = customParse | ||
| ? await customParse(response) | ||
| : await response.json(); | ||
| if (!guard(raw)) { | ||
| throw new TypeError("Response JSON failed validation guard"); | ||
| } | ||
| return raw; | ||
| } | ||
| //# sourceMappingURL=fetch-json.js.map |
| {"version":3,"file":"fetch-json.js","sourceRoot":"","sources":["../src/fetch-json.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC;AAOxC;;;GAGG;AACH,MAAM,CAAC,KAAK,UAAU,SAAS,CAC7B,KAA6B,EAC7B,KAAqC,EACrC,IAAuB;IAEvB,MAAM,EAAE,KAAK,EAAE,WAAW,EAAE,GAAG,WAAW,EAAE,GAAG,IAAI,IAAI,EAAE,CAAC;IAC1D,MAAM,QAAQ,GAAG,MAAM,KAAK,CAAC,KAAK,EAAE,WAAW,CAAC,CAAC;IACjD,IAAI,CAAC,QAAQ,CAAC,EAAE,EAAE,CAAC;QACjB,IAAI,QAA4B,CAAC;QACjC,IAAI,CAAC;YACH,QAAQ,GAAG,MAAM,QAAQ,CAAC,IAAI,EAAE,CAAC;QACnC,CAAC;QAAC,MAAM,CAAC;YACP,QAAQ,GAAG,SAAS,CAAC;QACvB,CAAC;QACD,MAAM,GAAG,GACP,OAAO,KAAK,KAAK,QAAQ;YACvB,CAAC,CAAC,KAAK;YACP,CAAC,CAAC,KAAK,YAAY,GAAG;gBACpB,CAAC,CAAC,KAAK,CAAC,IAAI;gBACZ,CAAC,CAAC,KAAK,CAAC,GAAG,CAAC;QAClB,MAAM,IAAI,SAAS,CAAC,QAAQ,CAAC,MAAM,EAAE,QAAQ,CAAC,UAAU,EAAE,GAAG,EAAE,QAAQ,CAAC,CAAC;IAC3E,CAAC;IACD,MAAM,GAAG,GAAY,WAAW;QAC9B,CAAC,CAAC,MAAM,WAAW,CAAC,QAAQ,CAAC;QAC7B,CAAC,CAAC,MAAM,QAAQ,CAAC,IAAI,EAAE,CAAC;IAC1B,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,EAAE,CAAC;QAChB,MAAM,IAAI,SAAS,CAAC,uCAAuC,CAAC,CAAC;IAC/D,CAAC;IACD,OAAO,GAAG,CAAC;AACb,CAAC"} |
| /** Normalize header pairs suitable for `Headers` init. */ | ||
| export declare function mergeHeaders(...parts: Array<HeadersInit | undefined | null>): Headers; | ||
| /** Return init with `Content-Type: application/json` merged into headers. */ | ||
| export declare function withJsonBody(body: unknown, init?: RequestInit): RequestInit; | ||
| //# sourceMappingURL=headers.d.ts.map |
| {"version":3,"file":"headers.d.ts","sourceRoot":"","sources":["../src/headers.ts"],"names":[],"mappings":"AAAA,0DAA0D;AAC1D,wBAAgB,YAAY,CAC1B,GAAG,KAAK,EAAE,KAAK,CAAC,WAAW,GAAG,SAAS,GAAG,IAAI,CAAC,GAC9C,OAAO,CAUT;AAED,6EAA6E;AAC7E,wBAAgB,YAAY,CAAC,IAAI,EAAE,OAAO,EAAE,IAAI,CAAC,EAAE,WAAW,GAAG,WAAW,CAS3E"} |
| /** Normalize header pairs suitable for `Headers` init. */ | ||
| export function mergeHeaders(...parts) { | ||
| const out = new Headers(); | ||
| for (const part of parts) { | ||
| if (part == null) | ||
| continue; | ||
| const h = new Headers(part); | ||
| h.forEach((value, key) => { | ||
| out.set(key, value); | ||
| }); | ||
| } | ||
| return out; | ||
| } | ||
| /** Return init with `Content-Type: application/json` merged into headers. */ | ||
| export function withJsonBody(body, init) { | ||
| const headers = mergeHeaders(init?.headers, { | ||
| "Content-Type": "application/json", | ||
| }); | ||
| return { | ||
| ...init, | ||
| headers, | ||
| body: JSON.stringify(body), | ||
| }; | ||
| } | ||
| //# sourceMappingURL=headers.js.map |
| {"version":3,"file":"headers.js","sourceRoot":"","sources":["../src/headers.ts"],"names":[],"mappings":"AAAA,0DAA0D;AAC1D,MAAM,UAAU,YAAY,CAC1B,GAAG,KAA4C;IAE/C,MAAM,GAAG,GAAG,IAAI,OAAO,EAAE,CAAC;IAC1B,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;QACzB,IAAI,IAAI,IAAI,IAAI;YAAE,SAAS;QAC3B,MAAM,CAAC,GAAG,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC;QAC5B,CAAC,CAAC,OAAO,CAAC,CAAC,KAAK,EAAE,GAAG,EAAE,EAAE;YACvB,GAAG,CAAC,GAAG,CAAC,GAAG,EAAE,KAAK,CAAC,CAAC;QACtB,CAAC,CAAC,CAAC;IACL,CAAC;IACD,OAAO,GAAG,CAAC;AACb,CAAC;AAED,6EAA6E;AAC7E,MAAM,UAAU,YAAY,CAAC,IAAa,EAAE,IAAkB;IAC5D,MAAM,OAAO,GAAG,YAAY,CAAC,IAAI,EAAE,OAAO,EAAE;QAC1C,cAAc,EAAE,kBAAkB;KACnC,CAAC,CAAC;IACH,OAAO;QACL,GAAG,IAAI;QACP,OAAO;QACP,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC;KAC3B,CAAC;AACJ,CAAC"} |
| {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,mBAAmB,EACnB,gBAAgB,EAChB,mBAAmB,EACnB,eAAe,GAChB,MAAM,aAAa,CAAC;AACrB,OAAO,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC;AACxC,OAAO,EACL,SAAS,EACT,KAAK,gBAAgB,GACtB,MAAM,iBAAiB,CAAC;AACzB,OAAO,sBAAsB,CAAC;AAC9B,OAAO,EACL,YAAY,EACZ,YAAY,GACb,MAAM,cAAc,CAAC;AACtB,OAAO,EACL,SAAS,EACT,aAAa,EACb,KAAK,aAAa,EAClB,KAAK,SAAS,GACf,MAAM,WAAW,CAAC;AACnB,OAAO,EACL,cAAc,EACd,SAAS,EACT,KAAK,cAAc,EACnB,KAAK,UAAU,GAChB,MAAM,mBAAmB,CAAC;AAC3B,OAAO,EACL,GAAG,EACH,EAAE,EACF,KAAK,SAAS,GACf,MAAM,YAAY,CAAC"} |
| export type JsonPrimitive = string | number | boolean | null; | ||
| export type JsonValue = JsonPrimitive | JsonValue[] | { | ||
| readonly [key: string]: JsonValue; | ||
| }; | ||
| export declare function parseJson(text: string): unknown; | ||
| /** | ||
| * Parse JSON and pass the result to `guard`. Returns `undefined` on parse failure | ||
| * or when `guard` returns false. | ||
| */ | ||
| export declare function safeParseJson<T>(text: string, guard: (value: unknown) => value is T): T | undefined; | ||
| //# sourceMappingURL=json.d.ts.map |
| {"version":3,"file":"json.d.ts","sourceRoot":"","sources":["../src/json.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,aAAa,GAAG,MAAM,GAAG,MAAM,GAAG,OAAO,GAAG,IAAI,CAAC;AAC7D,MAAM,MAAM,SAAS,GAAG,aAAa,GAAG,SAAS,EAAE,GAAG;IAAE,QAAQ,EAAE,GAAG,EAAE,MAAM,GAAG,SAAS,CAAA;CAAE,CAAC;AAE5F,wBAAgB,SAAS,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAE/C;AAED;;;GAGG;AACH,wBAAgB,aAAa,CAAC,CAAC,EAC7B,IAAI,EAAE,MAAM,EACZ,KAAK,EAAE,CAAC,KAAK,EAAE,OAAO,KAAK,KAAK,IAAI,CAAC,GACpC,CAAC,GAAG,SAAS,CAOf"} |
-17
| export function parseJson(text) { | ||
| return JSON.parse(text); | ||
| } | ||
| /** | ||
| * Parse JSON and pass the result to `guard`. Returns `undefined` on parse failure | ||
| * or when `guard` returns false. | ||
| */ | ||
| export function safeParseJson(text, guard) { | ||
| try { | ||
| const value = JSON.parse(text); | ||
| return guard(value) ? value : undefined; | ||
| } | ||
| catch { | ||
| return undefined; | ||
| } | ||
| } | ||
| //# sourceMappingURL=json.js.map |
| {"version":3,"file":"json.js","sourceRoot":"","sources":["../src/json.ts"],"names":[],"mappings":"AAGA,MAAM,UAAU,SAAS,CAAC,IAAY;IACpC,OAAO,IAAI,CAAC,KAAK,CAAC,IAAI,CAAY,CAAC;AACrC,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,aAAa,CAC3B,IAAY,EACZ,KAAqC;IAErC,IAAI,CAAC;QACH,MAAM,KAAK,GAAY,IAAI,CAAC,KAAK,CAAC,IAAI,CAAY,CAAC;QACnD,OAAO,KAAK,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,SAAS,CAAC;IAC1C,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,SAAS,CAAC;IACnB,CAAC;AACH,CAAC"} |
| export type QueryPrimitive = string | number | boolean | null | undefined; | ||
| export type QueryValue = QueryPrimitive | readonly QueryPrimitive[]; | ||
| /** | ||
| * Build `URLSearchParams` from a shallow record. Arrays become repeated keys. | ||
| * `undefined` and `null` entries are skipped. | ||
| */ | ||
| export declare function toSearchParams(query: Readonly<Record<string, QueryValue>>): URLSearchParams; | ||
| /** Append search params to a base URL string (handles existing `?`). */ | ||
| export declare function withQuery(baseUrl: string, query: Readonly<Record<string, QueryValue>>): string; | ||
| //# sourceMappingURL=query-string.d.ts.map |
| {"version":3,"file":"query-string.d.ts","sourceRoot":"","sources":["../src/query-string.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,cAAc,GAAG,MAAM,GAAG,MAAM,GAAG,OAAO,GAAG,IAAI,GAAG,SAAS,CAAC;AAC1E,MAAM,MAAM,UAAU,GAAG,cAAc,GAAG,SAAS,cAAc,EAAE,CAAC;AAEpE;;;GAGG;AACH,wBAAgB,cAAc,CAC5B,KAAK,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,UAAU,CAAC,CAAC,GAC1C,eAAe,CAcjB;AAED,wEAAwE;AACxE,wBAAgB,SAAS,CACvB,OAAO,EAAE,MAAM,EACf,KAAK,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,UAAU,CAAC,CAAC,GAC1C,MAAM,CAMR"} |
| /** | ||
| * Build `URLSearchParams` from a shallow record. Arrays become repeated keys. | ||
| * `undefined` and `null` entries are skipped. | ||
| */ | ||
| export function toSearchParams(query) { | ||
| const params = new URLSearchParams(); | ||
| for (const [key, raw] of Object.entries(query)) { | ||
| if (raw === undefined || raw === null) | ||
| continue; | ||
| if (Array.isArray(raw)) { | ||
| for (const item of raw) { | ||
| if (item === undefined || item === null) | ||
| continue; | ||
| params.append(key, String(item)); | ||
| } | ||
| } | ||
| else { | ||
| params.append(key, String(raw)); | ||
| } | ||
| } | ||
| return params; | ||
| } | ||
| /** Append search params to a base URL string (handles existing `?`). */ | ||
| export function withQuery(baseUrl, query) { | ||
| const params = toSearchParams(query); | ||
| if ([...params].length === 0) | ||
| return baseUrl; | ||
| const qs = params.toString(); | ||
| const joiner = baseUrl.includes("?") ? "&" : "?"; | ||
| return `${baseUrl}${joiner}${qs}`; | ||
| } | ||
| //# sourceMappingURL=query-string.js.map |
| {"version":3,"file":"query-string.js","sourceRoot":"","sources":["../src/query-string.ts"],"names":[],"mappings":"AAGA;;;GAGG;AACH,MAAM,UAAU,cAAc,CAC5B,KAA2C;IAE3C,MAAM,MAAM,GAAG,IAAI,eAAe,EAAE,CAAC;IACrC,KAAK,MAAM,CAAC,GAAG,EAAE,GAAG,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,KAAK,CAAC,EAAE,CAAC;QAC/C,IAAI,GAAG,KAAK,SAAS,IAAI,GAAG,KAAK,IAAI;YAAE,SAAS;QAChD,IAAI,KAAK,CAAC,OAAO,CAAC,GAAG,CAAC,EAAE,CAAC;YACvB,KAAK,MAAM,IAAI,IAAI,GAAG,EAAE,CAAC;gBACvB,IAAI,IAAI,KAAK,SAAS,IAAI,IAAI,KAAK,IAAI;oBAAE,SAAS;gBAClD,MAAM,CAAC,MAAM,CAAC,GAAG,EAAE,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC;YACnC,CAAC;QACH,CAAC;aAAM,CAAC;YACN,MAAM,CAAC,MAAM,CAAC,GAAG,EAAE,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC;QAClC,CAAC;IACH,CAAC;IACD,OAAO,MAAM,CAAC;AAChB,CAAC;AAED,wEAAwE;AACxE,MAAM,UAAU,SAAS,CACvB,OAAe,EACf,KAA2C;IAE3C,MAAM,MAAM,GAAG,cAAc,CAAC,KAAK,CAAC,CAAC;IACrC,IAAI,CAAC,GAAG,MAAM,CAAC,CAAC,MAAM,KAAK,CAAC;QAAE,OAAO,OAAO,CAAC;IAC7C,MAAM,EAAE,GAAG,MAAM,CAAC,QAAQ,EAAE,CAAC;IAC7B,MAAM,MAAM,GAAG,OAAO,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,GAAG,CAAC;IACjD,OAAO,GAAG,OAAO,GAAG,MAAM,GAAG,EAAE,EAAE,CAAC;AACpC,CAAC"} |
| /** True for 2xx responses (200–299). */ | ||
| export declare function isSuccessStatus(status: number): boolean; | ||
| /** True for redirect responses (300–399), excluding 304 which is often handled like success for caches. */ | ||
| export declare function isRedirectStatus(status: number): boolean; | ||
| /** True for client error responses (400–499). */ | ||
| export declare function isClientErrorStatus(status: number): boolean; | ||
| /** True for server error responses (500–599). */ | ||
| export declare function isServerErrorStatus(status: number): boolean; | ||
| //# sourceMappingURL=status.d.ts.map |
| {"version":3,"file":"status.d.ts","sourceRoot":"","sources":["../src/status.ts"],"names":[],"mappings":"AAAA,wCAAwC;AACxC,wBAAgB,eAAe,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAEvD;AAED,2GAA2G;AAC3G,wBAAgB,gBAAgB,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAExD;AAED,iDAAiD;AACjD,wBAAgB,mBAAmB,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAE3D;AAED,iDAAiD;AACjD,wBAAgB,mBAAmB,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAE3D"} |
| /** True for 2xx responses (200–299). */ | ||
| export function isSuccessStatus(status) { | ||
| return status >= 200 && status < 300; | ||
| } | ||
| /** True for redirect responses (300–399), excluding 304 which is often handled like success for caches. */ | ||
| export function isRedirectStatus(status) { | ||
| return status >= 300 && status < 400; | ||
| } | ||
| /** True for client error responses (400–499). */ | ||
| export function isClientErrorStatus(status) { | ||
| return status >= 400 && status < 500; | ||
| } | ||
| /** True for server error responses (500–599). */ | ||
| export function isServerErrorStatus(status) { | ||
| return status >= 500 && status < 600; | ||
| } | ||
| //# sourceMappingURL=status.js.map |
| {"version":3,"file":"status.js","sourceRoot":"","sources":["../src/status.ts"],"names":[],"mappings":"AAAA,wCAAwC;AACxC,MAAM,UAAU,eAAe,CAAC,MAAc;IAC5C,OAAO,MAAM,IAAI,GAAG,IAAI,MAAM,GAAG,GAAG,CAAC;AACvC,CAAC;AAED,2GAA2G;AAC3G,MAAM,UAAU,gBAAgB,CAAC,MAAc;IAC7C,OAAO,MAAM,IAAI,GAAG,IAAI,MAAM,GAAG,GAAG,CAAC;AACvC,CAAC;AAED,iDAAiD;AACjD,MAAM,UAAU,mBAAmB,CAAC,MAAc;IAChD,OAAO,MAAM,IAAI,GAAG,IAAI,MAAM,GAAG,GAAG,CAAC;AACvC,CAAC;AAED,iDAAiD;AACjD,MAAM,UAAU,mBAAmB,CAAC,MAAc;IAChD,OAAO,MAAM,IAAI,GAAG,IAAI,MAAM,GAAG,GAAG,CAAC;AACvC,CAAC"} |
| /** Discriminated result for API layers without throwing for expected failures. */ | ||
| export type ApiResult<T, E = unknown> = { | ||
| ok: true; | ||
| data: T; | ||
| } | { | ||
| ok: false; | ||
| error: E; | ||
| }; | ||
| export declare function ok<T>(data: T): ApiResult<T, never>; | ||
| export declare function err<E>(error: E): ApiResult<never, E>; | ||
| //# sourceMappingURL=types.d.ts.map |
| {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA,kFAAkF;AAClF,MAAM,MAAM,SAAS,CAAC,CAAC,EAAE,CAAC,GAAG,OAAO,IAChC;IAAE,EAAE,EAAE,IAAI,CAAC;IAAC,IAAI,EAAE,CAAC,CAAA;CAAE,GACrB;IAAE,EAAE,EAAE,KAAK,CAAC;IAAC,KAAK,EAAE,CAAC,CAAA;CAAE,CAAC;AAE5B,wBAAgB,EAAE,CAAC,CAAC,EAAE,IAAI,EAAE,CAAC,GAAG,SAAS,CAAC,CAAC,EAAE,KAAK,CAAC,CAElD;AAED,wBAAgB,GAAG,CAAC,CAAC,EAAE,KAAK,EAAE,CAAC,GAAG,SAAS,CAAC,KAAK,EAAE,CAAC,CAAC,CAEpD"} |
| export function ok(data) { | ||
| return { ok: true, data }; | ||
| } | ||
| export function err(error) { | ||
| return { ok: false, error }; | ||
| } | ||
| //# sourceMappingURL=types.js.map |
| {"version":3,"file":"types.js","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAKA,MAAM,UAAU,EAAE,CAAI,IAAO;IAC3B,OAAO,EAAE,EAAE,EAAE,IAAI,EAAE,IAAI,EAAE,CAAC;AAC5B,CAAC;AAED,MAAM,UAAU,GAAG,CAAI,KAAQ;IAC7B,OAAO,EAAE,EAAE,EAAE,KAAK,EAAE,KAAK,EAAE,CAAC;AAC9B,CAAC"} |
Major refactor
Supply chain riskPackage has recently undergone a major refactor. It may be unstable or indicate significant internal changes. Use caution when updating to versions that include significant changes.
Environment variable access
Supply chain riskPackage accesses environment variables, which may be a sign of credential stuffing or data theft.
URL strings
Supply chain riskPackage contains fragments of external URLs or IP addresses, which the package may be accessing at runtime.
Network access
Supply chain riskThis module accesses the network.
No README
QualityPackage does not have a README. This may indicate a failed publish or a low quality package.
No contributors or author data
MaintenancePackage does not specify a list of contributors or an author in package.json.
No repository
Supply chain riskPackage does not have a linked source code repository. Without this field, a package will have no reference to the location of the source code use to generate the package.
523623
2647.96%2
-33.33%133
303.03%7411
3346.98%1
-50%0
-100%129
Infinity%15
36.36%2
100%No
NaN+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
Updated
Updated