Create a TypeScript SDK from an OpenAPI 3 definition
A TypeScript rewrite of openapi-js-sdk-builder.
It basically brings a minimal TypeScript SDK from an OpenAPI3 file with no OOP
inside. It is based on the axios
module.
With a raw Node script:
import { generateSDKFromOpenAPI } from 'openapi-ts-sdk-builder';
import { readFileSync, writeFileSync } from 'fs';
const openAPIContents = readFileSync('openapi.json', 'utf-8');
const sdkContents = generateSDKFromOpenAPI(openAPIContents);
writeFileSync('sdk.ts', sdkContents, 'utf-8');
You can also use the built-in webpack loader in your frontends builds:
In webpack.config.js
:
module.exports = {
//...
module: {
rules: [
{
test: /(\.|^)openapi.json$/,
loader: require.resolve('openapi-js-sdk-builder'),
type: 'javascript/auto',
},
],
},
};
In your code:
import API from './myapi.openapi.json';
// Just use the API then
await API.getPing();
You can also safely operate on the API by doing so:
import BaseAPI from './sdk';
import config from './config';
import type { AxiosRequestConfig } from 'axios';
type AuthTokenInput = { token?: string };
export default Object.keys(BaseAPI).reduce((FinalAPI, operationId) => {
FinalAPI[operationId] = async (
{ token, ...input }: unknown & AuthTokenInput,
options: AxiosRequestConfig = {},
) => {
return BaseAPI[operationId](
{
...input,
xApplicationVersion: process.env.VERSION,
},
{
...options,
baseURL: config.apiURL,
headers: {
...options.headers,
...(token
? {
authorization: `Bearer ${token}`,
}
: {}),
},
validateStatus: () => true,
},
);
};
return FinalAPI;
}, {}) as {
[P in keyof typeof BaseAPI]: (
input: Parameters<typeof BaseAPI[P]>[0] & AuthTokenInput,
config?: AxiosRequestConfig,
) => Promise<ReturnType<typeof BaseAPI[P]>>;
};
Finally, you may appreciate using it with the
useSSR
React hook to benefit from your SDK
types:
import useSWR from 'swr';
import type { PromiseValue } from 'type-fest';
import API from './api';
type Handler<I, O> = (input: I) => Promise<O>;
type HandlerInput<T> = T extends Handler<infer I, unknown> ? I : never;
type HandlerOutput<T> = T extends Handler<unknown, infer I> ? I : never;
const API_KEYS: Record<any, string> = Object.keys(API).reduce((hash, key) => {
hash[API[key]] = key;
return hash;
}, {});
export default function useAPISWR<T extends Handler<any, any>>(
swrCouple: [T, HandlerInput<T>],
options?: Parameters<typeof useSWR>[2],
) {
const uniqueKey = swrCouple
? Object.keys(swrCouple[1]).reduce(
(finalKey, key) => finalKey + key + JSON.stringify(swrCouple[1][key]),
// Sadly, here, we cannot rely on `swrCouple[0].name` to
// build the unicity key since the build destroys it
API_KEYS[swrCouple[0]] + '-',
)
: null;
return useSWR<
PromiseValue<HandlerOutput<T>> extends { body: infer D } ? D : never
>(
uniqueKey,
async () => (await swrCouple[0](swrCouple[1])).body,
options as any,
);
}
Build a JS SDK from an OpenAPI file
Kind: inner method of openapi-ts-sdk-builder
Returns: Promise.<string>
- The SDK JS code
Param | Type | Description |
---|---|---|
openAPIContent | string |
|
options | Object |
|
options.sdkVersion | string |
The SDK version |
[options.sdkName] | string |
The SDK name (default to API) |
[options.ignoredParametersNames] | Array.<string> |
Provide a list of parameters to ignore |
[options.undocumentedParametersNames] | Array.<string> |
Provide a list of parameters to keep undocumented |
[options.filterStatuses] | Array.<number> |
Filter some response statuses |
[options.generateUnusedSchemas] | boolean |
Wether to generate the schemas that ain't used at the moment |