项目作者: nfroidure

项目描述 :
Create a TypeScript SDK from an OpenAPI 3 definition
高级语言: TypeScript
项目地址: git://github.com/nfroidure/openapi-ts-sdk-builder.git
创建时间: 2020-09-04T07:26:46Z
项目社区:https://github.com/nfroidure/openapi-ts-sdk-builder

开源协议:MIT License

下载


openapi-ts-sdk-builder

Create a TypeScript SDK from an OpenAPI 3 definition

GitHub license

A TypeScript rewrite of
openapi-js-sdk-builder.

It basically brings a minimal TypeScript SDK from an OpenAPI3 file with no OOP
inside. It works with any HTTP client.

Usage

With a raw Node script:

  1. import { generateSDKFromOpenAPI } from 'openapi-ts-sdk-builder';
  2. import { readFileSync, writeFileSync } from 'fs';
  3. const openAPIContents = readFileSync('openapi.json', 'utf-8');
  4. const sdkContents = generateSDKFromOpenAPI(
  5. openAPIContents,
  6. {
  7. sdkVersion: 'v1.1.1',
  8. ignoredParametersNames: ['cookie', 'X-API-Version', 'X-SDK-Version'],
  9. undocumentedParametersNames: ['X-Application-Version'],
  10. },
  11. {
  12. generateUnusedSchemas: true,
  13. brandedTypes: [
  14. 'SensorUUID',
  15. 'UUID',
  16. 'Locale',
  17. 'TimeZone',
  18. 'ValueName',
  19. 'SensorVariable',
  20. ],
  21. generateRealEnums: true,
  22. exportNamespaces: true,
  23. },
  24. );
  25. writeFileSync('src/sdk.ts', sdkContents, 'utf-8');

Sample usage with axios:

  1. import BaseAPI, { APIStatuses } from './sdk.ts';
  2. import axios from 'axios';
  3. import querystring from 'querystring';
  4. import type { RequestExecutor } from './sdk.ts';
  5. import type { AxiosRequestConfig } from 'axios';
  6. const executeRequest: RequestExecutor<AxiosRequestConfig> = async (
  7. httpRequest,
  8. operationId,
  9. options,
  10. ) => {
  11. const callOptions = {
  12. ...options,
  13. baseURL: 'http://localhost:3000',
  14. url: httpRequest.path,
  15. method: httpRequest.method,
  16. headers: {
  17. ...(options.headers || {}),
  18. ...(httpRequest.headers || {}),
  19. },
  20. params: httpRequest.params,
  21. data: httpRequest.body,
  22. paramsSerializer: querystring.stringify.bind(querystring),
  23. validateStatus: (status: number) =>
  24. APIStatuses[operationId].includes(status),
  25. };
  26. const response = await axios(callOptions);
  27. return {
  28. status: response.status,
  29. headers: response.headers,
  30. body: response.data,
  31. };
  32. };
  33. // Use the API
  34. await BaseAPI.getPing(executeRequest);
  35. await BaseAPI.getUser(executeRequest, { userId: '123' });
  36. // Generate URIs only use the API then
  37. await APIURIBuilders.buildGetPingURI({
  38. /*...*/
  39. });
  40. // To know which method is used by an endpoint
  41. APIMethods.getPing; // => get
  42. // To know which status codes can be returned by an endpoint
  43. APIStatuses.getPing; // => ["default", 200]
  44. // Generate a complete endpoint input
  45. // (may be useful when you want to pass
  46. // HTTP requests to another process )
  47. APIInputBuilders.buildGetPingInput({
  48. /*...*/
  49. });

You can also safely operate on the API by doing so:

  1. import BaseAPI, { APIStatuses } from './sdk.ts';
  2. import config from './config';
  3. import YError from 'yerror';
  4. import type { RequestExecutor, Components } from './sdk.ts';
  5. import type { AxiosRequestConfig } from 'axios';
  6. export { Enums };
  7. export type { Components };
  8. type AuthTokenInput = { token?: string };
  9. const API = Object.keys(BaseAPI).reduce((FinalAPI, operationId) => {
  10. FinalAPI[operationId] = async (
  11. { token, ...input }: unknown & AuthTokenInput,
  12. options: AxiosRequestConfig = {},
  13. ) => {
  14. try {
  15. const response = await BaseAPI[operationId](
  16. executeRequest,
  17. {
  18. ...input,
  19. xApplicationVersion: config.applicationVersion,
  20. },
  21. {
  22. ...options,
  23. baseURL: config.apiURL,
  24. headers: {
  25. ...options.headers,
  26. ...(token
  27. ? {
  28. authorization: `Bearer ${token}`,
  29. }
  30. : {}),
  31. },
  32. },
  33. );
  34. return response;
  35. } catch (err) {
  36. console.error('Got an API error:', err.stack);
  37. throw new YError(
  38. err.response?.data?.error ? 'E_API_ERROR' : 'E_UNEXPECTED_ERROR',
  39. err.response?.data,
  40. );
  41. }
  42. };
  43. return FinalAPI;
  44. }, {}) as {
  45. [P in keyof typeof BaseAPI]: (
  46. input: Parameters<typeof BaseAPI[P]>[1] & AuthTokenInput,
  47. config?: AxiosRequestConfig,
  48. ) => Promise<ReturnType<typeof BaseAPI[P]>>;
  49. };
  50. export default API;

Finally, you may appreciate using it with the
useSSR React hook to benefit from your SDK
types:

  1. import useSWR from 'swr';
  2. import API from './api';
  3. type Handler<I, O> = (input: I) => Promise<O>;
  4. type HandlerInput<T> = T extends Handler<infer I, unknown> ? I : never;
  5. type HandlerOutput<T> = T extends Handler<unknown, infer I> ? I : never;
  6. const API_KEYS: Record<any, string> = Object.keys(API).reduce((hash, key) => {
  7. hash[API[key]] = key;
  8. return hash;
  9. }, {});
  10. export default function useAPISWR<T extends Handler<any, any>>(
  11. swrCouple: [T, HandlerInput<T>],
  12. options?: Parameters<typeof useSWR>[2],
  13. ) {
  14. const uniqueKey = swrCouple
  15. ? Object.keys(swrCouple[1]).reduce(
  16. (finalKey, key) => finalKey + key + JSON.stringify(swrCouple[1][key]),
  17. // Sadly, here, we cannot rely on `swrCouple[0].name` to
  18. // build the unicity key since the build destroys it
  19. API_KEYS[swrCouple[0]] + '-',
  20. )
  21. : null;
  22. return useSWR<
  23. Awaited<HandlerOutput<T>> extends { body: infer D } ? D : never
  24. >(
  25. uniqueKey,
  26. async () => (await swrCouple[0](swrCouple[1])).body,
  27. options as any,
  28. );
  29. }

API

openapi-ts-sdk-builder

openapi-ts-sdk-builder~generateSDKFromOpenAPI(openAPIContent, options, [typeOptions]) ⇒ Promise.

Build a JS SDK from an OpenAPI file

Kind: inner method of openapi-ts-sdk-builder
Returns: Promise. - 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. Provide a list of parameters to ignore
[options.undocumentedParametersNames] Array. Provide a list of parameters to keep undocumented
[typeOptions] Object Options to be passed to the type generator

Authors

License

MIT