fastify-openapi-glue
Version:
generate a fastify configuration from an openapi specification
114 lines (105 loc) • 2.8 kB
JavaScript
export default (
data,
) => `// Fastify plugin autogenerated by fastify-openapi-glue
import fastifyPlugin from "fastify-plugin";
import { Security } from "./${data.securityFile}";
import { SecurityError } from "./${data.securityHandlers}";
import { Service } from "./${data.serviceFile}";
function notImplemented(operationId) {
return async () => {
throw new Error(\`Operation \${operationId} not implemented\`);
};
}
function buildHandler(serviceHandlers, operationId) {
if (operationId in serviceHandlers) {
return serviceHandlers[operationId];
}
return notImplemented(operationId);
}
${
hasSecuritySchemes(data.config.routes)
? `
function buildPreHandler(securityHandlers, schemes) {
if (schemes.length === 0) {
return async () => { };
}
return async (req, reply) => {
const handlerErrors = [];
const schemeList = [];
let statusCode = 401;
for (const scheme of schemes) {
try {
await securityHandlers[scheme.name](req, reply, scheme.parameters);
return; // If one security check passes, no need to try any others
} catch (err) {
req.log.debug(\`Security handler '\${scheme.name}' failed: '\${err}'\`);
handlerErrors.push(err);
if (err.statusCode !== undefined) {
statusCode = err.statusCode;
}
}
schemeList.push(scheme.name);
}
// if we get this far no security handlers validated this request
throw new SecurityError(
\`None of the security schemes (\${schemeList.join(", ")}) successfully authenticated this request.\`,
statusCode,
"Unauthorized",
handlerErrors,
);
};
}`
: ""
}
export default fastifyPlugin(
async (instance, _opts) => {
instance.register(generateRoutes, { prefix: "${data.config.prefix || ""}" })
}, { fastify: '^4.x' })
async function generateRoutes(fastify, _opts) {
const service = new Service();
const security = new Security();
${data.config.routes
.map(
(item) =>
` fastify.route({
method: "${item.method}",
url: "${item.url}",
schema: ${optimizeSchema(item.schema)},
${
item.config
? `config: ${item.config},
`
: ""
}handler: buildHandler(service, "${item.operationId}").bind(Service)${
item.security
? `,
prehandler: buildPreHandler(security, ${JSON.stringify(item.security)}).bind(Security)
`
: ""
}
});
`,
)
.join("\n")}
}
export const options = {
ajv: {
customOptions: {
strict: false,
},
},
};
`;
function hasSecuritySchemes(routes) {
return routes.filter((route) => route.security !== undefined).length > 0;
}
function optimizeSchema(schema) {
const schemaKeys = ["body", "query", "querystring", "params", "reponse"];
const newSchema = {};
for (const key of schemaKeys) {
if (schema[key] !== undefined) {
newSchema[key] = schema[key];
}
}
return JSON.stringify(newSchema, null, "\t");
}