Skip to main content

SDK customization options

The customizations section is used to customize your SDKs.

SettingTypeRequiredDefaultDescription
authenticationobjectN/ACustomization the API authentication settings
generateEnvbooltrueShould example .env files be generated?
licenseobjectN/AWhat license should the SDKs be covered under?
retryobjectN/ARetry functionality customization
injectedModelsarrayN/AA list of models to inject into their parent models
customQueriesobjectN/AA list of files containing custom queries to use when working with a GraphQL spec
environmentVariablesarrayN/AA list of environment variables to inject into the SDKs
refreshTokenobjectN/ARefresh token customization
environmentsarrayN/AA list of deployment environments
inferServiceNamesboolfalseShould the SDKs infer service names from the spec?
responseHeadersboolfalseShould response headers be included in the response object
devContainerboolfalseShould the generated SDKs contain the files to be able to run it as a dev container

authentication

The authentication options allow you to configure the authentication that your API uses. This section is an object with the following options:

OptionTypeRequiredDefaultDescription
accessobjectN/AAccess authentication options
apiKeyobjectN/AAPI key authentication options

You can read more on authentication in our authentication guide.

access

This section is an object with the following options:

OptionTypeRequiredDefaultDescription
prefixstringN/AThe prefix to use for the access authentication

prefix

The prefix is used to define a custom prefix when using a bearer token. By default when using a bearer token, the Authorization header is passed as Bearer <token>. For example, if your bearer token is Passw0rd123!, the header would be:

HeaderValue
AuthorizationBearer Passw0rd123!

By setting the prefix, you can replace Bearer with the value of your choice.

For example, if you have the following:

