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");
}