Automate SDK generation for Fastify APIs
Supported SDK languages:
TypeScript / Javascript | Java / Kotlin | Python | C# | Go | PHP |
---|---|---|---|---|---|
✅ | ✅ | ✅ | ✅ | ✅ | ✅ |
- Before getting started make sure you have a liblab account and the liblab CLI installed.
- If you don't have an existing project but want to try out liblab then check out our standalone tutorials.
Providing an SDK for your API can significantly ease the development process for users, ensuring quicker integration and encouraging wider adoption due to the streamlined development experience.
In this doc you'll learn how to take your existing Fastify API and generate user-friendly SDKs for most major programming languages using the liblab SDK generator. After a short bit of setup you'll have a pipeline that will automatically generate SDKs for your API whenever you make changes.
Initializing the SDK
First, create a new directory to store your SDK. This directory should be separate from your existing project directory:
mkdir Fastify-sdk
cd Fastify-sdk
And initialize your project to create a liblab.config.json
file:
liblab init -y
Getting an OpenAPI Spec File
In order to auto-generate SDKs from a Fastify project, you need an OpenAPI Spec File. The OpenAPI file contains information that describes your API, like servers, paths, operations, parameters, responses, and security schemas.
Since Fastify does not have built-in support for generating OpenAPI specs, you'll need a plugin. The most commonly used plugin for this purpose is
the fastify-swagger
.
This guide will walk you through the steps to use fastify-swagger
to generate the OpenAPI spec from your Fastify API.
Installing fastify-swagger
To install the fastify-swagger
, navigate to your Fastify API directory and run:
npm install @fastify/swagger
Configuring the fastify-swagger
Now you'll configure fastify-swagger
. Here are some of the key configuration options you can use:
info
: Define the API's title, description, and version.servers
: Specify your API servers, such as production and sandbox URLs.security
: Set up security schemes used by the API operations.components
: Add reusable objects (e.g., schema definitions).tags
: Group endpoints under categories for better organization.
You can use all properties defined in OpenAPI V3 to customize your OpenAPI spec.
First you'll integrate fastify-swagger
with your project by calling fastify.register()
and passing in the @fastify/swagger
plugin along with a high level configuration:
//...
async function start() {
await fastify.register(require('@fastify/swagger'), {
openapi: {
openapi: '3.1.0',
info: {
title: 'Greeting API',
description: 'This API allows you to greet users by their name, providing personalized greeting messages.',
version: '1.0.0'
},
servers: [
{
url: 'http://localhost:3000',
description: 'Development environment for local testing'
}
],
components: {
securitySchemes: {
apiKey: {
type: 'apiKey',
name: 'apiKey',
in: 'header',
description: 'API key used for authentication, required in the header of requests.'
}
}
},
tags: [
{ name: 'Greeting', description: 'Endpoints related to user greetings.' }
]
}
});
//...
Annotating Your Project
You don't need to annotate every part of your API at once. You've already defined enough of your API to generate a usable openapi.json
specification file. You could skip to the Registering the OpenAPI Spec Endpoint section whenever you'd like.
This is an iterative process. You can always return to it later.
To generate the best SDK and documentation possible for your SDK's users, you should provide additional metadata alongside the definitions of your endpoints. The metadata will be included in the generated OpenAPI spec. Below are the key annotations you can use with fastify-swagger
to document your endpoints.
description
: A brief explanation of what the endpoint does.summary
: A short summary of the operation.security
: Defines the security requirements for accessing the endpoint. You can specify different authentication mechanisms likeapiKey
,bearerAuth
, etc.params
: Describes the parameters in the URL.querystring
: Defines query parameters.body
: Describes the request body for POST, PUT, or PATCH methods.response
: Describes the possible responses from the endpoint, including status codes and the structure of the response body.
The following code snippet shows how to define a simple greeting endpoint. It provides an endpoint, /greeting/{name}
, which accepts a name as input and returns a Hello, <name>!
message.
fastify.get('/greeting/:name', {
schema: {
description: 'Returns a personalized greeting message for the specified user.',
tags: ['Greeting'],
summary: 'Greet a user by their name',
security: [{ apiKey: [] }],
params: {
type: 'object',
properties: {
name: {
type: 'string',
description: 'The name of the person to greet. This is a required parameter for personalized greetings.'
}
},
required: ['name']
},
response: {
200: {
description: 'Successfully returns a personalized greeting message.',
content: {
'application/json': {
schema: {
type: 'object',
properties: {
message: {
type: 'string',
description: 'The greeting message directed at the user.'
}
},
example: {
message: "Hello, John!" // Example of a successful response
}
}
}
}
},
400: {
description: 'Bad Request - Missing "name" parameter in the request.',
content: {
'application/json': {
schema: {
type: 'object',
properties: {
error: {
type: 'string',
description: 'Error message explaining the cause of the bad request.'
}
},
example: {
error: "Missing 'name' parameter in the request" // Example of an error response
}
}
}
}
}
}
}
}
Registering the OpenAPI Spec Endpoint
By default, the fastify-swagger
plugin does not expose the OpenAPI spec automatically. You need to register an endpoint to make the OpenAPI spec available as a JSON file. You can choose whatever path you'd like. Here it's set as /openapi.json
:
fastify.get('/openapi.json', async (request, reply) => {
return fastify.swagger();
});
Complete Example
Combining the above steps produces a complete example of generating an Openapi spec using Fastify.
const fastify = require('fastify')({ logger: true });
async function start() {
await fastify.register(require('@fastify/swagger'), {
openapi: {
openapi: '3.1.0',
info: {
title: 'Greeting API',
description: 'This API allows you to greet users by their name, providing personalized greeting messages.',
version: '1.0.0'
},
servers: [
{
url: 'http://localhost:3000',
description: 'Development environment for local testing'
}
],
components: {
securitySchemes: {
apiKey: {
type: 'apiKey',
name: 'apiKey',
in: 'header',
description: 'API key used for authentication, required in the header of requests.'
}
}
},
tags: [
{ name: 'Greeting', description: 'Endpoints related to user greetings.' }
]
}
});
fastify.get('/greeting/:name', {
schema: {
description: 'Returns a personalized greeting message for the specified user.',
tags: ['Greeting'],
summary: 'Greet a user by their name',
security: [{ apiKey: [] }],
params: {
type: 'object',
properties: {
name: {
type: 'string',
description: 'The name of the person to greet. This is a required parameter for personalized greetings.'
}
},
required: ['name']
},
response: {
200: {
description: 'Successfully returns a personalized greeting message.',
content: {
'application/json': {
schema: {
type: 'object',
properties: {
message: {
type: 'string',
description: 'The greeting message directed at the user.'
}
},
example: {
message: "Hello, John!" // Example of a successful response
}
}
}
}
},
400: {
description: 'Bad Request - Missing "name" parameter in the request.',
content: {
'application/json': {
schema: {
type: 'object',
properties: {
error: {
type: 'string',
description: 'Error message explaining the cause of the bad request.'
}
},
example: {
error: "Missing 'name' parameter in the request" // Example of an error response
}
}
}
}
}
}
}
}, async (request, reply) => {
const { name } = request.params;
if (!name) {
return reply.status(400).send({ error: "Missing 'name' parameter in the request" });
}
return { message: `Hello, ${name}!` };
});
fastify.get('/openapi.json', async (request, reply) => {
return fastify.swagger();
});
// Ensure Fastify is ready before starting the server
await fastify.ready();
fastify.listen({ port: 3000 }, (err, address) => {
if (err) {
console.error(err);
process.exit(1);
}
console.log(`🚀 Server running at ${address}`);
console.log(`📄 OpenAPI spec available at ${address}/openapi.json`);
});
}
start();
Click to see the OpenAPI spec example
{
"openapi": "3.1.0",
"info": {
"title": "Greeting API",
"description": "This API allows you to greet users by their name, providing personalized greeting messages.",
"version": "1.0.0"
},
"components": {
"securitySchemes": {
"apiKey": {
"type": "apiKey",
"name": "apiKey",
"in": "header",
"description": "API key used for authentication, required in the header of requests."
}
},
"schemas": {
}
},
"paths": {
"/greeting/{name}": {
"get": {
"summary": "Greet a user by their name",
"tags": [
"Greeting"
],
"description": "Returns a personalized greeting message for the specified user.",
"parameters": [
{
"schema": {
"type": "string"
},
"in": "path",
"name": "name",
"required": true,
"description": "The name of the person to greet. This is a required parameter for personalized greetings."
}
],
"security": [
{
"apiKey": []
}
],
"responses": {
"200": {
"description": "Successfully returns a personalized greeting message.",
"content": {
"application/json": {
"schema": {
"type": "object",
"properties": {
"message": {
"type": "string",
"description": "The greeting message directed at the user."
}
},
"example": {
"message": "Hello, John!"
}
}
}
}
},
"400": {
"description": "Bad Request - Missing \"name\" parameter in the request.",
"content": {
"application/json": {
"schema": {
"type": "object",
"properties": {
"error": {
"type": "string",
"description": "Error message explaining the cause of the bad request."
}
},
"example": {
"error": "Missing 'name' parameter in the request"
}
}
}
}
}
}
}
},
"/openapi.json": {
"get": {
"responses": {
"200": {
"description": "Default Response"
}
}
}
}
},
"servers": [
{
"url": "http://localhost:3000",
"description": "Development environment for local testing"
}
],
"tags": [
{
"name": "Greeting",
"description": "Endpoints related to user greetings, allowing personalized messages based on the name provided."
}
]
}
Copy Your Spec
Once the configuration is complete, you can generate the OpenAPI spec. Start your development server as you normally would:
node server.js
To view your OpenAPI spec, navigate to the /openapi.json
endpoint on your server (e.g., http://localhost:3000/openapi.json).
If everything looks good then save your openapi.json
file to the liblab project directory you created during the initializing step. This is typically something like:
cd ../Fastify-sdk
curl -o openapi.json http://127.0.0.1:3000/openapi.json
Configuring liblab
Now you'll need to make some minor updates to your liblab.config.json
file in your Fastify-sdk folder:
- Point the
specFilePath
parameter to the location of your OpenAPI spec file (ex../openapi.json
). - Specify the
baseUrl
of your API. This is the URL that the SDK will use to make requests to your API.
The top of the file should then looks something like this:
{
"sdkName": "Fastify-sdk",
"apiVersion": "1.0.0",
"apiName": "Fastify-api",
"specFilePath": "./openapi.json",
"baseUrl": "http://localhost:PORT",
"languages": [
"go",
"java",
"python",
"typescript",
"csharp",
"php"
],
"auth": [
"bearer"
]
}
liblab's SDK generator supports many more advanced URL and environment configuration options than the basic configuration shown here.
Explore the configuration documentation to discover all the available settings and enhancements or review the SDK customization options for tailored adjustments.
Generate the SDK
During build you might see warnings about the OpenAPI spec. These are often minor issues that can be fixed later.
Now that you have an OpenAPI spec file and have finished setting the liblab.config.json
file, it's time to generate our SDK:
liblab build -y
The CLI will validate the OpenAPI spec and notify you about any issues with it or the liblab.config.json
.
The output will look something like this:
✓ No issues detected in the liblab config file.
No hooks found, SDKs will be generated without hooks.
⚠ Validation succeeded with warnings
Created /Users/username/projects/Fastify-sdk/output/api-schema-validation.json with the full linting results
Next you'll see the builds started and once they're done you'll see a message like this:
Your SDKs are being generated. Visit the liblab portal (https://app.liblab.com/apis/Fastify-sdk/builds/1234) to view more details on your build(s).
✓ C# built
✓ Go built
✓ Java built
✓ PHP built
✓ Python built
✓ TypeScript built
✓ Generate package-lock.json for TypeScript
Successfully generated SDKs for Python, Java, Go, TypeScript, C#, PHP. ♡ You can find them inside: /Users/username/projects/Fastify-sdk/output
If we go inside the output
directory, we will see a directory for each of our SDKs:
ls output/
api-schema-validation.json go php typescript
csharp java python
Try out your SDK
The following instructions assume you have already set up the respective development environment for the language you are testing. If necessary refer to each language's official documentation before proceeding.
Learn more about the language versions liblab generated SDKs support.
The generated SDKs are intended to be deployed to package managers for end users. The instructions below to test your SDK locally will differ from user-facing instructions.
- TypeScript / JavaScript
- Python
- Java
- C#
cd output/typescript/examples
npm run setup
npm run start
cd output/python/examples
chmod +x install.sh
./install.sh
source .venv/bin/activate
python3 sample.py
cd output/java/example
chmod +x run.sh
./run.sh
cd output/csharp/Example
dotnet run --framework net9.0
Next Steps
Now that you've packaged your SDKs you can learn how to integrate them with your CI/CD pipeline and publish them to their respective package manager repositories.
We currently have guides for: