fastify-openapi-glue
Version:
generate a fastify configuration from an openapi specification
738 lines (711 loc) • 14.3 kB
JavaScript
// Fastify plugin autogenerated by fastify-openapi-glue
import fastifyPlugin from "fastify-plugin";
import { Security } from "./security.js";
import { SecurityError } from "./securityHandlers.js";
import { Service } from "./service.js";
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);
}
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: "/v2" });
},
{ fastify: "^4.x" },
);
async function generateRoutes(fastify, _opts) {
const service = new Service();
const security = new Security();
fastify.route({
method: "POST",
url: "/pet",
schema: {
body: {
type: "object",
required: ["name", "photoUrls"],
properties: {
id: {
type: "integer",
format: "int64",
},
category: {
type: "object",
properties: {
id: {
type: "integer",
format: "int64",
},
name: {
type: "string",
},
},
xml: {
name: "Category",
},
},
name: {
type: "string",
example: "doggie",
},
photoUrls: {
type: "array",
xml: {
name: "photoUrl",
wrapped: true,
},
items: {
type: "string",
},
},
tags: {
type: "array",
xml: {
name: "tag",
wrapped: true,
},
items: {
type: "object",
properties: {
id: {
type: "integer",
format: "int64",
},
name: {
type: "string",
},
},
xml: {
name: "Tag",
},
},
},
status: {
type: "string",
description: "pet status in the store",
enum: ["available", "pending", "sold"],
},
},
xml: {
name: "Pet",
},
},
},
handler: buildHandler(service, "addPet").bind(Service),
prehandler: buildPreHandler(security, [
{ petstore_auth: ["write:pets", "read:pets"] },
]).bind(Security),
});
fastify.route({
method: "PUT",
url: "/pet",
schema: {
body: {
type: "object",
required: ["name", "photoUrls"],
properties: {
id: {
type: "integer",
format: "int64",
},
category: {
type: "object",
properties: {
id: {
type: "integer",
format: "int64",
},
name: {
type: "string",
},
},
xml: {
name: "Category",
},
},
name: {
type: "string",
example: "doggie",
},
photoUrls: {
type: "array",
xml: {
name: "photoUrl",
wrapped: true,
},
items: {
type: "string",
},
},
tags: {
type: "array",
xml: {
name: "tag",
wrapped: true,
},
items: {
type: "object",
properties: {
id: {
type: "integer",
format: "int64",
},
name: {
type: "string",
},
},
xml: {
name: "Tag",
},
},
},
status: {
type: "string",
description: "pet status in the store",
enum: ["available", "pending", "sold"],
},
},
xml: {
name: "Pet",
},
},
},
handler: buildHandler(service, "updatePet").bind(Service),
prehandler: buildPreHandler(security, [
{ petstore_auth: ["write:pets", "read:pets"] },
]).bind(Security),
});
fastify.route({
method: "GET",
url: "/pet/findByStatus",
schema: {
querystring: {
type: "object",
properties: {
status: {
type: "array",
description: "Status values that need to be considered for filter",
items: {
type: "string",
enum: ["available", "pending", "sold"],
default: "available",
},
collectionFormat: "multi",
},
},
required: ["status"],
},
},
handler: buildHandler(service, "findPetsByStatus").bind(Service),
prehandler: buildPreHandler(security, [
{ petstore_auth: ["write:pets", "read:pets"] },
]).bind(Security),
});
fastify.route({
method: "GET",
url: "/pet/findByTags",
schema: {
querystring: {
type: "object",
properties: {
tags: {
type: "array",
description: "Tags to filter by",
items: {
type: "string",
},
collectionFormat: "multi",
},
},
required: ["tags"],
},
},
handler: buildHandler(service, "findPetsByTags").bind(Service),
prehandler: buildPreHandler(security, [
{ petstore_auth: ["write:pets", "read:pets"] },
]).bind(Security),
});
fastify.route({
method: "GET",
url: "/pet/:petId",
schema: {
params: {
type: "object",
properties: {
petId: {
type: "integer",
description: "ID of pet to return",
format: "int64",
},
},
required: ["petId"],
},
},
handler: buildHandler(service, "getPetById").bind(Service),
prehandler: buildPreHandler(security, [{ api_key: [] }]).bind(Security),
});
fastify.route({
method: "POST",
url: "/pet/:petId",
schema: {
body: {
type: "object",
properties: {
name: {
type: "string",
description: "Updated name of the pet",
},
status: {
type: "string",
description: "Updated status of the pet",
},
},
},
params: {
type: "object",
properties: {
petId: {
type: "integer",
description: "ID of pet that needs to be updated",
format: "int64",
},
},
required: ["petId"],
},
},
handler: buildHandler(service, "updatePetWithForm").bind(Service),
prehandler: buildPreHandler(security, [
{ petstore_auth: ["write:pets", "read:pets"] },
]).bind(Security),
});
fastify.route({
method: "DELETE",
url: "/pet/:petId",
schema: {
params: {
type: "object",
properties: {
petId: {
type: "integer",
description: "Pet id to delete",
format: "int64",
},
},
required: ["petId"],
},
},
handler: buildHandler(service, "deletePet").bind(Service),
prehandler: buildPreHandler(security, [
{ petstore_auth: ["write:pets", "read:pets"] },
]).bind(Security),
});
fastify.route({
method: "POST",
url: "/pet/:petId/uploadImage",
schema: {
body: {
type: "object",
properties: {
additionalMetadata: {
type: "string",
description: "Additional data to pass to server",
},
file: {
type: "string",
description: "file to upload",
},
},
},
params: {
type: "object",
properties: {
petId: {
type: "integer",
description: "ID of pet to update",
format: "int64",
},
},
required: ["petId"],
},
},
handler: buildHandler(service, "uploadFile").bind(Service),
prehandler: buildPreHandler(security, [
{ petstore_auth: ["write:pets", "read:pets"] },
]).bind(Security),
});
fastify.route({
method: "GET",
url: "/store/inventory",
schema: {},
handler: buildHandler(service, "getInventory").bind(Service),
prehandler: buildPreHandler(security, [{ api_key: [] }]).bind(Security),
});
fastify.route({
method: "POST",
url: "/store/order",
schema: {
body: {
type: "object",
properties: {
id: {
type: "integer",
format: "int64",
},
petId: {
type: "integer",
format: "int64",
},
quantity: {
type: "integer",
format: "int32",
},
shipDate: {
type: "string",
format: "date-time",
},
status: {
type: "string",
description: "Order Status",
enum: ["placed", "approved", "delivered"],
},
complete: {
type: "boolean",
default: false,
},
},
xml: {
name: "Order",
},
},
},
handler: buildHandler(service, "placeOrder").bind(Service),
});
fastify.route({
method: "GET",
url: "/store/order/:orderId",
schema: {
params: {
type: "object",
properties: {
orderId: {
type: "integer",
description: "ID of pet that needs to be fetched",
format: "int64",
maximum: 10,
minimum: 1,
},
},
required: ["orderId"],
},
},
handler: buildHandler(service, "getOrderById").bind(Service),
});
fastify.route({
method: "DELETE",
url: "/store/order/:orderId",
schema: {
params: {
type: "object",
properties: {
orderId: {
type: "integer",
description: "ID of the order that needs to be deleted",
format: "int64",
minimum: 1,
},
},
required: ["orderId"],
},
},
handler: buildHandler(service, "deleteOrder").bind(Service),
});
fastify.route({
method: "POST",
url: "/user",
schema: {
body: {
type: "object",
properties: {
id: {
type: "integer",
format: "int64",
},
username: {
type: "string",
},
firstName: {
type: "string",
},
lastName: {
type: "string",
},
email: {
type: "string",
},
password: {
type: "string",
},
phone: {
type: "string",
},
userStatus: {
type: "integer",
format: "int32",
description: "User Status",
},
},
xml: {
name: "User",
},
},
},
handler: buildHandler(service, "createUser").bind(Service),
});
fastify.route({
method: "POST",
url: "/user/createWithArray",
schema: {
body: {
type: "array",
items: {
type: "object",
properties: {
id: {
type: "integer",
format: "int64",
},
username: {
type: "string",
},
firstName: {
type: "string",
},
lastName: {
type: "string",
},
email: {
type: "string",
},
password: {
type: "string",
},
phone: {
type: "string",
},
userStatus: {
type: "integer",
format: "int32",
description: "User Status",
},
},
xml: {
name: "User",
},
},
},
},
handler: buildHandler(service, "createUsersWithArrayInput").bind(Service),
});
fastify.route({
method: "POST",
url: "/user/createWithList",
schema: {
body: {
type: "array",
items: {
type: "object",
properties: {
id: {
type: "integer",
format: "int64",
},
username: {
type: "string",
},
firstName: {
type: "string",
},
lastName: {
type: "string",
},
email: {
type: "string",
},
password: {
type: "string",
},
phone: {
type: "string",
},
userStatus: {
type: "integer",
format: "int32",
description: "User Status",
},
},
xml: {
name: "User",
},
},
},
},
handler: buildHandler(service, "createUsersWithListInput").bind(Service),
});
fastify.route({
method: "GET",
url: "/user/login",
schema: {
querystring: {
type: "object",
properties: {
username: {
type: "string",
description: "The user name for login",
},
password: {
type: "string",
description: "The password for login in clear text",
},
},
required: ["username", "password"],
},
},
handler: buildHandler(service, "loginUser").bind(Service),
});
fastify.route({
method: "GET",
url: "/user/logout",
schema: {},
handler: buildHandler(service, "logoutUser").bind(Service),
});
fastify.route({
method: "GET",
url: "/user/:username",
schema: {
params: {
type: "object",
properties: {
username: {
type: "string",
description:
"The name that needs to be fetched. Use user1 for testing. ",
},
},
required: ["username"],
},
},
handler: buildHandler(service, "getUserByName").bind(Service),
});
fastify.route({
method: "PUT",
url: "/user/:username",
schema: {
body: {
type: "object",
properties: {
id: {
type: "integer",
format: "int64",
},
username: {
type: "string",
},
firstName: {
type: "string",
},
lastName: {
type: "string",
},
email: {
type: "string",
},
password: {
type: "string",
},
phone: {
type: "string",
},
userStatus: {
type: "integer",
format: "int32",
description: "User Status",
},
},
xml: {
name: "User",
},
},
params: {
type: "object",
properties: {
username: {
type: "string",
description: "name that need to be updated",
},
},
required: ["username"],
},
},
handler: buildHandler(service, "updateUser").bind(Service),
});
fastify.route({
method: "DELETE",
url: "/user/:username",
schema: {
params: {
type: "object",
properties: {
username: {
type: "string",
description: "The name that needs to be deleted",
},
},
required: ["username"],
},
},
handler: buildHandler(service, "deleteUser").bind(Service),
});
}
export const options = {
ajv: {
customOptions: {
strict: false,
},
},
};