{"id":14483600,"url":"https://github.com/nfroidure/openapi-ts-sdk-builder","last_synced_at":"2025-04-24T02:53:31.883Z","repository":{"id":39801156,"uuid":"292779894","full_name":"nfroidure/openapi-ts-sdk-builder","owner":"nfroidure","description":"Create a TypeScript SDK from an OpenAPI 3 definition","archived":false,"fork":false,"pushed_at":"2024-10-03T07:50:30.000Z","size":1078,"stargazers_count":14,"open_issues_count":4,"forks_count":1,"subscribers_count":2,"default_branch":"main","last_synced_at":"2025-04-10T12:56:13.676Z","etag":null,"topics":["hacktoberfest","openapi","sdk-builder"],"latest_commit_sha":null,"homepage":"","language":"TypeScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/nfroidure.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":".github/CONTRIBUTING","funding":".github/FUNDING.yml","license":"LICENSE","code_of_conduct":".github/CODE_OF_CONDUCT.md","threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null},"funding":{"github":["nfroidure"]}},"created_at":"2020-09-04T07:26:46.000Z","updated_at":"2025-04-05T03:12:14.000Z","dependencies_parsed_at":"2025-01-14T07:34:18.073Z","dependency_job_id":"d7bbb27e-2a66-439d-84a4-1b9bc77a9718","html_url":"https://github.com/nfroidure/openapi-ts-sdk-builder","commit_stats":{"total_commits":39,"total_committers":3,"mean_commits":13.0,"dds":"0.10256410256410253","last_synced_commit":"3198545b5e5c5f6e0585489f674287e8d48bdcb2"},"previous_names":[],"tags_count":15,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/nfroidure%2Fopenapi-ts-sdk-builder","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/nfroidure%2Fopenapi-ts-sdk-builder/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/nfroidure%2Fopenapi-ts-sdk-builder/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/nfroidure%2Fopenapi-ts-sdk-builder/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/nfroidure","download_url":"https://codeload.github.com/nfroidure/openapi-ts-sdk-builder/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":250020782,"owners_count":21361959,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["hacktoberfest","openapi","sdk-builder"],"created_at":"2024-09-03T00:01:53.984Z","updated_at":"2025-04-24T02:53:31.863Z","avatar_url":"https://github.com/nfroidure.png","language":"TypeScript","funding_links":["https://github.com/sponsors/nfroidure"],"categories":["TypeScript"],"sub_categories":[],"readme":"[//]: # ( )\n[//]: # (This file is automatically generated by a `metapak`)\n[//]: # (module. Do not change it  except between the)\n[//]: # (`content:start/end` flags, your changes would)\n[//]: # (be overridden.)\n[//]: # ( )\n# openapi-ts-sdk-builder\n\u003e Create a TypeScript SDK from an OpenAPI 3 definition\n\n[![GitHub license](https://img.shields.io/badge/license-MIT-blue.svg)](https://github.com/nfroidure/openapi-ts-sdk-builder/blob/main/LICENSE)\n\n\n[//]: # (::contents:start)\n\nA TypeScript rewrite of\n[openapi-js-sdk-builder](https://github.com/sencrop/openapi-js-sdk-builder).\n\nIt basically brings a minimal TypeScript SDK from an OpenAPI3 file with no OOP\ninside. It works with any HTTP client.\n\n# Usage\n\nWith a raw Node script:\n\n```js\nimport { generateSDKFromOpenAPI } from 'openapi-ts-sdk-builder';\nimport { readFileSync, writeFileSync } from 'fs';\n\nconst openAPIContents = readFileSync('openapi.json', 'utf-8');\nconst sdkContents = generateSDKFromOpenAPI(\n  openAPIContents,\n  {\n    sdkVersion: 'v1.1.1',\n    ignoredParametersNames: ['cookie', 'X-API-Version', 'X-SDK-Version'],\n    undocumentedParametersNames: ['X-Application-Version'],\n  },\n  {\n    generateUnusedSchemas: true,\n    brandedTypes: [\n      'SensorUUID',\n      'UUID',\n      'Locale',\n      'TimeZone',\n      'ValueName',\n      'SensorVariable',\n    ],\n    generateRealEnums: true,\n    exportNamespaces: true,\n  },\n);\n\nwriteFileSync('src/sdk.ts', sdkContents, 'utf-8');\n```\n\nSample usage with `axios`:\n\n```ts\nimport BaseAPI, { APIStatuses } from './sdk.ts';\nimport axios from 'axios';\nimport querystring from 'querystring';\nimport type { RequestExecutor } from './sdk.ts';\nimport type { AxiosRequestConfig } from 'axios';\n\nconst executeRequest: RequestExecutor\u003cAxiosRequestConfig\u003e = async (\n  httpRequest,\n  operationId,\n  options,\n) =\u003e {\n  const callOptions = {\n    ...options,\n    baseURL: 'http://localhost:3000',\n    url: httpRequest.path,\n    method: httpRequest.method,\n    headers: {\n      ...(options.headers || {}),\n      ...(httpRequest.headers || {}),\n    },\n    params: httpRequest.params,\n    data: httpRequest.body,\n    paramsSerializer: querystring.stringify.bind(querystring),\n    validateStatus: (status: number) =\u003e\n      APIStatuses[operationId].includes(status),\n  };\n  const response = await axios(callOptions);\n\n  return {\n    status: response.status,\n    headers: response.headers,\n    body: response.data,\n  };\n};\n\n// Use the API\nawait BaseAPI.getPing(executeRequest);\nawait BaseAPI.getUser(executeRequest, { userId: '123' });\n\n// Generate URIs only use the API then\nawait APIURIBuilders.buildGetPingURI({\n  /*...*/\n});\n\n// To know which method is used by an endpoint\nAPIMethods.getPing; // =\u003e get\n\n// To know which status codes can be returned by an endpoint\nAPIStatuses.getPing; // =\u003e [\"default\", 200]\n\n// Generate a complete endpoint input\n// (may be useful when you want to pass\n// HTTP requests to another process )\nAPIInputBuilders.buildGetPingInput({\n  /*...*/\n});\n```\n\nYou can also safely operate on the API by doing so:\n\n```ts\nimport BaseAPI, { APIStatuses } from './sdk.ts';\nimport config from './config';\nimport YError from 'yerror';\nimport type { RequestExecutor, Components } from './sdk.ts';\nimport type { AxiosRequestConfig } from 'axios';\n\nexport { Enums };\nexport type { Components };\n\ntype AuthTokenInput = { token?: string };\n\nconst API = Object.keys(BaseAPI).reduce((FinalAPI, operationId) =\u003e {\n  FinalAPI[operationId] = async (\n    { token, ...input }: unknown \u0026 AuthTokenInput,\n    options: AxiosRequestConfig = {},\n  ) =\u003e {\n    try {\n      const response =  await BaseAPI[operationId](\n        executeRequest,\n        {\n          ...input,\n          xApplicationVersion: config.applicationVersion,\n        },\n        {\n          ...options,\n          baseURL: config.apiURL,\n          headers: {\n            ...options.headers,\n            ...(token\n              ? {\n                  authorization: `Bearer ${token}`,\n                }\n              : {}),\n          },\n        },\n      );\n      return response;\n    } catch (err) {\n      console.error('Got an API error:', err.stack);\n      throw new YError(\n        err.response?.data?.error ? 'E_API_ERROR' : 'E_UNEXPECTED_ERROR',\n        err.response?.data,\n      );\n    }\n  };\n  return FinalAPI;\n}, {}) as {\n  [P in keyof typeof BaseAPI]: (\n    input: Parameters\u003ctypeof BaseAPI[P]\u003e[1] \u0026 AuthTokenInput,\n    config?: AxiosRequestConfig,\n  ) =\u003e Promise\u003cReturnType\u003ctypeof BaseAPI[P]\u003e\u003e;\n};\n\nexport default API;\n```\n\nFinally, you may appreciate using it with the\n[`useSSR` React hook](https://github.com/vercel/swr) to benefit from your SDK\ntypes:\n\n```ts\nimport useSWR from 'swr';\nimport API from './api';\n\ntype Handler\u003cI, O\u003e = (input: I) =\u003e Promise\u003cO\u003e;\ntype HandlerInput\u003cT\u003e = T extends Handler\u003cinfer I, unknown\u003e ? I : never;\ntype HandlerOutput\u003cT\u003e = T extends Handler\u003cunknown, infer I\u003e ? I : never;\n\nconst API_KEYS: Record\u003cany, string\u003e = Object.keys(API).reduce((hash, key) =\u003e {\n  hash[API[key]] = key;\n  return hash;\n}, {});\n\nexport default function useAPISWR\u003cT extends Handler\u003cany, any\u003e\u003e(\n  swrCouple: [T, HandlerInput\u003cT\u003e],\n  options?: Parameters\u003ctypeof useSWR\u003e[2],\n) {\n  const uniqueKey = swrCouple\n    ? Object.keys(swrCouple[1]).reduce(\n        (finalKey, key) =\u003e finalKey + key + JSON.stringify(swrCouple[1][key]),\n        // Sadly, here, we cannot rely on `swrCouple[0].name` to\n        // build the unicity key since the build destroys it\n        API_KEYS[swrCouple[0]] + '-',\n      )\n    : null;\n\n  return useSWR\u003c\n    Awaited\u003cHandlerOutput\u003cT\u003e\u003e extends { body: infer D } ? D : never\n  \u003e(\n    uniqueKey,\n    async () =\u003e (await swrCouple[0](swrCouple[1])).body,\n    options as any,\n  );\n}\n```\n\n[//]: # (::contents:end)\n\n# API\n\u003ca name=\"module_openapi-ts-sdk-builder\"\u003e\u003c/a\u003e\n\n## openapi-ts-sdk-builder\n\u003ca name=\"module_openapi-ts-sdk-builder..generateSDKFromOpenAPI\"\u003e\u003c/a\u003e\n\n### openapi-ts-sdk-builder~generateSDKFromOpenAPI(openAPIContent, options, [typeOptions]) ⇒ \u003ccode\u003ePromise.\u0026lt;string\u0026gt;\u003c/code\u003e\nBuild a JS SDK from an OpenAPI file\n\n**Kind**: inner method of [\u003ccode\u003eopenapi-ts-sdk-builder\u003c/code\u003e](#module_openapi-ts-sdk-builder)  \n**Returns**: \u003ccode\u003ePromise.\u0026lt;string\u0026gt;\u003c/code\u003e - The SDK JS code  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| openAPIContent | \u003ccode\u003estring\u003c/code\u003e |  |\n| options | \u003ccode\u003eObject\u003c/code\u003e |  |\n| options.sdkVersion | \u003ccode\u003estring\u003c/code\u003e | The SDK version |\n| [options.sdkName] | \u003ccode\u003estring\u003c/code\u003e | The SDK name (default to API) |\n| [options.ignoredParametersNames] | \u003ccode\u003eArray.\u0026lt;string\u0026gt;\u003c/code\u003e | Provide a list of parameters to ignore |\n| [options.undocumentedParametersNames] | \u003ccode\u003eArray.\u0026lt;string\u0026gt;\u003c/code\u003e | Provide a list of parameters to keep undocumented |\n| [typeOptions] | \u003ccode\u003eObject\u003c/code\u003e | Options to be passed to the type generator |\n\n\n# Authors\n- [Nicolas Froidure](https://insertafter.com/en/index.html)\n\n# License\n[MIT](https://github.com/nfroidure/openapi-ts-sdk-builder/blob/main/LICENSE)\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fnfroidure%2Fopenapi-ts-sdk-builder","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fnfroidure%2Fopenapi-ts-sdk-builder","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fnfroidure%2Fopenapi-ts-sdk-builder/lists"}