import * as z from "zod";import { buildJsonSchemas } from "fastify-zod";// Define the propertiesconst productInput = { // users input properties title: z.string(), price: z.number(), content: z.string().optional(), // optional};const productGenerated = { // automatically generated when the product is created id: z.number(), createdAt: z.string(), updatedAt: z.string(),};// Define the schemasconst createProductSchema = z.object({ ...productInput,});const productResponseSchema = z.object({ ...productInput, ...productGenerated,});const productsResponseSchema = z.array(productResponseSchema);// Export the typeexport type CreateProductInput = z.infer<typeof createProductSchema>;// Export the schemasexport const { schemas: productSchemas, $ref } = buildJsonSchemas({ createProductSchema, productResponseSchema, productsResponseSchema,});
Let’s take a look at what is happening above:
First, we separate the properties into two, such as productInput which will be input by users, and productGenerated which will be generated automatically when the user creates a product.
Define those properties according to our prisma schema
Export the type of CreateProductInput.
Then create schemas for createProductSchema, productResponseSchema and export them with buildJsonSchemas.
Register the schema with fastify
src/app.ts
import { productSchemas } from "./modules/product/product.schema";// other codesasync function main() { for (const schema of [...userSchemas, ...productSchemas]) { // It should be before you register your routes fastify.addSchema(schema); } // other codes}
I think some of you might get some error message in your terminal.⚠️ Don’t bother to make such changes in the_product.schema.ts_file where you export the schemas.
product.schema.ts
// other codesexport const { schemas: productSchemas, $ref } = buildJsonSchemas( { createProductSchema, singleProductResponseSchema, productsResponseSchema, }, { $id: "productSchemas", // Ensure the root $id is unique },);
Great! 👏 It’s time to check the createProduct route is working successfully or not. Let’s play around with the Postman. 🚀
// other codesasync function main() { // ... fastify.register(require("@fastify/swagger"), {}); fastify.register(require("@fastify/swagger-ui"), { routePrefix: "/docs", swagger: { info: { title: "Fastify Prisma REST API", description: "A REST API built with Fastify, Prisma and TypeScript", version: "1.0.0", contact: { name: "Vinojan Abhimanyu", url: "https://vinojan.online", email: "imvinojanv@gmail.com", }, }, externalDocs: { url: "https://github.com/imvinojanv/fastify-prisma-rest-api", description: "Fastify Tutorial source code is on GitHub", }, host: "0.0.0.0:3000", basePath: "/", schemes: ["http", "https"], consumes: ["application/json"], produces: ["application/json"], }, uiConfig: { docExpansion: "none", // expand/not all the documentations none|list|full deepLinking: true, }, staticCSP: false, transformStaticCSP: (header: any) => header, exposeRoute: true, }); // Executes Swagger fastify.ready((err) => { if (err) throw err; fastify.swagger(); }); // ...}
📑 Swagger docs will be successfully executed at 👇[http://localhost:3000/docs](http://localhost:3000/docs)
I appreciate you taking the time to read this article.🙌
In this part, We learned how to implement the general API secured with authentication and how to create a public routes and how to documenting the API endpoints using Swagger. I hope you are able to create a scalable APIs with the proper documentation from now on.
I’m so glad I taught you ☺️
Before you move on to explore the next article, don’t forget to give your claps👏 for this article and share with your friends.
Stay connected with me on social media. Thanks for your support and have a great rest of your day! 🎊