UNPKG

@openapi-generator-plus/typescript-express-example-server-generator

Version:

An OpenAPI Generator Plus template for a TypeScript API server using Express to output example responses

91 lines (86 loc) 3.25 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.expressPath = expressPath; exports.index = index; const template_utils_1 = require("@openapi-generator-plus/template-utils"); /** * Convert an operation path (using OpenAPI's `{param}` placeholders) to an * Express route path (using `:param` placeholders). */ function expressPath(path) { if (!path) { return path; } return path.replace(/\{([-a-zA-Z_]+)\}/g, ':$1'); } /* A single example response, pushed onto the `defaultResponses` array that the * handler picks a random entry from. Rendered at column 0 — the caller aligns * it to the handler body's indentation. */ function pushExample(content, example) { return `defaultResponses.push({ contentType: "${content.mediaType.mediaType}", body: ${example.valueString}, })`; } /* The handler body for an operation whose default response has examples: pick * one of the examples at random and send it. */ function exampleResponseBody(defaultResponse) { const pushes = (0, template_utils_1.each)(defaultResponse.contents, content => (0, template_utils_1.each)(content.examples, example => pushExample(content, example), '\n'), '\n'); return (0, template_utils_1.ts) ` const defaultResponses: { contentType: string, body: string }[] = [] ${pushes} const response = defaultResponses[Math.floor(Math.random() * defaultResponses.length)]; res.set('Content-Type', response.contentType) res.send(response.body)`; } /* The handler body for an operation with no example response to return. */ function unimplementedResponseBody() { return (0, template_utils_1.ts) ` //TODO res.status(503).send('Unimplemented')`; } function operationHandler(op) { const body = op.defaultResponse && (0, template_utils_1.hasExamples)(op.defaultResponse) ? exampleResponseBody(op.defaultResponse) : unimplementedResponseBody(); return (0, template_utils_1.ts) ` app.${(0, template_utils_1.lowerCase)(op.httpMethod)}('${expressPath(op.fullPath)}', function(req, res) { ${body} })`; } function operationGroup(group) { return (0, template_utils_1.ts) ` /* ${group.name} */ ${(0, template_utils_1.each)(group.operations, operationHandler, '\n')} `; } /* * Each group's rendering ends with its own trailing blank line (matching how * the hbs `{{#each groups}}` body emitted one after every group, including * the last), so `const options` below is glued directly onto the `${each}` * interpolation rather than sitting on its own source line — putting it on * its own line would add a second, spurious blank line before it. */ function index(ctx) { return (0, template_utils_1.ts) ` import express from 'express' import getopts from 'getopts' const app = express() ${(0, template_utils_1.each)(ctx.groups, operationGroup)}const options = getopts(process.argv.slice(2), { alias: { port: 'p', }, unknown: (option) => { console.log(\`Unknown option: \${option}\`) return false }, }) const port = options.port || 3000 const server = app.listen(port, function() { const address = server.address() if (typeof address === 'string') { console.log(\`Listening on \${address}\`) } else if (address) { console.log(\`Listening on \${address.port}\`) } }) `; }