After finishing all tests (in tap) I would like to run a script that generates openapi.yml.
In the .taprc config, I added the after property:
after: utils/generateOpenApi.ts
and my script (utils/generateOpenApi.ts) looks like this:
const helper = require('fastify-cli/helper.js')
import fs from 'fs'
import path from 'path'
const generateOpenApi = async() => {
const argv = [path.join(__dirname, '..', 'src', 'app.ts')]
const app = await helper.build(argv, {})
console.log('app.swagger', app.swagger)
const yaml = app.swagger({ yaml: true });
fs.writeFileSync("swagger.yaml", yaml);
}
generateOpenApi()
My main file (app.ts):
import { FastifyPluginAsync } from "fastify";
import { buildJsonSchemas, register } from "fastify-zod";
import { join } from "path";
import AutoLoad, { AutoloadPluginOptions } from "@fastify/autoload";
import { type FastifyZod } from "fastify-zod";
import { models } from "./routes/users/users.schemas";
export type AppOptions = {
// Place your custom options for app below here.
} & Partial<AutoloadPluginOptions>;
// Pass --options via CLI arguments in command to enable these options.
const options: AppOptions = {};
declare module "fastify" {
interface FastifyInstance {
readonly zod: FastifyZod<typeof models>;
}
}
const app: FastifyPluginAsync<AppOptions> = async (
fastify,
opts
): Promise<void> => {
await register(fastify, {
jsonSchemas: buildJsonSchemas(models, { errorMessages: true }),
swaggerOptions: {
swagger: {
info: {
title: "Fastify API",
description:
"Building a blazing fast REST API with Node.js, MongoDB, Fastify and Swagger",
version: "0.1.0",
},
host: "localhost",
schemes: ["http"],
consumes: ["application/json"],
},
},
swaggerUiOptions: {
routePrefix: "/docs",
uiConfig: {
docExpansion: "full",
deepLinking: false,
},
uiHooks: {
onRequest: function (request, reply, next) {
next();
},
preHandler: function (request, reply, next) {
next();
},
},
staticCSP: true,
transformStaticCSP: (header) => header,
transformSpecification: (swaggerObject, request, reply) => {
return swaggerObject;
},
transformSpecificationClone: true,
},
});
void fastify.register(AutoLoad, {
dir: join(__dirname, "plugins"),
options: opts,
});
void fastify.register(AutoLoad, {
dir: join(__dirname, "routes"),
options: opts,
ignorePattern: /.*(schemas)\.ts/
});
};
export default app;
export { app, option
You need to wrap the app.ts
with the fastify-plugin
.
The structure of your application is like this (on the left):
The helper.build(argv, {})
function returns the fastify-cli root
instance that does not have the swagger-ui plugin attached.
So, if you break the encapsulation by using the fastify-plugin
, the app.ts
lives in the same parent's context and you can access the swagger-ui plugin from the reference returned by helper.build(argv, {})
.
Further reading: