{"id":15776056,"url":"https://github.com/mikestead/openapi-client","last_synced_at":"2025-04-09T10:10:43.162Z","repository":{"id":46327086,"uuid":"61082707","full_name":"mikestead/openapi-client","owner":"mikestead","description":"Generate ES6 or Typescript service integration code from an OpenAPI 2 spec","archived":false,"fork":false,"pushed_at":"2023-04-25T20:21:42.000Z","size":107,"stargazers_count":93,"open_issues_count":21,"forks_count":34,"subscribers_count":9,"default_branch":"master","last_synced_at":"2025-03-26T19:45:50.406Z","etag":null,"topics":["code-generation","javascript","openapi","swagger","typescript"],"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/mikestead.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"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}},"created_at":"2016-06-14T01:45:54.000Z","updated_at":"2023-09-18T09:54:56.000Z","dependencies_parsed_at":"2024-06-18T18:38:43.900Z","dependency_job_id":null,"html_url":"https://github.com/mikestead/openapi-client","commit_stats":{"total_commits":95,"total_committers":13,"mean_commits":"7.3076923076923075","dds":0.6631578947368422,"last_synced_commit":"45b482a8427476b187dbcce946b2bf9fef7db210"},"previous_names":[],"tags_count":41,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mikestead%2Fopenapi-client","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mikestead%2Fopenapi-client/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mikestead%2Fopenapi-client/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mikestead%2Fopenapi-client/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/mikestead","download_url":"https://codeload.github.com/mikestead/openapi-client/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":247489187,"owners_count":20947069,"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":["code-generation","javascript","openapi","swagger","typescript"],"created_at":"2024-10-04T17:04:40.253Z","updated_at":"2025-04-09T10:10:43.136Z","avatar_url":"https://github.com/mikestead.png","language":"TypeScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# OpenAPI Client\n\nGenerate ES6 or Typescript service integration code from an OpenAPI 2.0 spec.\n\nAlso supports optional Redux action creator generation.\n\nTested against JSON services.\n\n## Install\n\nIn your project\n\n    npm install openapi-client --save-dev\n\nOr globally to run CLI from anywhere\n\n    npm install openapi-client -g\n\n### Type Dependencies\n\nIf targeting TypeScript you'll also need to install the `isomorphic-fetch` typings in your project.\n\n    npm install @types/isomorphic-fetch --save-dev\n\n## Usage – Generating the API client\n\n`openapi-client` generates action creators in the `outDir` of your choosing. The rest of the examples assume that you've set `--outDir api-client`. You can generate the `api-client` either using the CLI, or in code.\n\n### CLI\n\n```\nUsage: openapi [options]\n\nOptions:\n\n  -h, --help              output usage information\n  -V, --version           output the version number\n  -s, --src \u003curl|path\u003e    The url or path to the Open API spec file\n  -o, --outDir \u003cdir\u003e      The path to the directory where files should be generated\n  -l, --language \u003cjs|ts\u003e  The language of code to generate\n  --redux                 True if wanting to generate redux action creators\n```\n\n### Code\n\n```javascript\nconst openapi = require('openapi-client')\nopenapi.genCode({\n  src: 'http://petstore.swagger.io/v2/swagger.json',\n  outDir: './src/service',\n  language: 'ts',\n  redux: true\n})\n.then(complete, error)\n\nfunction complete(spec) {\n  console.info('Service generation complete')\n}\n\nfunction error(e) {\n  console.error(e.toString())\n}\n```\n\n## Usage – Integrating into your project\n\n### Initialization\n\nIf you don't need authorization, or to override anything provided by your OpenAPI spec, you can use the actions generated by `openapi-client` directly. However, most of the time you'll need to perform some authorization to use your API. If that's the case, you can initialize the client, probably in the `index.js` of your client-side app:\n\n```javascript\nimport serviceGateway from './path/to/service/gateway';\n\nserviceGateway.init({\n  url: 'https://service.com/api', // set your service url explicitly. Defaults to the one generated from your OpenAPI spec\n  getAuthorization // Add a `getAuthorization` handler for when a request requires auth credentials\n});\n\n// The param 'security' represents the security definition in your OpenAPI spec a request is requiring\n// For bearer type it has two properties:\n// 1. id - the name of the security definition from your OpenAPI spec\n// 2. scopes - the token scope(s) required\n// Should return a promise\nfunction getAuthorization(security) {\n  switch (security.id) {\n    case 'account': return getAccountToken(security);\n    // case 'api_key': return getApiKey(security); // Or any other securityDefinitions from your OpenAPI spec\n    default: throw new Error(`Unknown security type '${security.id}'`)\n  }\n};\n\nfunction getAccountToken(security) {\n  const token = findAccountToken(security); // A utility function elsewhere in your application that returns a string containing your token – possibly from Redux or localStorage\n  if (token) return Promise.resolve({ token: token.value });\n  else throw new Error(`Token ${type} ${security.scopes} not available`);\n}\n```\n\n#### Initialization Options\n\nThe full set of gateway initialization options.\n\n```TypeScript\nexport interface ServiceOptions {\n  /**\n   * The service url.\n   *\n   * If not specified then defaults to the one defined in the Open API\n   * spec used to generate the service api.\n   */\n  url?: string${ST}\n  /**\n   * Fetch options object to apply to each request e.g \n   * \n   *     { mode: 'cors', credentials: true }\n   * \n   * If a headers object is defined it will be merged with any defined in\n   * a specific request, the latter taking precedence with name collisions.\n   */\n  fetchOptions?: any${ST}\n  /**\n   * Function which should resolve rights for a request (e.g auth token) given\n   * the OpenAPI defined security requirements of the operation to be executed.\n   */\n  getAuthorization?: (security: OperationSecurity, \n                      securityDefinitions: any,\n                      op: OperationInfo) =\u003e Promise\u003cOperationRightsInfo\u003e${ST}\n  /**\n   * Given an error response, custom format and return a ServiceError\n   */\n  formatServiceError?: (response: FetchResponse, data: any) =\u003e ServiceError${ST}\n  /**\n   * Before each Fetch request is dispatched this function will be called if it's defined.\n   * \n   * You can use this to augment each request, for example add extra query parameters.\n   * \n   *     const params = reqInfo.parameters;\n   *     if (params \u0026\u0026 params.query) {\n   *       params.query.lang = \"en\"\n   *     }\n   *     return reqInfo\n   */\n  processRequest?: (op: OperationInfo, reqInfo: RequestInfo) =\u003e RequestInfo${ST}\n  /**\n   * If you need some type of request retry behavior this function\n   * is the place to do it.\n   * \n   * The response is promise based so simply resolve the \"res\" parameter\n   * if you're happy with it e.g.\n   * \n   *     if (!res.error) return Promise.resolve({ res });\n   * \n   * Otherwise return a promise which flags a retry.\n   * \n   *     return Promise.resolve({ res, retry: true })\n   * \n   * You can of course do other things before this, like refresh an auth\n   * token if the error indicated it expired.\n   * \n   * The \"attempt\" param will tell you how many times a retry has been attempted.\n   */\n  processResponse?: (req: api.ServiceRequest,\n                    res: Response\u003cany\u003e,\n                    attempt: number) =\u003e Promise\u003capi.ResponseOutcome\u003e${ST}\n  /**\n   * If a fetch request fails this function gives you a chance to process\n   * that error before it's returned up the promise chain to the original caller.\n   */\n  processError?: (req: api.ServiceRequest,\n                  res: api.ResponseOutcome) =\u003e Promise\u003capi.ResponseOutcome\u003e${ST}\n  /**\n   * By default the authorization header name is \"Authorization\".\n   * This property allows you to override it.\n   * \n   * One place this can come up is where your API is under the same host as\n   * a website it powers. If the website has Basic Auth in place then some\n   * browsers will override your \"Authorization: Bearer \u003ctoken\u003e\" header with\n   * the Basic Auth value when calling your API. To counter this we can change\n   * the header, e.g.\n   * \n   *     authorizationHeader = \"X-Authorization\"\n   * \n   * The service must of course accept this alternative.\n   */\n  authorizationHeader?: string${ST}\n}\n```\n\n### Using generated Redux action creators\n\nYou can use the generated API client directly. However, if you pass `--redux` or `redux: true` to `openapi-client`, you will have generated Redux action creators to call your API (using a wrapper around `fetch`). The following example assumes that you're using `react-redux` to wrap action creators in `dispatch`. You also need to use for example `redux-thunk` as middleware to allow async actions. \n\nIn your component:\n\n```jsx\nimport React, { Component } from 'react';\nimport { connect } from 'react-redux';\nimport { bindActionCreators } from 'redux';\nimport functional from 'react-functional';\n\nimport { getPetById } from '../api-client/action/pet';\n\nconst Pet = ({ actions, pet }) =\u003e (\n  \u003cdiv\u003e\n    {pet.name}\n  \u003c/div\u003e\n)\n\n// Dispatch an action to get the pet when the component mounts. Here we're using 'react-functional', but this could also be done using the class componentDidMount method\nPet.componentDidMount = ({ actions }) =\u003e actions.getPetById(id);\n\nconst mapStateToProps = state =\u003e (\n  {\n    pet: getPet(state) // a function that gets \n  }\n);\n\nconst mapDispatchToProps = dispatch =\u003e (\n  {\n    actions: bindActionCreators({ getPetById }, dispatch)\n  }\n);\n\nexport default connect( mapStateToProps, mapDispatchToProps)(functional(Pet));\n```\n\nThe client can't generate your reducer for you as it doesn't know how merge the returned object into state, so you'll need to add a something to your reducer, such as:\n\n```jsx\nexport default function reducer(state = initialState, action) {\n  switch (action.type) {\n    case GET_PET_BY_ID_START:\n      return state.set('isFetching', true);\n    case GET_PET_BY_ID: // When we actually have a pet returned\n      if(!action.error){\n        return state.merge({\n          isFetching: false,\n          pet: action.payload,\n          error: null,\n        });\n      }\n      else{ // handle an error\n        return state.merge({\n          isFetching: false,\n          error: action.error,\n        });\n      }\n    default:\n      return state;\n  }\n}\n```\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmikestead%2Fopenapi-client","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fmikestead%2Fopenapi-client","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmikestead%2Fopenapi-client/lists"}