{
...
"customizations": {
"authentication": {
"access": {
"prefix": "Token"
}
},
...
}

Then the header would be:

HeaderValue
AuthorizationToken Passw0rd123!

apiKey

The apiKey option is used to configure the API key authentication for the SDKs. This is used if the auth setting is set to apikey. This is an object with the following options:

OptionTypeRequiredDefaultDescription
headerstringX-API-KEYThe header to use for the API key authentication

The header option sets the header to use for the API key authentication. This is used by the SDKs to set the header when making requests to the API. For example, if you have the following:

{
...
"customizations": {
"authentication": {
"apiKey": {
"header": "MY_CUSTOM_APIKEY_HEADER"
}
},
...
}

Then the API key will be passed to your API using the MY_CUSTOM_APIKEY_HEADER header.

If this is not set, then API keys by default will be passed using the X-API-KEY header.

generateEnv

If this option is set to true, then an example .env file is created in the SDK with the name .env.example to set environment variables for authentication. This can be used by your SDK users to configure their environment variables.

For example, if you have an API that uses a bearer token then this will need to be passed to the SDK on initialization, and it is good practice for this to be read from an environment variable or other configuration instead of being hard coded.

In TypeScript you would initialize the SDK using code like this:

import { ExcitingSoda } from 'excitingsoda';

const sdk = new ExcitingSoda({ accessToken: process.env.EXCITINGSODA_ACCESS_TOKEN });

The EXCITINGSODA_ACCESS_TOKEN environment variable will be defined in the .env.example:

EXCITINGSODA_ACCESS_TOKEN=
info

The naming convention of .env.example is standard practice as .env files are normally not committed to source code control, and are usually ignored in .gitignore files.

license

The license option sets the open source license for the SDKs, if wanted. This is used in the LICENSE file that is created with the SDKs, as well as in the package manifests (such as the TypeScript package.json or Java pom.xml files). This is an object with the following options:

OptionTypeRequiredDefaultDescription
typestringNONEThe type of license to use. If this is not set, the default is to not set a license
urlstring""The URL of a custom license if the type is set to CUSTOM

type

The type of license - such as one of a set of popular licenses, or a custom license.

Valid values are:

ValueDescription
MITMIT
GPL3GPL 3.0
APACHEApache 2.0
NONENo license information will be set
CUSTOMUse a custom license

For example, to use an MIT license for your SDK:

{
...
"customizations": {
"license": {
"type": "MIT"
}
},
...
}

If you set this to CUSTOM, then you will need to set the url to the URL of the license file to use.

url

The URL to a custom license file. The liblab CLI will need to be able to access this file, so the remote URL will need to be public, for example a source-available Business Source License (BSL) license available publicly on your website or in a public GitHub repo.

This is only used if the type option is set to CUSTOM. For example, to point the SDK to a custom license file, use the following:

{
...
"customizations": {
"license": {
"type": "CUSTOM",
"url": "https://exciting.soda/sdk/license.txt"
}
},
...
}

You can find a list of OSI approved licenses on the Open Source Initiative licenses page.

retry

The retry setting is used to configure the retry functionality for the SDKs. This is an object with the following options:

OptionTypeRequiredDefaultDescription
enabledboolfalseShould retry functionality be enabled?
maxAttemptsinteger3The maximum number of attempts to retry
retryDelayinteger150The delay between retries in milliseconds

If this setting is not set, the SDKs will not have retry functionality enabled.

enabled

The enabled option determines whether or not retry functionality is enabled. If this is set to true, then the SDK will retry requests that fail due to network errors or server errors. If this is set to false, then the SDK will not retry requests.

maxAttempts

The maxAttempts option sets the maximum number of attempts to retry a request. For example, if this is set to 3, then the SDK will retry a request up to 3 times before giving up.

retryDelay

The retryDelay option sets the delay between retries in milliseconds. For example, if this is set to 150, then the SDK will wait 150 milliseconds between retries.

injectedModels

When liblab generates an SDK, it creates models for the request and response objects, as well as the different schemas defined in the components section of the API spec. Some schemas are composed of other schemas, and these are by default created as separate models.

For example, if you have:

"Message": {
"properties": {
"message": {
"type": "string",
"title": "Message"
},
"body": {
"$ref": "#/components/schemas/MessageBody"
}
},
"type": "object",
},
"MessageBody": {
...
}

Then the SDK will create 2 models, Messageand MessageBody. If you don't want the separate MessageBody model created, you can add "MessageBody" to the injectedModels array, and the MessageBody model will be injected into the Message model:

{
...
"customizations": {
"injectedModels": [
"MessageBody"
]
},
...
}

You will get the following:

export interface Message {
message: string;
body: Body;
}
interface Body {
details: string;
}

customQueries

The customQueries setting is used to configure custom queries for GraphQL APIs. GraphQL allows your APIs to be easily extensible, allowing you to query the API and get results that can change over time as more fields are added. This is great for flexibility, but makes SDK generation impossible as there is no way to know what fields are available to create type-safe SDKs.

Custom queries are a way to provide specific capabilities to your SDK, allowing you to provide a named service with a strongly typed response.

For example, if you have the following query:

query GetBooks {
book {
id
name
author
}
}

This will generate a book object, and a service to retrieve all books:

export type Book = Attributable &
Identifiable & {
id: string;
name: string;
};

The customQueries setting allows you to define a list of custom query files (.gql files) to add to the SDK. This is an object with the following options:

OptionTypeRequiredDefaultDescription
pathsarrayN/AA list of paths to the custom query files

paths

The paths option is an array of paths to local custom query files.

{
...
"customizations": {
"customQueries": {
"paths": [
"./book-queries.gql"
"./movie-queries.gql"
]
}
},
...
}

environmentVariables

The environmentVariables setting allows you to define environment variables that need to be set by the SDK user for the SDK to work - for example if you need values set that are used in code you create in a hook.

This setting is an array of objects, with each object having the following options:

OptionTypeRequiredDefaultDescription
namestringN/AThe name of the environment variable
descriptionstringN/AThe value of the environment variable

These environment variables will be declared in the .env.example files that are created with each SDK (assuming this is enabled with the generateEnv setting). They will also be documented in the README for the SDK.

For example, if you have the following:

{
...
"environmentVariables" : [
{
"name": "TEAM_NAME",
"description": "The team name for the SDK user"
}
],
...
}

This will add the following to the .env.example file:

TEAM_NAME=

And the following to the README:

## Environment Variables

You will need the following environment variables in order to access all the features of this SDK:

| Name | Description |
| :-------- | :----------|
| TEAM_NAME | The team name for the SDK user |

name

The name for the environment variable.

description

The description for the environment variable. This is used for the README file only.

refreshToken

The refreshToken setting is used to configure the refresh token functionality for the SDKs, to allow the SDK user to remain authenticated after their authentication expires. This is an object with the following options:

OptionTypeRequiredDefaultDescription
endpointstringN/AThe endpoint to use for refreshing the token
bearerKeystringN/AThe response property to use to get the bearer token from the response
refreshKeystringN/AThe response property to use to get the refresh token from the response

If your API supports refresh tokens for authentication, then this needs to be set. If this section is not set, then the SDKs will not have refresh token functionality enabled. You can read more about refresh tokens in our authentication guide.

These values need to match your spec - the endpoint needs to be defined as a supported path that can receive POST requests, and the bearerKey and refreshKey must be valid fields in the response from the endpoint.

endpoint

This is the endpoint to use to refresh the token.

bearerKey

The bearerKey is the name of the key in the response from the refresh token endpoint that contains the access token that the SDK can use to continue authenticating with the API.

For example, if this is the response from the endpoint that is defined in your API spec:

"RefreshTokenPair": {
"properties": {
"accessToken": {
"type": "string"
},
"refreshToken": {
"type": "string"
}
},
"required": [
"accessToken",
"refreshToken"
],
"type": "object"
},

Then the bearerKey should be set to access_token:

{
"customizations": {
"refreshToken": {
...
"bearerKey": "access_token"
}
}
}

refreshKey

The refreshKey is the name of the key in the response from the refresh token endpoint that contains the refresh token that the SDK can use to continue refreshing the access token with the API.

For example, if this is the response from the endpoint that is defined in your API spec:


"RefreshTokenPair": {
"properties": {
"accessToken": {
"type": "string"
},
"refreshToken": {
"type": "string"
}
},
"required": [
"accessToken",
"refreshToken"
],
"type": "object"
},

Then the refreshKey should be set to refresh_token:

{
"customizations": {
"refreshToken": {
...
"refreshKey": "refresh_token"
}
}
}

environments

Your API may have multiple environments or locations, such as preview and production, or NorthAmerica, EMEA, and APAC. This setting allows you to configure environments to be added to the SDKs as constant values that are passed in when creating the SDK client.

This is an array of objects, with each object having the following options:

OptionTypeRequiredDefaultDescription
namestringN/AThe name of the environment
urlstringN/AThe URL for the environment

You can read more about configuring URLs and setting these at run time in our URLs and environments guide.

name

The name option sets the name of the environment. This is used as the name of the constant in the SDK, and is used when creating the SDK client. This name must not have any invalid characters that would not be allowed in constant names. For example, DevNA is valid, Dev NA is not.

url

The url option sets the URL for the environment. This is used as the value of the constant in the SDK, and is used when creating the SDK client. This is validated to ensure it is a valid URL.

inferServiceNames

The inferServiceNames flag determines if service names for the SDK should be inferred from the endpoint names rather than tags if they all share a common prefix.

The OpenAPI specification has tags that are used to group service endpoints. For example:

tags:
- name: Boba
description: Operations for boba
- name: Soda
description: Operations for soda
paths:
"/boba":
get:
tags:
- Boba
...
"/boba/{id}":
post:
tags:
- Boba
...
"/soda":
get:
tags:
- Soda
...

In this case, the Boba tag is used to group the GET and POST operations for the /boba endpoints, and the Soda tag is used for the /soda endpoint. Using tags means the services in your SDK will be created based on these tags - for example in this case you would have a BobaService with methods to get and post boba, and a SodaService with a method to get soda.

tags are optional, so you many not have these defined in your spec. You may also have a common prefix to your endpoint, such as a version number:

paths:
"/v2/boba":
get:
...
"/v2/boba/{id}":
post:
...
"/v2/soda":
get:
...

In this case the liblab CLI would default to creating a V2Service service with methods to get and post boba, and get soda. This may not be what you want, you may want to have a BobaService and SodaService service instead.

To avoid this set the inferServiceNames option to true to infer the service names from the endpoint paths.

{
...
"customizations": {
"inferServiceNames": true
},
...
}

In this case, this would look at all the endpoints, and if they have a common prefix, then this would be ignored for the service names. Instead of a V2Service service, you would get a BobaService and SodaService.

This only works if your endpoints all have the same common prefix. For example, if you have some endpoints that are v2 and some that are v3 then service names cannot be inferred, as this may lead to name clashes (for example both services having a GET endpoint for boba). In this case, it is recommended to use tags in your OpenAPI spec.

responseHeaders

When responses come back from API calls, they can contain data, as well as important information in the headers. By default, the SDKs will only return the data from the response, and ignore the headers. If you want to include the headers in the response, then set this option to true.

For example, if you have a response object like this:

paths:
/book/{id}:
get:
operationId: getBook
parameters:
- name: id
in: path
required: true
description: The id of the book
schema:
type: string
responses:
'200':
description: Expected response to a valid request
content:
application/json:
schema:
$ref: '#/components/schemas/Book'
components:
schemas:
Book:
type: object
properties:
name:
type: string
id:
type: string

If the response headers option is not set, or set to false, then the generated getBook method will look like this:

async getBook(id: string): Promise<Book> {

If you set the response headers option to true:

{
...
"customizations": {
"responseHeaders": true
},
...
}

The the return values from calls to the SDK services will be a wrapper object containing the response data, as well as a dictionary of the headers. The getBook method will look like this:

async getBook(id: string): Promise<Response<Book>> {

With the Response<T> type looking like this:

export default interface Response<T> {
data: T;
headers: Record<string, string>;
}

If this call returned a header such as Content-Range, this would be in the headers dictionary.

devContainer

The devContainer option determines if the generated SDKs should include the files to be able to open and run the SDK using a dev container.

A dev container is a development environment setup that is containerized using technologies like Docker, making it consistent and reproducible across different development machines. It contains everything needed for the development environment, including the programming language, dependencies, libraries, tools and extensions.

If you set this to true, every SDK generated will include a devcontainer.json file, allowing you to start using the SDK as soon as it’s produced from inside any IDE that supports development containers, such as VS Code. Additionally, each SDK will have a VS Code launch.json file so you can run and debug the SDK example.

{
...
"customizations": {
"devContainer": true
},
...
}

You can read more on development containers in the development containers documentation.