[
  {
    "path": ".editorconfig",
    "content": "# http://editorconfig.org\nroot = true\n\n[*]\nindent_style = space\nindent_size = 2\ncharset = utf-8\ntrim_trailing_whitespace = true\ninsert_final_newline = true\n\n[*.md]\ntrim_trailing_whitespace = false\n"
  },
  {
    "path": ".github/FUNDING.yml",
    "content": "github: anttiviljami\nopen_collective: openapi-stack\ncustom:\n  - https://buymeacoff.ee/anttiviljami\n"
  },
  {
    "path": ".github/workflows/ci.yml",
    "content": "name: CI\non:\n  push:\n    branches: [\"main\"]\n    tags: [\"*\"]\n  pull_request:\n    branches: [\"main\"]\n\npermissions:\n  id-token: write # Required for OIDC\n  contents: read\n\njobs:\n  test:\n    name: Test\n    strategy:\n      matrix:\n        axios_version:\n          - 0.25.0 # oldest supported\n          - 0.*.* # latest 0.x\n          - ^1.0.0 # latest 1.x\n          - latest\n    runs-on: ubuntu-latest\n    steps:\n      - uses: actions/checkout@v5\n      - uses: actions/setup-node@v6\n        with:\n          node-version: \"20\"\n      - run: npm ci\n      - run: npm install axios@${{ matrix.axios_version }} && npm why axios\n      - run: npm run lint\n      - run: npm test\n\n  publish:\n    name: Publish\n    runs-on: ubuntu-latest\n    if: startsWith(github.ref, 'refs/tags/')\n    needs:\n      - test\n    steps:\n      - uses: actions/checkout@v5\n      - uses: actions/setup-node@v6\n        with:\n          node-version: \"24\"\n          registry-url: https://registry.npmjs.org/\n      - run: npm ci\n      - run: npm publish\n"
  },
  {
    "path": ".github/workflows/codeql.yml",
    "content": "name: \"CodeQL\"\n\non:\n  push:\n    branches: [\"main\"]\n  pull_request:\n    branches: [\"main\"]\n  schedule:\n    - cron: \"26 21 * * 5\"\n\njobs:\n  analyze:\n    name: Analyze\n    runs-on: ubuntu-latest\n    permissions:\n      actions: read\n      contents: read\n      security-events: write\n\n    strategy:\n      fail-fast: false\n      matrix:\n        language: [javascript]\n\n    steps:\n      - name: Checkout\n        uses: actions/checkout@v3\n\n      - name: Initialize CodeQL\n        uses: github/codeql-action/init@v2\n        with:\n          languages: ${{ matrix.language }}\n          queries: +security-and-quality\n\n      - name: Autobuild\n        uses: github/codeql-action/autobuild@v2\n\n      - name: Perform CodeQL Analysis\n        uses: github/codeql-action/analyze@v2\n        with:\n          category: \"/language:${{ matrix.language }}\"\n"
  },
  {
    "path": ".gitignore",
    "content": "# build\n*.js\n*.js.map\n*.d.ts\n\n# include types\n!src/types/*.d.ts\n\n# include jest config\n!jest.config.js\n\n# npm\nnode_modules\nnpm_debug.log*\n"
  },
  {
    "path": ".husky/pre-commit",
    "content": "#!/usr/bin/env sh\n. \"$(dirname -- \"$0\")/_/husky.sh\"\n\nnpm run lint\nnpm test"
  },
  {
    "path": ".prettierignore",
    "content": "*.d.ts\n*.js\n"
  },
  {
    "path": ".prettierrc",
    "content": "{\n  \"parser\": \"typescript\",\n  \"arrowParens\": \"always\",\n  \"trailingComma\": \"all\",\n  \"singleQuote\": true,\n  \"printWidth\": 120\n}\n"
  },
  {
    "path": "CODE_OF_CONDUCT.md",
    "content": "# Contributor Covenant Code of Conduct\n\n## Our Pledge\n\nWe as members, contributors, and leaders pledge to make participation in our\ncommunity a harassment-free experience for everyone, regardless of age, body\nsize, visible or invisible disability, ethnicity, sex characteristics, gender\nidentity and expression, level of experience, education, socio-economic status,\nnationality, personal appearance, race, religion, or sexual identity\nand orientation.\n\nWe pledge to act and interact in ways that contribute to an open, welcoming,\ndiverse, inclusive, and healthy community.\n\n## Our Standards\n\nExamples of behavior that contributes to a positive environment for our\ncommunity include:\n\n* Demonstrating empathy and kindness toward other people\n* Being respectful of differing opinions, viewpoints, and experiences\n* Giving and gracefully accepting constructive feedback\n* Accepting responsibility and apologizing to those affected by our mistakes,\n  and learning from the experience\n* Focusing on what is best not just for us as individuals, but for the\n  overall community\n\nExamples of unacceptable behavior include:\n\n* The use of sexualized language or imagery, and sexual attention or\n  advances of any kind\n* Trolling, insulting or derogatory comments, and personal or political attacks\n* Public or private harassment\n* Publishing others' private information, such as a physical or email\n  address, without their explicit permission\n* Other conduct which could reasonably be considered inappropriate in a\n  professional setting\n\n## Enforcement Responsibilities\n\nCommunity leaders are responsible for clarifying and enforcing our standards of\nacceptable behavior and will take appropriate and fair corrective action in\nresponse to any behavior that they deem inappropriate, threatening, offensive,\nor harmful.\n\nCommunity leaders have the right and responsibility to remove, edit, or reject\ncomments, commits, code, wiki edits, issues, and other contributions that are\nnot aligned to this Code of Conduct, and will communicate reasons for moderation\ndecisions when appropriate.\n\n## Scope\n\nThis Code of Conduct applies within all community spaces, and also applies when\nan individual is officially representing the community in public spaces.\nExamples of representing our community include using an official e-mail address,\nposting via an official social media account, or acting as an appointed\nrepresentative at an online or offline event.\n\n## Enforcement\n\nInstances of abusive, harassing, or otherwise unacceptable behavior may be\nreported to the community leaders responsible for enforcement at\nviljami@viljami.io.\nAll complaints will be reviewed and investigated promptly and fairly.\n\nAll community leaders are obligated to respect the privacy and security of the\nreporter of any incident.\n\n## Enforcement Guidelines\n\nCommunity leaders will follow these Community Impact Guidelines in determining\nthe consequences for any action they deem in violation of this Code of Conduct:\n\n### 1. Correction\n\n**Community Impact**: Use of inappropriate language or other behavior deemed\nunprofessional or unwelcome in the community.\n\n**Consequence**: A private, written warning from community leaders, providing\nclarity around the nature of the violation and an explanation of why the\nbehavior was inappropriate. A public apology may be requested.\n\n### 2. Warning\n\n**Community Impact**: A violation through a single incident or series\nof actions.\n\n**Consequence**: A warning with consequences for continued behavior. No\ninteraction with the people involved, including unsolicited interaction with\nthose enforcing the Code of Conduct, for a specified period of time. This\nincludes avoiding interactions in community spaces as well as external channels\nlike social media. Violating these terms may lead to a temporary or\npermanent ban.\n\n### 3. Temporary Ban\n\n**Community Impact**: A serious violation of community standards, including\nsustained inappropriate behavior.\n\n**Consequence**: A temporary ban from any sort of interaction or public\ncommunication with the community for a specified period of time. No public or\nprivate interaction with the people involved, including unsolicited interaction\nwith those enforcing the Code of Conduct, is allowed during this period.\nViolating these terms may lead to a permanent ban.\n\n### 4. Permanent Ban\n\n**Community Impact**: Demonstrating a pattern of violation of community\nstandards, including sustained inappropriate behavior,  harassment of an\nindividual, or aggression toward or disparagement of classes of individuals.\n\n**Consequence**: A permanent ban from any sort of public interaction within\nthe community.\n\n## Attribution\n\nThis Code of Conduct is adapted from the [Contributor Covenant][homepage],\nversion 2.0, available at\nhttps://www.contributor-covenant.org/version/2/0/code_of_conduct.html.\n\nCommunity Impact Guidelines were inspired by [Mozilla's code of conduct\nenforcement ladder](https://github.com/mozilla/diversity).\n\n[homepage]: https://www.contributor-covenant.org\n\nFor answers to common questions about this code of conduct, see the FAQ at\nhttps://www.contributor-covenant.org/faq. Translations are available at\nhttps://www.contributor-covenant.org/translations.\n"
  },
  {
    "path": "CONTRIBUTING.md",
    "content": "# Contributing\n\nOpenAPI Client Axios is Free and Open Source Software. Issues and pull requests are more than welcome!\n"
  },
  {
    "path": "DOCS.md",
    "content": "# Documentation\n\nOpenAPI Client Axios documentation has moved to [openapistack.co](https://openapistack.co)\n\nSee: https://openapistack.co/docs/openapi-client-axios\n"
  },
  {
    "path": "LICENSE",
    "content": "The MIT License (MIT)\n\nCopyright (c) 2021 Viljami Kuosmanen\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the \"Software\"), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in\nall copies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\nTHE SOFTWARE.\n"
  },
  {
    "path": "README.md",
    "content": "<span id=\"npm--fix-hidden-readme-header\"></span>\n\n<h1 align=\"center\"><img alt=\"openapi-client-axios\" src=\"https://raw.githubusercontent.com/openapistack/openapi-client-axios/main/header.png\" style=\"max-width:50rem\"></h1>\n\n[![CI](https://github.com/openapistack/openapi-client-axios/workflows/CI/badge.svg)](https://github.com/openapistack/openapi-client-axios/actions?query=workflow%3ACI)\n[![License](http://img.shields.io/:license-mit-blue.svg)](https://github.com/openapistack/openapi-client-axios/blob/main/LICENSE)\n[![npm version](https://img.shields.io/npm/v/openapi-client-axios.svg)](https://www.npmjs.com/package/openapi-client-axios)\n[![npm downloads](https://img.shields.io/npm/dw/openapi-client-axios.svg)](https://www.npmjs.com/package/openapi-client-axios)\n[![bundle size](https://img.shields.io/bundlephobia/minzip/openapi-client-axios.svg?label=gzip%20bundle)](https://bundlephobia.com/package/openapi-client-axios)\n[![Libraries.io dependency status for latest release](https://img.shields.io/librariesio/release/npm/openapi-client-axios.svg)](https://www.npmjs.com/package/openapi-client-axios?activeTab=dependencies)\n![npm type definitions](https://img.shields.io/npm/types/openapi-client-axios.svg)\n[![Ask DeepWiki](https://deepwiki.com/badge.svg)](https://deepwiki.com/openapistack/openapi-client-axios)\n[![Buy me a coffee](https://img.shields.io/badge/donate-buy%20me%20a%20coffee-orange)](https://buymeacoff.ee/anttiviljami)\n\n<p align=\"center\">JavaScript client library for consuming OpenAPI-enabled APIs with <a href=\"https://github.com/axios/axios\" target=\"_blank\">axios</a>. Types included.</p>\n\n## Features\n\n- [x] Create API clients from [OpenAPI v3 definitions](https://github.com/OAI/OpenAPI-Specification)\n- [x] Client is configured in runtime. **No generated code!**\n- [x] Generate TypeScript definitions (.d.ts) for your APIs with full IntelliSense support\n- [x] Easy to use API to call API operations using JavaScript methods\n  - `client.getPet(1)`\n  - `client.searchPets()`\n  - `client.searchPets({ ids: [1, 2, 3] })`\n  - `client.updatePet(1, payload)`\n- [x] Built on top of the robust [axios](https://github.com/axios/axios) JavaScript library\n- [x] Isomorphic, works both in browser and Node.js\n\n## Documentation\n\n**New!** OpenAPI Client Axios documentation is now found on [openapistack.co](https://openapistack.co)\n\nhttps://openapistack.co/docs/openapi-client-axios/intro\n\n## Quick Start\n\n```\nnpm install --save axios openapi-client-axios\n```\n\n```\nyarn add axios openapi-client-axios\n```\n\nWith promises / CommonJS syntax:\n\n```javascript\nconst OpenAPIClientAxios = require('openapi-client-axios').default;\n\nconst api = new OpenAPIClientAxios({ definition: 'https://example.com/api/openapi.json' });\napi.init()\n  .then(client => client.getPetById(1))\n  .then(res => console.log('Here is pet id:1 from the api', res.data));\n```\n\nWith async-await / ES6 syntax:\n\n```javascript\nimport OpenAPIClientAxios from 'openapi-client-axios';\n\nconst api = new OpenAPIClientAxios({ definition: 'https://example.com/api/openapi.json' });\napi.init();\n\nasync function createPet() {\n  const client = await api.getClient();\n  const res = await client.createPet(null, { name: 'Garfield' });\n  console.log('Pet created', res.data);\n}\n```\n\n## Client\n\nOpenAPI Client Axios uses [operationIds](https://github.com/OAI/OpenAPI-Specification/blob/master/versions/3.0.0.md#operation-object)\nin OpenAPIv3 definitions to call API operations.\n\nAfter initializing `OpenAPIClientAxios`, an axios client instance extended with OpenAPI capabilities is exposed.\n\nExample:\n```javascript\nconst api = new OpenAPIClientAxios({ definition: 'https://example.com/api/openapi.json' });\napi.init().then((client) => {\n  client.updatePet(1, { age: 12 });\n});\n```\n\n`client` is an [axios instance](https://github.com/axios/axios#creating-an-instance) initialized with\nbaseURL from OpenAPI definitions and extended with extra operation methods for calling API operations.\n\nIt also has a reference to OpenAPIClientAxios at `client.api`\n\n## Operation methods\n\nOpenAPIClientAxios operation methods take 3 arguments:\n\n```javascript\nclient.operationId(parameters?, data?, config?)\n```\n\n### Parameters\n\nThe first argument is used to pass parameters available for the operation.\n\n```javascript\n// GET /pets/{petId}\nclient.getPet({ petId: 1 })\n```\n\nFor syntactic sugar purposes, you can also specify a single implicit parameter value, in which case OpenAPIClientAxios\nwill look for the first required parameter for the operation. Usually this is will be a path parameter.\n\n```javascript\n// GET /pets/{petId} - getPet\nclient.getPet(1)\n```\n\nAlternatively, you can explicitly specify parameters in array form. This method allows you to set custom parameters not defined\nin the OpenAPI spec.\n\n```javascript\n// GET /pets?search=Garfield - searchPets\nclient.searchPets([{ name: 'search', value: 'Garfield', in: 'query' }])\n```\n\nThe type of the parameters can be any of:\n- query\n- header\n- path\n- cookie\n\n### Data\n\nThe second argument is used to pass the requestPayload\n\n```javascript\n// PUT /pets/1 - updatePet\nclient.updatePet(1, { name: 'Odie' })\n```\n\nMore complex payloads, such as Node.js streams or FormData supported by Axios can be used.\n\nThe first argument can be set to null if there are no parameters required for the operation.\n\n```javascript\n// POST /pets - createPet\nclient.updatePet(null, { name: 'Garfield' })\n```\n\n### Config object\n\nThe last argument is the config object.\n\nThe config object is an [`AxiosRequestConfig`](https://github.com/axios/axios#request-config) object. You can use it to\noverride axios request config parameters, such as `headers`, `timeout`, `withCredentials` and many more.\n\n```javascript\n// POST /user - createUser\nclient.createUser(null, { user: 'admin', pass: '123' }, { headers: { 'x-api-key': 'secret' } });\n```\n\n## Paths Dictionary\n\nOpenAPI Client Axios also allows calling API operations via their path and HTTP\nmethod, using the paths dictionary.\n\nExample:\n\n```javascript\nclient.paths['/pets'].get(); // GET /pets, same as calling client.getPets()\nclient.paths['/pets'].post(); // POST /pets\nclient.paths['/pets/{petId}'].put(1); // PUT /pets/1\nclient.paths['/pets/{petId}/owner/{ownerId}'].get({ petId: 1, ownerId: 2 }) ; // GET /pets/1/owner/2\n```\n\nThis allows calling operation methods without using their operationIds, which\nmay be sometimes preferred.\n\n## Typesafe Clients\n\n![TypeScript IntelliSense](https://openapistack.co/assets/images/intellisense-b61ace10fd35746dd5bfefa977c0645e.gif)\n\n`openapi-client-axios` comes with a CLI command `openapicmd typegen` to generate Typescript types for type safety and code autocomplete.\n\n```\nnpx openapicmd typegen ./openapi.yaml > src/types/openapi.d.ts\n```\n\nThe output of `typegen` exports a type called `Client`, which can be used for instances created with `OpenAPIClientAxios`.\n\nBoth the `api.getClient()` and `api.init()` methods support passing in a Client type.\n\n```typescript\nimport { Client as PetStoreClient } from './client.d.ts';\n\nconst client = await api.init<PetStoreClient>();\nconst client = await api.getClient<PetStoreClient>();\n```\n\n`openapicmd typegen` supports using both local and remote URLs for OpenAPI definition files.\n\n```\n$ npx openapicmd typegen ./petstore.yaml\n$ npx openapicmd typegen https://petstore3.swagger.io/api/v3/openapi.json\n```\n\n## Commercial support\n\nFor assistance with openapi-client-axios in your company, reach out at support@openapistack.co.\n\n## Contributing\n\nOpenAPI Client Axios is Free and Open Source Software. Issues and pull requests are more than welcome!\n"
  },
  {
    "path": "jest.config.ts",
    "content": "import type { JestConfigWithTsJest } from 'ts-jest'\n\nconst jestConfig: JestConfigWithTsJest = {\n  testEnvironment: 'node',\n  testMatch: ['**/?(*.)+(spec|test).ts?(x)'],\n  transform: {\n    '^.+\\\\.[tj]s?$': [\n      'ts-jest',\n      {\n        useESM: true,\n      },\n    ],\n  },\n}\n\nexport default jestConfig"
  },
  {
    "path": "package.json",
    "content": "{\n  \"name\": \"openapi-client-axios\",\n  \"description\": \"JavaScript client library for consuming OpenAPI-enabled APIs with axios. Types included.\",\n  \"version\": \"7.9.0\",\n  \"license\": \"MIT\",\n  \"keywords\": [\n    \"openapi\",\n    \"swagger\",\n    \"client\",\n    \"axios\",\n    \"frontend\",\n    \"browser\",\n    \"mock\",\n    \"typescript\"\n  ],\n  \"author\": \"Viljami Kuosmanen <viljami@viljami.io>\",\n  \"funding\": \"https://github.com/sponsors/anttiviljami\",\n  \"homepage\": \"https://openapistack.co\",\n  \"repository\": {\n    \"type\": \"git\",\n    \"url\": \"git+https://github.com/openapistack/openapi-client-axios.git\"\n  },\n  \"bugs\": {\n    \"url\": \"https://github.com/openapistack/openapi-client-axios/issues\"\n  },\n  \"main\": \"index.js\",\n  \"types\": \"index.d.ts\",\n  \"files\": [\n    \"*.js\",\n    \"*.d.ts\",\n    \"*.map\",\n    \"**/*.js\",\n    \"**/*.d.ts\",\n    \"**/*.map\",\n    \"!*.test.*\",\n    \"!**/*.test.*\",\n    \"!__tests__/**\",\n    \"!src/**\",\n    \"!*.config.js\"\n  ],\n  \"peerDependencies\": {\n    \"axios\": \">=0.25.0\",\n    \"js-yaml\": \"^4.1.0\"\n  },\n  \"dependencies\": {\n    \"bath-es5\": \"^3.0.3\",\n    \"dereference-json-schema\": \"^0.2.1\",\n    \"openapi-types\": \"^12.1.3\"\n  },\n  \"devDependencies\": {\n    \"@types/jest\": \"^29.5.5\",\n    \"@types/js-yaml\": \"^4.0.5\",\n    \"@types/json-schema\": \"^7.0.6\",\n    \"axios\": \"^1.13.5\",\n    \"axios-mock-adapter\": \"^1.22.0\",\n    \"jest\": \"^29.7.0\",\n    \"json-schema\": \"^0.4.0\",\n    \"json-schema-deref-sync\": \"^0.14.0\",\n    \"msw\": \"^1.3.2\",\n    \"prettier\": \"^3.0.3\",\n    \"source-map-support\": \"^0.5.10\",\n    \"ts-jest\": \"^29.1.1\",\n    \"ts-node\": \"^10.9.1\",\n    \"typescript\": \"^4.5.5\"\n  },\n  \"scripts\": {\n    \"build\": \"tsc\",\n    \"watch-build\": \"tsc -w\",\n    \"prepare\": \"npm run build\",\n    \"test\": \"NODE_ENV=test jest\",\n    \"lint\": \"prettier --check src/**/*.ts __tests__/**/*.ts\",\n    \"lint:fix\": \"prettier --write src/**/*.ts __tests__/**/*.ts\"\n  },\n  \"gitHead\": \"6ea364b653a2264ddd2de4d2f1ddabc5cf3cbfd5\"\n}\n"
  },
  {
    "path": "src/__tests__/fixtures.ts",
    "content": "import { OpenAPIV3 } from 'openapi-types';\n\nexport const baseURL = 'http://localhost:8080';\nexport const baseURLAlternative = 'http://localhost:9090/';\nexport const baseURLWithVariable = 'http://{foo1}.localhost:9090/{foo2}/{foo3}/';\nexport const baseURLWithVariableResolved = 'http://bar1.localhost:9090/bar2a/bar3b/';\nexport const baseURLV2 = 'http://localhost:8080/v2';\n\nexport const responses: OpenAPIV3.ResponsesObject = {\n  200: { description: 'ok' },\n};\n\nexport const petId: OpenAPIV3.ParameterObject = {\n  name: 'petId',\n  in: 'path',\n  required: true,\n  schema: {\n    type: 'integer',\n  },\n};\n\nexport const petShopId: OpenAPIV3.ParameterObject = {\n  name: 'x-petshop-id',\n  in: 'header',\n  schema: {\n    type: 'string',\n  },\n};\n\nexport const ownerId: OpenAPIV3.ParameterObject = {\n  name: 'ownerId',\n  in: 'path',\n  required: true,\n  schema: {\n    type: 'integer',\n  },\n};\n\nexport const createDefinition = (overrides: Partial<OpenAPIV3.Document> = {}): OpenAPIV3.Document => ({\n  openapi: '3.0.0',\n  info: {\n    title: 'api',\n    version: '1.0.0',\n  },\n  servers: [],\n  paths: {},\n  ...overrides,\n});\n\nexport const definition: OpenAPIV3.Document = {\n  openapi: '3.0.0',\n  info: {\n    title: 'api',\n    version: '1.0.0',\n  },\n  servers: [\n    { url: baseURL },\n    {\n      url: baseURLAlternative,\n      description: 'Alternative server',\n    },\n    {\n      url: baseURLWithVariable,\n      description: 'server with variable baseURL',\n      variables: {\n        foo1: {\n          default: 'bar1',\n          enum: ['bar1', 'bar1a'],\n        },\n        foo2: {\n          default: 'bar2b',\n          enum: ['bar2a', 'bar2b'],\n        },\n        foo3: {\n          default: 'bar3a',\n          enum: ['bar3a', 'bar3b'],\n        },\n      },\n    },\n  ],\n  paths: {\n    '/pets': {\n      get: {\n        operationId: 'getPets',\n        responses: {\n          200: {\n            $ref: '#/components/responses/PetsListRes',\n          },\n        },\n        parameters: [\n          {\n            name: 'q',\n            in: 'query',\n            schema: {\n              type: 'array',\n              items: {\n                type: 'string',\n              },\n            },\n          },\n        ],\n      },\n      post: {\n        operationId: 'createPet',\n        responses: {\n          201: {\n            $ref: '#/components/responses/PetRes',\n          },\n        },\n      },\n    },\n    '/pets/{petId}': {\n      get: {\n        operationId: 'getPetById',\n        responses: {\n          200: {\n            $ref: '#/components/responses/PetRes',\n          },\n        },\n        parameters: [petShopId],\n      },\n      put: {\n        operationId: 'replacePetById',\n        responses: {\n          200: {\n            $ref: '#/components/responses/PetRes',\n          },\n        },\n      },\n      patch: {\n        operationId: 'updatePetById',\n        responses: {\n          200: {\n            $ref: '#/components/responses/PetRes',\n          },\n        },\n      },\n      delete: {\n        operationId: 'deletePetById',\n        responses: {\n          200: {\n            $ref: '#/components/responses/PetRes',\n          },\n        },\n      },\n      parameters: [petId],\n    },\n    '/pets/{petId}/owner': {\n      get: {\n        operationId: 'getOwnerByPetId',\n        responses,\n      },\n      parameters: [petId],\n    },\n    '/pets/{petId}/owner/{ownerId}': {\n      get: {\n        operationId: 'getPetOwner',\n        responses,\n      },\n      parameters: [petId, ownerId],\n    },\n    '/pets/meta': {\n      get: {\n        operationId: 'getPetsMeta',\n        responses,\n      },\n    },\n    '/pets/relative': {\n      servers: [{ url: baseURLV2 }],\n      get: {\n        operationId: 'getPetsRelative',\n        responses,\n      },\n    },\n  },\n  components: {\n    schemas: {\n      PetWithName: {\n        type: 'object',\n        properties: {\n          id: {\n            type: 'integer',\n            minimum: 1,\n          },\n          name: {\n            type: 'string',\n            example: 'Garfield',\n          },\n        },\n      },\n    },\n    responses: {\n      PetRes: {\n        description: 'ok',\n        content: {\n          'application/json': {\n            schema: {\n              $ref: '#/components/schemas/PetWithName',\n            },\n          },\n        },\n      },\n      PetsListRes: {\n        description: 'ok',\n        content: {\n          'application/json': {\n            schema: {\n              type: 'array',\n              items: {\n                $ref: '#/components/schemas/PetWithName',\n              },\n            },\n          },\n        },\n      },\n    },\n  },\n};\n"
  },
  {
    "path": "src/__tests__/resources/example-pet-api.openapi.json",
    "content": "{\n  \"openapi\": \"3.0.0\",\n  \"info\": {\n    \"title\": \"Example API\",\n    \"description\": \"Example CRUD API for pets\",\n    \"version\": \"1.0.0\"\n  },\n  \"tags\": [\n    {\n      \"name\": \"pets\",\n      \"description\": \"Pet operations\"\n    }\n  ],\n  \"servers\": [\n    {\n      \"url\": \"http://localhost:8080\"\n    }\n  ],\n  \"paths\": {\n    \"/pets\": {\n      \"get\": {\n        \"operationId\": \"getPets\",\n        \"summary\": \"List pets\",\n        \"description\": \"Returns all pets in database\",\n        \"tags\": [\n          \"pets\"\n        ],\n        \"responses\": {\n          \"200\": {\n            \"description\": \"List of pets in database\"\n          }\n        },\n        \"parameters\": [\n          {\n            \"name\": \"limit\",\n            \"in\": \"query\",\n            \"description\": \"Number of items to return\",\n            \"required\": false,\n            \"schema\": {\n              \"$ref\": \"#/components/schemas/QueryLimit\"\n            }\n          },\n          {\n            \"name\": \"offset\",\n            \"in\": \"query\",\n            \"description\": \"Starting offset for returning items\",\n            \"required\": false,\n            \"schema\": {\n              \"$ref\": \"#/components/schemas/QueryOffset\"\n            }\n          }\n        ]\n      },\n      \"post\": {\n        \"operationId\": \"createPet\",\n        \"summary\": \"Create a pet\",\n        \"description\": \"Crete a new pet into the database\",\n        \"tags\": [\n          \"pets\"\n        ],\n        \"responses\": {\n          \"201\": {\n            \"description\": \"Pet created succesfully\"\n          }\n        },\n        \"parameters\": [],\n        \"requestBody\": {\n          \"$ref\": \"#/components/requestBodies/PetPayload\"\n        }\n      }\n    },\n    \"/pets/{id}\": {\n      \"get\": {\n        \"operationId\": \"getPetById\",\n        \"summary\": \"Get a pet\",\n        \"description\": \"Returns a pet by its id in database\",\n        \"tags\": [\n          \"pets\"\n        ],\n        \"responses\": {\n          \"200\": {\n            \"description\": \"Pet object corresponding to id\"\n          },\n          \"404\": {\n            \"description\": \"Pet not found\"\n          }\n        },\n        \"parameters\": [\n          {\n            \"name\": \"id\",\n            \"in\": \"path\",\n            \"description\": \"Unique identifier for pet in database\",\n            \"required\": true,\n            \"schema\": {\n              \"$ref\": \"#/components/schemas/PetId\"\n            }\n          },\n          {\n            \"name\": \"x-petshop-id\",\n            \"in\": \"header\",\n            \"description\": \"Optional header parameter to pass petshop id\",\n            \"schema\": {\n              \"type\": \"string\",\n              \"example\": \"123\"\n            }\n          }\n        ]\n      },\n      \"put\": {\n        \"operationId\": \"replacePetById\",\n        \"summary\": \"Replace pet\",\n        \"description\": \"Replace an existing pet in the database\",\n        \"tags\": [\n          \"pets\"\n        ],\n        \"responses\": {\n          \"200\": {\n            \"description\": \"Pet replaced succesfully\"\n          },\n          \"404\": {\n            \"description\": \"Pet not found\"\n          }\n        },\n        \"parameters\": [\n          {\n            \"name\": \"id\",\n            \"in\": \"path\",\n            \"description\": \"Unique identifier for pet in database\",\n            \"required\": true,\n            \"schema\": {\n              \"$ref\": \"#/components/schemas/PetId\"\n            }\n          }\n        ],\n        \"requestBody\": {\n          \"$ref\": \"#/components/requestBodies/PetPayload\"\n        }\n      },\n      \"patch\": {\n        \"operationId\": \"updatePetById\",\n        \"summary\": \"Update pet\",\n        \"description\": \"Update an existing pet in the database\",\n        \"tags\": [\n          \"pets\"\n        ],\n        \"responses\": {\n          \"200\": {\n            \"description\": \"Pet updated succesfully\"\n          },\n          \"404\": {\n            \"description\": \"Pet not found\"\n          }\n        },\n        \"parameters\": [\n          {\n            \"name\": \"id\",\n            \"in\": \"path\",\n            \"description\": \"Unique identifier for pet in database\",\n            \"required\": true,\n            \"schema\": {\n              \"$ref\": \"#/components/schemas/PetId\"\n            }\n          }\n        ],\n        \"requestBody\": {\n          \"$ref\": \"#/components/requestBodies/PetPayload\"\n        }\n      },\n      \"delete\": {\n        \"operationId\": \"deletePetById\",\n        \"summary\": \"Delete a pet\",\n        \"description\": \"Deletes a pet by its id in database\",\n        \"tags\": [\n          \"pets\"\n        ],\n        \"responses\": {\n          \"200\": {\n            \"description\": \"Pet deleted succesfully\"\n          },\n          \"404\": {\n            \"description\": \"Pet not found\"\n          }\n        },\n        \"parameters\": [\n          {\n            \"name\": \"id\",\n            \"in\": \"path\",\n            \"description\": \"Unique identifier for pet in database\",\n            \"required\": true,\n            \"schema\": {\n              \"$ref\": \"#/components/schemas/PetId\"\n            }\n          }\n        ]\n      }\n    },\n    \"/pets/{id}/owner\": {\n      \"get\": {\n        \"operationId\": \"getOwnerByPetId\",\n        \"summary\": \"Get a pet's owner\",\n        \"description\": \"Get the owner for a pet\",\n        \"tags\": [\n          \"pets\"\n        ],\n        \"responses\": {\n          \"200\": {\n            \"description\": \"Human corresponding pet id\"\n          },\n          \"404\": {\n            \"description\": \"Human or pet not found\"\n          }\n        },\n        \"parameters\": [\n          {\n            \"name\": \"id\",\n            \"in\": \"path\",\n            \"description\": \"Unique identifier for pet in database\",\n            \"required\": true,\n            \"schema\": {\n              \"$ref\": \"#/components/schemas/PetId\"\n            }\n          }\n        ]\n      }\n    },\n    \"/pets/{petId}/owner/{ownerId}\": {\n      \"get\": {\n        \"operationId\": \"getPetOwner\",\n        \"summary\": \"Get owner by id\",\n        \"description\": \"Get the owner for a pet\",\n        \"tags\": [\n          \"pets\"\n        ],\n        \"parameters\": [\n          {\n            \"name\": \"petId\",\n            \"in\": \"path\",\n            \"description\": \"Unique identifier for pet in database\",\n            \"required\": true,\n            \"schema\": {\n              \"$ref\": \"#/components/schemas/PetId\"\n            }\n          },\n          {\n            \"name\": \"ownerId\",\n            \"in\": \"path\",\n            \"description\": \"Unique identifier for owner in database\",\n            \"required\": true,\n            \"schema\": {\n              \"$ref\": \"#/components/schemas/PetId\"\n            }\n          }\n        ],\n        \"responses\": {\n          \"200\": {\n            \"description\": \"Human corresponding owner id\"\n          },\n          \"404\": {\n            \"description\": \"Human or pet not found\"\n          }\n        }\n      }\n    },\n    \"/pets/meta\": {\n      \"get\": {\n        \"operationId\": \"getPetsMeta\",\n        \"summary\": \"Get pet metadata\",\n        \"description\": \"Returns a list of metadata about pets and their relations in the database\",\n        \"tags\": [\n          \"pets\"\n        ],\n        \"responses\": {\n          \"200\": {\n            \"description\": \"Metadata for pets\"\n          }\n        }\n      }\n    },\n    \"/pets/relative\": {\n      \"servers\": [\n        {\n          \"url\": \"baseURLV2\"\n        }\n      ],\n      \"get\": {\n        \"operationId\": \"getPetsRelative\",\n        \"summary\": \"Get pet metadata\",\n        \"description\": \"Returns a list of metadata about pets and their relations in the database\",\n        \"tags\": [\n          \"pets\"\n        ],\n        \"responses\": {\n          \"200\": {\n            \"description\": \"Metadata for pets\"\n          }\n        }\n      }\n    }\n  },\n  \"components\": {\n    \"schemas\": {\n      \"PetId\": {\n        \"description\": \"Unique identifier for pet in database\",\n        \"example\": 1,\n        \"title\": \"PetId\",\n        \"type\": \"integer\"\n      },\n      \"PetPayload\": {\n        \"type\": \"object\",\n        \"properties\": {\n          \"name\": {\n            \"description\": \"Name of the pet\",\n            \"example\": \"Garfield\",\n            \"title\": \"PetName\",\n            \"type\": \"string\"\n          }\n        },\n        \"additionalProperties\": false,\n        \"required\": [\n          \"name\"\n        ]\n      },\n      \"QueryLimit\": {\n        \"description\": \"Number of items to return\",\n        \"example\": 25,\n        \"title\": \"QueryLimit\",\n        \"type\": \"integer\"\n      },\n      \"QueryOffset\": {\n        \"description\": \"Starting offset for returning items\",\n        \"example\": 0,\n        \"title\": \"QueryOffset\",\n        \"type\": \"integer\",\n        \"minimum\": 0\n      }\n    },\n    \"requestBodies\": {\n      \"PetPayload\": {\n        \"description\": \"Request payload containing a pet object\",\n        \"content\": {\n          \"application/json\": {\n            \"schema\": {\n              \"$ref\": \"#/components/schemas/PetPayload\"\n            }\n          }\n        }\n      }\n    }\n  }\n}\n"
  },
  {
    "path": "src/__tests__/resources/example-pet-api.openapi.yml",
    "content": "openapi: 3.0.0\ninfo:\n  title: Example API\n  description: Example CRUD API for pets\n  version: 1.0.0\ntags:\n  - name: pets\n    description: Pet operations\nservers:\n  - url: http://localhost:8080\npaths:\n  /pets:\n    get:\n      operationId: getPets\n      summary: List pets\n      description: Returns all pets in database\n      tags:\n        - pets\n      responses:\n        '200':\n          description: List of pets in database\n      parameters:\n        - name: limit\n          in: query\n          description: Number of items to return\n          required: false\n          schema:\n            $ref: '#/components/schemas/QueryLimit'\n        - name: offset\n          in: query\n          description: Starting offset for returning items\n          required: false\n          schema:\n            $ref: '#/components/schemas/QueryOffset'\n    post:\n      operationId: createPet\n      summary: Create a pet\n      description: Crete a new pet into the database\n      tags:\n        - pets\n      responses:\n        '201':\n          description: Pet created succesfully\n      parameters: []\n      requestBody:\n        $ref: '#/components/requestBodies/PetPayload'\n  '/pets/{id}':\n    get:\n      operationId: getPetById\n      summary: Get a pet\n      description: Returns a pet by its id in database\n      tags:\n        - pets\n      responses:\n        '200':\n          description: Pet object corresponding to id\n        '404':\n          description: Pet not found\n      parameters:\n        - name: id\n          in: path\n          description: Unique identifier for pet in database\n          required: true\n          schema:\n            $ref: '#/components/schemas/PetId'\n        - name: x-petshop-id\n          in: header\n          description: Optional header parameter to pass petshop id\n          schema:\n            type: string\n            example: \"123\"\n    put:\n      operationId: replacePetById\n      summary: Replace pet\n      description: Replace an existing pet in the database\n      tags:\n        - pets\n      responses:\n        '200':\n          description: Pet replaced succesfully\n        '404':\n          description: Pet not found\n      parameters:\n        - name: id\n          in: path\n          description: Unique identifier for pet in database\n          required: true\n          schema:\n            $ref: '#/components/schemas/PetId'\n      requestBody:\n        $ref: '#/components/requestBodies/PetPayload'\n    patch:\n      operationId: updatePetById\n      summary: Update pet\n      description: Update an existing pet in the database\n      tags:\n        - pets\n      responses:\n        '200':\n          description: Pet updated succesfully\n        '404':\n          description: Pet not found\n      parameters:\n        - name: id\n          in: path\n          description: Unique identifier for pet in database\n          required: true\n          schema:\n            $ref: '#/components/schemas/PetId'\n      requestBody:\n        $ref: '#/components/requestBodies/PetPayload'\n    delete:\n      operationId: deletePetById\n      summary: Delete a pet\n      description: Deletes a pet by its id in database\n      tags:\n        - pets\n      responses:\n        '200':\n          description: Pet deleted succesfully\n        '404':\n          description: Pet not found\n      parameters:\n        - name: id\n          in: path\n          description: Unique identifier for pet in database\n          required: true\n          schema:\n            $ref: '#/components/schemas/PetId'\n  '/pets/{id}/owner':\n    get:\n      operationId: getOwnerByPetId\n      summary: Get a pet's owner\n      description: Get the owner for a pet\n      tags:\n        - pets\n      responses:\n        '200':\n          description: Human corresponding pet id\n        '404':\n          description: Human or pet not found\n      parameters:\n        - name: id\n          in: path\n          description: Unique identifier for pet in database\n          required: true\n          schema:\n            $ref: '#/components/schemas/PetId'\n  '/pets/{petId}/owner/{ownerId}':\n    get:\n      operationId: getPetOwner\n      summary: Get owner by id\n      description: Get the owner for a pet\n      tags:\n        - pets\n      parameters:\n        - name: petId\n          in: path\n          description: Unique identifier for pet in database\n          required: true\n          schema:\n            $ref: '#/components/schemas/PetId'\n        - name: ownerId\n          in: path\n          description: Unique identifier for owner in database\n          required: true\n          schema:\n            $ref: '#/components/schemas/PetId'\n      responses:\n        '200':\n          description: Human corresponding owner id\n        '404':\n          description: Human or pet not found\n  /pets/meta:\n    get:\n      operationId: getPetsMeta\n      summary: Get pet metadata\n      description: Returns a list of metadata about pets and their relations in the database\n      tags:\n        - pets\n      responses:\n        '200':\n          description: Metadata for pets\n  /pets/relative:\n    servers: [{ url: baseURLV2 }]\n    get:\n      operationId: 'getPetsRelative'\n      summary: Get pet metadata\n      description: Returns a list of metadata about pets and their relations in the database\n      tags:\n        - pets\n      responses:\n        '200':\n          description: Metadata for pets\ncomponents:\n  schemas:\n    PetId:\n      description: Unique identifier for pet in database\n      example: 1\n      title: PetId\n      type: integer\n    PetPayload:\n      type: object\n      properties:\n        name:\n          description: Name of the pet\n          example: Garfield\n          title: PetName\n          type: string\n      additionalProperties: false\n      required:\n        - name\n    QueryLimit:\n      description: Number of items to return\n      example: 25\n      title: QueryLimit\n      type: integer\n    QueryOffset:\n      description: Starting offset for returning items\n      example: 0\n      title: QueryOffset\n      type: integer\n      minimum: 0\n  requestBodies:\n    PetPayload:\n      description: 'Request payload containing a pet object'\n      content:\n        application/json:\n          schema:\n            $ref: '#/components/schemas/PetPayload'\n"
  },
  {
    "path": "src/client.test.ts",
    "content": "import path from 'path';\nimport fs from 'fs';\nimport { rest } from 'msw'\nimport { setupServer } from 'msw/node'\nimport MockAdapter from 'axios-mock-adapter';\nimport { definition, baseURL, baseURLV2, baseURLAlternative, baseURLWithVariableResolved, createDefinition } from './__tests__/fixtures';\nimport { OpenAPIClientAxios, OpenAPIClient } from './client';\nimport axios, { AxiosResponse } from 'axios';\n\nconst testsDir = path.join(__dirname, '.', '__tests__');\n\nconst examplePetAPIJSON = path.join(testsDir, 'resources', 'example-pet-api.openapi.json');\nconst examplePetAPIYAML = path.join(testsDir, 'resources', 'example-pet-api.openapi.yml');\n\nconst server = setupServer(\n  rest.get('http://localhost/example-pet-api.openapi.json', (_req, res, ctx) => {  \n    return res(ctx.body(fs.readFileSync(examplePetAPIJSON)), ctx.set('Content-Type', 'application/json'));\n  }),\n  rest.get('http://localhost/example-pet-api.openapi.yml', (_req, res, ctx) => {  \n    return res(ctx.body(fs.readFileSync(examplePetAPIYAML)), ctx.set('Content-Type', 'application/yaml'));\n  })\n);\n\nbeforeAll(() => server.listen());\n\ndescribe('OpenAPIClientAxios', () => {\n  const checkHasOperationMethods = (client: OpenAPIClient) => {\n    expect(client).toHaveProperty('getPets');\n    expect(client).toHaveProperty('createPet');\n    expect(client).toHaveProperty('getPetById');\n    expect(client).toHaveProperty('replacePetById');\n    expect(client).toHaveProperty('updatePetById');\n    expect(client).toHaveProperty('deletePetById');\n    expect(client).toHaveProperty('getOwnerByPetId');\n    expect(client).toHaveProperty('getPetOwner');\n    expect(client).toHaveProperty('getPetsMeta');\n    expect(client).toHaveProperty('getPetsRelative');\n  };\n\n  describe('init', () => {\n    test('can be initalised with a valid OpenAPI document as JS Object', async () => {\n      const api = new OpenAPIClientAxios({ definition });\n      await api.init();\n      expect(api.initialized).toEqual(true);\n      expect(api.client.api).toBe(api);\n      checkHasOperationMethods(api.client);\n    });\n\n    test('operation method names are configurable', async () => {\n      const api = new OpenAPIClientAxios({\n        definition,\n        transformOperationName: (operation) => operation.toUpperCase(),\n      });\n      await api.init();\n\n      expect(api.client).toHaveProperty('GETPETS');\n      expect(api.client).toHaveProperty('CREATEPET');\n      expect(api.client).toHaveProperty('GETPETBYID');\n    });\n\n    test('dereferences the input document', async () => {\n      const api = new OpenAPIClientAxios({ definition });\n      await api.init();\n      expect(JSON.stringify(api.inputDocument)).toMatch('$ref');\n      expect(JSON.stringify(api.definition)).not.toMatch('$ref');\n    });\n\n    test('can be initialized using a valid YAML file', async () => {\n      const api = new OpenAPIClientAxios({ definition: 'http://localhost/example-pet-api.openapi.yml' });\n      await api.init();\n      expect(api.initialized).toEqual(true);\n      expect(api.client.api).toBe(api);\n      checkHasOperationMethods(api.client);\n    });\n\n    test('can be initialized using a valid JSON file', async () => {\n      const api = new OpenAPIClientAxios({ definition: 'http://localhost/example-pet-api.openapi.json' });\n      await api.init();\n      expect(api.initialized).toEqual(true);\n      expect(api.client.api).toBe(api);\n      checkHasOperationMethods(api.client);\n    });\n\n    test('can be initialized using alternative server using index', async () => {\n      const api = new OpenAPIClientAxios({ definition, withServer: 1 });\n      await api.init();\n      expect(api.getBaseURL()).toEqual(baseURLAlternative);\n      expect(api.client.api).toBe(api);\n      checkHasOperationMethods(api.client);\n    });\n\n    test('can be initialized using alternative server using description', async () => {\n      const api = new OpenAPIClientAxios({ definition, withServer: 'Alternative server' });\n      await api.init();\n      expect(api.getBaseURL()).toEqual(baseURLAlternative);\n      expect(api.client.api).toBe(api);\n      checkHasOperationMethods(api.client);\n    });\n\n    test('can be initialized using alternative server with variable in baseURL', async () => {\n      const api = new OpenAPIClientAxios({\n        definition,\n        withServer: 2,\n        baseURLVariables: { foo2: 'bar2a', foo3: 1 },\n      });\n      await api.init();\n      expect(api.getBaseURL()).toEqual(baseURLWithVariableResolved);\n      expect(api.client.api).toBe(api);\n      checkHasOperationMethods(api.client);\n    });\n\n    test('can be initialized using alternative server using object', async () => {\n      const url = 'http://examplde.com/v5';\n      const api = new OpenAPIClientAxios({ definition, withServer: { url } });\n      await api.init();\n      expect(api.getBaseURL()).toEqual(url);\n      expect(api.client.api).toBe(api);\n      checkHasOperationMethods(api.client);\n    });\n\n    test('can be initialized using default baseUrl resolver', async () => {\n      const api = new OpenAPIClientAxios({ definition });\n      await api.init();\n      expect(api.getBaseURL()).toEqual(baseURL);\n      expect(api.client.api).toBe(api);\n      checkHasOperationMethods(api.client);\n    });\n  });\n\n  describe('withServer', () => {\n    test('can set default server as object', async () => {\n      const api = new OpenAPIClientAxios({ definition });\n      await api.init();\n      expect(api.getBaseURL()).toEqual(baseURL);\n      const newServer = {\n        url: 'http://example.com/apiv4',\n        description: 'example api v4',\n      };\n      api.withServer(newServer);\n      expect(api.getBaseURL()).toEqual(newServer.url);\n    });\n\n    test('can set default server by using description', async () => {\n      const api = new OpenAPIClientAxios({ definition });\n      await api.init();\n      expect(api.getBaseURL()).toEqual(baseURL);\n      const newServer = 'Alternative server';\n      api.withServer(newServer);\n      expect(api.getBaseURL()).toEqual(baseURLAlternative);\n    });\n\n    test('can set default server by index', async () => {\n      const api = new OpenAPIClientAxios({ definition });\n      await api.init();\n      expect(api.getBaseURL()).toEqual(baseURL);\n      const newServer = 1;\n      api.withServer(newServer);\n      expect(api.getBaseURL()).toEqual(baseURLAlternative);\n    });\n\n    test('can set default server with variables', async () => {\n      const api = new OpenAPIClientAxios({ definition });\n      await api.init();\n      expect(api.getBaseURL()).toEqual(baseURL);\n      const newServer = 2;\n      const newServerVars = { foo2: 'bar2a', foo3: 1 };\n      api.withServer(newServer, newServerVars);\n      expect(api.getBaseURL()).toEqual(baseURLWithVariableResolved);\n    });\n  });\n\n  describe('initSync', () => {\n    test('can be initialized synchronously with a valid OpenAPI document as JS Object', () => {\n      const api = new OpenAPIClientAxios({ definition });\n      api.initSync();\n      expect(api.initialized).toEqual(true);\n      expect(api.client.api).toBe(api);\n      checkHasOperationMethods(api.client);\n    });\n\n    test('dereferences the input document', () => {\n      const api = new OpenAPIClientAxios({ definition });\n      api.initSync();\n      expect(JSON.stringify(api.inputDocument)).toMatch('$ref');\n      expect(JSON.stringify(api.definition)).not.toMatch('$ref');\n    });\n\n    test('throws an error when initialized using a URL', () => {\n      const api = new OpenAPIClientAxios({ definition: '/example-pet-api.openapi.json' });\n      expect(api.initSync).toThrowError();\n    });\n  });\n\n  describe('client', () => {\n    test('has set default baseURL to the first server in config', async () => {\n      const api = new OpenAPIClientAxios({ definition });\n      const client = await api.init();\n      expect(client.defaults.baseURL).toBe(baseURL);\n    });\n\n    test('can override axios default config', async () => {\n      const api = new OpenAPIClientAxios({\n        definition,\n        axiosConfigDefaults: { maxRedirects: 1, withCredentials: true },\n      });\n      const client = await api.init();\n      expect(client.defaults.maxRedirects).toBe(1);\n      expect(client.defaults.withCredentials).toBe(true);\n    });\n\n    test('request defaults from user-provided axios instance are not modified', async () => {\n      const userRequestTransformer = (data: object, headers?: object) => data;\n      const userResponseTransformer = (data: object) => data;\n      const userParamsSerializer = () => \"\";\n      const userAdapter = () => new Promise<AxiosResponse<any, any>>(() => ({}));\n      const userOnUploadProgress = () => {};\n      const userOnDownloadProgress = () => {};\n      const userValidateStatus = () => true;\n      const userCancelToken = new axios.CancelToken(() => {});\n\n      const userAxiosInstance = axios.create({\n        url: '/hello',\n        method: 'post',\n        baseURL: 'https://some-domain.com/api',\n        transformRequest: userRequestTransformer,\n        transformResponse: userResponseTransformer,\n        headers: {'X-Requested-With': 'fake'},\n        params: {\n          ID: 123456789,\n        },\n        paramsSerializer: userParamsSerializer,\n        data: {\n          hello: 'world',\n        },\n        timeout: 1234,\n        withCredentials: true,\n        adapter: userAdapter,\n        auth: {\n          username: 'fake',\n          password: 'fakepassword'\n        },\n        responseType: 'stream',\n        responseEncoding: 'fakeEncoding',\n        xsrfCookieName: 'HELLO-WORLD',\n        xsrfHeaderName: 'HELLO-WORLD-2',\n        onUploadProgress: userOnUploadProgress,\n        onDownloadProgress: userOnDownloadProgress,\n        maxContentLength: 1234,\n        maxBodyLength: 5678,\n        validateStatus: userValidateStatus,\n        maxRedirects: 99,\n        socketPath: '/fake/path/example',\n        proxy: {\n          host: '1.2.3.4',\n          port: 9876,\n          auth: {\n            username: 'anotherFakeUsername',\n            password: 'anotherFakePassword'\n          }\n        },\n        cancelToken: userCancelToken,\n        decompress: false\n      });\n\n      const api = new OpenAPIClientAxios({\n        definition,\n        axiosInstance: userAxiosInstance,\n      });\n      const client = await api.init();\n      const d = client.defaults;\n\n      expect(d.url).toBe('/hello');\n      expect(d.method).toBe('post');\n      expect(d.baseURL).toBe('https://some-domain.com/api');\n      expect(d.transformRequest).toBe(userRequestTransformer);\n      expect(d.transformResponse).toBe(userResponseTransformer);\n      expect((d.headers as unknown as Record<string, unknown>)['X-Requested-With']).toBe('fake');\n      expect(d.params.ID).toBe(123456789);\n      expect(d.paramsSerializer).toBe(userParamsSerializer);\n      expect(d.data.hello).toBe('world');\n      expect(d.timeout).toBe(1234);\n      expect(d.withCredentials).toBe(true);\n      expect(d.adapter).toBe(userAdapter);\n      expect(d.auth).toStrictEqual({\n        username: 'fake',\n        password: 'fakepassword'\n      }),\n      expect(d.responseType).toBe('stream');\n      expect(d.responseEncoding).toBe('fakeEncoding');\n      expect(d.xsrfCookieName).toBe('HELLO-WORLD');\n      expect(d.xsrfHeaderName).toBe('HELLO-WORLD-2');\n      expect(d.onUploadProgress).toBe(userOnUploadProgress);\n      expect(d.onDownloadProgress).toBe(userOnDownloadProgress);\n      expect(d.maxContentLength).toBe(1234);\n      expect(d.maxBodyLength).toBe(5678);\n      expect(d.validateStatus).toBe(userValidateStatus);\n      expect(d.maxRedirects).toBe(99);\n      expect(d.socketPath).toBe('/fake/path/example');\n      expect(d.proxy).toStrictEqual({\n          host: '1.2.3.4',\n          port: 9876,\n          auth: {\n            username: 'anotherFakeUsername',\n            password: 'anotherFakePassword'\n          },\n      });\n      expect(d.cancelToken).toBe(userCancelToken);\n      expect(d.decompress).toBe(false);\n    });\n  });\n\n  describe('operation methods', () => {\n    test('getPets() calls GET /pets', async () => {\n      const api = new OpenAPIClientAxios({ definition });\n      const client = await api.init();\n\n      const mock = new MockAdapter(api.client);\n      const mockResponse = [{ id: 1, name: 'Garfield' }];\n      const mockHandler = jest.fn((config) => [200, mockResponse]);\n      mock.onGet('/pets').reply((config) => mockHandler(config));\n\n      const res = await client.getPets();\n      expect(res.data).toEqual(mockResponse);\n      expect(mockHandler).toBeCalled();\n    });\n\n    test(\"getPets({ q: 'cats' }) calls GET /pets?q=cats\", async () => {\n      const api = new OpenAPIClientAxios({ definition });\n      const client = await api.init();\n\n      const mock = new MockAdapter(api.client);\n      const mockResponse = [{ id: 1, name: 'Garfield' }];\n      const mockHandler = jest.fn((config) => [200, mockResponse]);\n      mock.onGet('/pets').reply((config) => mockHandler(config));\n\n      const params = { q: 'cats ' };\n      const res = await client.getPets(params);\n\n      expect(res.data).toEqual(mockResponse);\n      expect(mockHandler).toBeCalled();\n      const mockContext = mockHandler.mock.calls[mockHandler.mock.calls.length - 1][0];\n      expect(mockContext.params).toEqual(params);\n    });\n\n    test(\"getPets({ q: ['cats', 'dogs'] }) calls GET /pets?q=cats&q=dogs\", async () => {\n      const api = new OpenAPIClientAxios({ definition });\n      const client = await api.init();\n\n      const mock = new MockAdapter(api.client);\n      const mockResponse = [{ id: 1, name: 'Garfield' }];\n      const mockHandler = jest.fn((config) => [200, mockResponse]);\n      mock.onGet('/pets').reply((config) => mockHandler(config));\n\n      const params = { q: ['cats', 'dogs'] };\n      const res = await client.getPets(params);\n      expect(res.data).toEqual(mockResponse);\n      expect(mockHandler).toBeCalled();\n      const mockContext = mockHandler.mock.calls[mockHandler.mock.calls.length - 1][0];\n      expect(mockContext.params).toEqual(params);\n    });\n\n    test('getPetById({ petId: 1 }) calls GET /pets/1', async () => {\n      const api = new OpenAPIClientAxios({ definition });\n      const client = await api.init();\n\n      const mock = new MockAdapter(api.client);\n      const mockResponse = { id: 1, name: 'Garfield' };\n      const mockHandler = jest.fn((config) => [200, mockResponse]);\n      mock.onGet('/pets/1').reply((config) => mockHandler(config));\n\n      const res = await client.getPetById({ petId: 1 });\n      expect(res.data).toEqual(mockResponse);\n      expect(mockHandler).toBeCalled();\n    });\n\n    test('getPetById(1) calls GET /pets/1', async () => {\n      const api = new OpenAPIClientAxios({ definition });\n      const client = await api.init();\n\n      const mock = new MockAdapter(api.client);\n      const mockResponse = { id: 1, name: 'Garfield' };\n      const mockHandler = jest.fn((config) => [200, mockResponse]);\n      mock.onGet('/pets/1').reply((config) => mockHandler(config));\n\n      const res = await client.getPetById(1);\n      expect(res.data).toEqual(mockResponse);\n      expect(mockHandler).toBeCalled();\n    });\n\n    test('getPetById({ petId: 1 }) calls GET /pets/1', async () => {\n      const api = new OpenAPIClientAxios({ definition });\n      const client = await api.init();\n\n      const mock = new MockAdapter(api.client);\n      const mockResponse = { id: 1, name: 'Garfield' };\n      const mockHandler = jest.fn((config) => [200, mockResponse]);\n      mock.onGet('/pets/1').reply((config) => mockHandler(config));\n\n      const res = await client.getPetById({ petId: 1 });\n      expect(res.data).toEqual(mockResponse);\n      expect(mockHandler).toBeCalled();\n    });\n\n    test('getPetById({ petId: 1, \"x-petshop-id\": \"test-shop\" }) calls GET /pets/1 with request header', async () => {\n      const api = new OpenAPIClientAxios({ definition });\n      const client = await api.init();\n\n      const mock = new MockAdapter(api.client);\n      const mockResponse = { id: 1, name: 'Garfield' };\n      const mockHandler = jest.fn((config) => [200, mockResponse]);\n      mock.onGet('/pets/1').reply((config) => mockHandler(config));\n\n      const res = await client.getPetById({ petId: 1, 'x-petshop-id': 'test-shop' });\n      expect(res.data).toEqual(mockResponse);\n      expect(mockHandler).toBeCalledWith(expect.objectContaining({ headers: expect.objectContaining({ 'x-petshop-id': 'test-shop' }) }))\n    });\n\n    test('getPetById({ petId: 1, \"x-petshop-id\": \"test-shop\" }) calls GET /pets/1 with request header and extern config', async () => {\n      const api = new OpenAPIClientAxios({ definition });\n      const client = await api.init();\n\n      const mock = new MockAdapter(api.client);\n      const mockResponse = { id: 1, name: 'Garfield' };\n      const mockHandler = jest.fn((config) => [200, mockResponse]);\n      mock.onGet('/pets/1').reply((config) => mockHandler(config));\n\n      const config = { headers: { authorization: 'Bearer abc' } };\n      const res = await client.getPetById({ petId: 1, 'x-petshop-id': 'test-shop' }, undefined, config);\n      expect(res.data).toEqual(mockResponse);\n      expect(mockHandler).toBeCalledWith(\n        expect.objectContaining({\n          headers: expect.objectContaining({ 'x-petshop-id': 'test-shop', authorization: 'Bearer abc' }),\n        }),\n      );\n    });\n\n    test('getPetById([{ name: \"petId\", value: \"1\", in: \"path\" }]) calls GET /pets/1', async () => {\n      const api = new OpenAPIClientAxios({ definition });\n      const client = await api.init();\n\n      const mock = new MockAdapter(api.client);\n      const mockResponse = { id: 1, name: 'Garfield' };\n      const mockHandler = jest.fn((config) => [200, mockResponse]);\n      mock.onGet('/pets/1').reply((config) => mockHandler(config));\n\n      const res = await client.getPetById([{ name: 'petId', value: '1', in: 'path' }]);\n      expect(res.data).toEqual(mockResponse);\n      expect(mockHandler).toBeCalled();\n    });\n\n    test('getPetById([{ name: \"petId\", value: \"1\", in: \"path\" }, { name: \"new\", value: \"2\", in: \"query\" }]) calls GET /pets/1?new=2', async () => {\n      const api = new OpenAPIClientAxios({ definition });\n      const client = await api.init();\n\n      const mock = new MockAdapter(api.client);\n      const mockResponse = { id: 1, name: 'Garfield' };\n      const mockHandler = jest.fn((config) => [200, mockResponse]);\n      mock.onGet('/pets/1').reply((config) => mockHandler(config));\n\n      const res = await client.getPetById([{ name: 'petId', value: '1', in: 'path' }]);\n      expect(res.data).toEqual(mockResponse);\n      expect(mockHandler).toBeCalled();\n    });\n\n    test('createPet(pet) calls POST /pets with JSON payload', async () => {\n      const api = new OpenAPIClientAxios({ definition });\n      const client = await api.init();\n\n      const mock = new MockAdapter(api.client);\n      const pet = { name: 'Garfield' };\n      const mockResponse = { id: 1, ...pet };\n      const mockHandler = jest.fn((config) => [201, mockResponse]);\n      mock.onPost('/pets').reply((config) => mockHandler(config));\n\n      const res = await client.createPet(null, pet);\n      expect(res.data).toEqual(mockResponse);\n      expect(mockHandler).toBeCalled();\n      const mockContext = mockHandler.mock.calls[mockHandler.mock.calls.length - 1][0];\n      expect(mockContext.data).toEqual(JSON.stringify(pet));\n    });\n\n    test('replacePetById(1, pet) calls PUT /pets/1 with JSON payload', async () => {\n      const api = new OpenAPIClientAxios({ definition });\n      const client = await api.init();\n\n      const mock = new MockAdapter(api.client);\n      const pet = { id: 1, name: 'Garfield' };\n      const mockResponse = pet;\n      const mockHandler = jest.fn((config) => [200, mockResponse]);\n      mock.onPut('/pets/1').reply((config) => mockHandler(config));\n\n      const res = await client.replacePetById(1, pet);\n      expect(res.data).toEqual(mockResponse);\n      expect(mockHandler).toBeCalled();\n      const mockContext = mockHandler.mock.calls[mockHandler.mock.calls.length - 1][0];\n      expect(mockContext.data).toEqual(JSON.stringify(pet));\n    });\n\n    test('deletePetById(1) calls DELETE /pets/1', async () => {\n      const api = new OpenAPIClientAxios({ definition });\n      const client = await api.init();\n\n      const mock = new MockAdapter(api.client);\n      const mockResponse = { id: 1, name: 'Garfield' };\n      const mockHandler = jest.fn((config) => [200, mockResponse]);\n      mock.onDelete('/pets/1').reply((config) => mockHandler(config));\n\n      const res = await client.deletePetById(1);\n      expect(res.data).toEqual(mockResponse);\n      expect(mockHandler).toBeCalled();\n    });\n\n    test('getOwnerByPetId(1) calls GET /pets/1/owner', async () => {\n      const api = new OpenAPIClientAxios({ definition });\n      const client = await api.init();\n\n      const mock = new MockAdapter(api.client);\n      const mockResponse = { name: 'Jon' };\n      const mockHandler = jest.fn((config) => [200, mockResponse]);\n      mock.onGet('/pets/1/owner').reply((config) => mockHandler(config));\n\n      const res = await client.getOwnerByPetId(1);\n      expect(res.data).toEqual(mockResponse);\n      expect(mockHandler).toBeCalled();\n    });\n\n    test('getPetOwner([1, 2]) calls GET /pets/1/owner/2', async () => {\n      const api = new OpenAPIClientAxios({ definition });\n      const client = await api.init();\n\n      const mock = new MockAdapter(api.client);\n      const mockResponse = { name: 'Jon' };\n      const mockHandler = jest.fn((config) => [200, mockResponse]);\n      mock.onGet('/pets/1/owner/2').reply((config) => mockHandler(config));\n\n      const res = await client.getPetOwner({ petId: 1, ownerId: 2 });\n      expect(res.data).toEqual(mockResponse);\n      expect(mockHandler).toBeCalled();\n    });\n\n    test('getPetOwner({ petId: 1, ownerId: 2 }) calls GET /pets/1/owner/2', async () => {\n      const api = new OpenAPIClientAxios({ definition });\n      const client = await api.init();\n\n      const mock = new MockAdapter(api.client);\n      const mockResponse = { name: 'Jon' };\n      const mockHandler = jest.fn((config) => [200, mockResponse]);\n      mock.onGet('/pets/1/owner/2').reply((config) => mockHandler(config));\n\n      const res = await client.getPetOwner({ petId: 1, ownerId: 2 });\n      expect(res.data).toEqual(mockResponse);\n      expect(mockHandler).toBeCalled();\n    });\n\n    test('getPetsMeta() calls GET /pets/meta', async () => {\n      const api = new OpenAPIClientAxios({ definition });\n      const client = await api.init();\n\n      const mock = new MockAdapter(api.client);\n      const mockResponse = { totalPets: 10 };\n      const mockHandler = jest.fn((config) => [200, mockResponse]);\n      mock.onGet('/pets/meta').reply((config) => mockHandler(config));\n\n      const res = await client.getPetsMeta();\n      expect(res.data).toEqual(mockResponse);\n      expect(mockHandler).toBeCalled();\n    });\n\n    test('getPetsRelative() calls GET /v2/pets/relative', async () => {\n      const api = new OpenAPIClientAxios({ definition });\n      const client = await api.init();\n\n      const mock = new MockAdapter(api.client);\n      const mockHandler = jest.fn((config) => [200, config.baseURL]);\n      mock.onGet('/pets/relative').reply((config) => mockHandler(config));\n\n      const res = await client.getPetsRelative();\n      expect(res.data).toEqual(baseURLV2);\n      expect(mockHandler).toBeCalled();\n    });\n  });\n\n  describe('paths dictionary', () => {\n    test(`paths['/pets'].get() calls GET /pets`, async () => {\n      const api = new OpenAPIClientAxios({ definition });\n      const client = await api.init();\n\n      const mock = new MockAdapter(api.client);\n      const mockResponse = [{ id: 1, name: 'Garfield' }];\n      const mockHandler = jest.fn((config) => [200, mockResponse]);\n      mock.onGet('/pets').reply((config) => mockHandler(config));\n\n      const res = await client.paths['/pets'].get();\n      expect(res.data).toEqual(mockResponse);\n      expect(mockHandler).toBeCalled();\n    });\n\n    test(`paths['/pets/{petId}'].get(1) calls GET /pets/1`, async () => {\n      const api = new OpenAPIClientAxios({ definition });\n      const client = await api.init();\n\n      const mock = new MockAdapter(api.client);\n      const mockResponse = { id: 1, name: 'Garfield' };\n      const mockHandler = jest.fn((config) => [200, mockResponse]);\n      mock.onGet('/pets/1').reply((config) => mockHandler(config));\n\n      const res = await client.paths['/pets/{petId}'].get(1);\n      expect(res.data).toEqual(mockResponse);\n      expect(mockHandler).toBeCalled();\n    });\n\n    test(`paths['/pets'].post() calls POST /pets`, async () => {\n      const api = new OpenAPIClientAxios({ definition });\n      const client = await api.init();\n\n      const mock = new MockAdapter(api.client);\n      const pet = { name: 'Garfield' };\n      const mockResponse = { id: 1, ...pet };\n      const mockHandler = jest.fn((config) => [201, mockResponse]);\n      mock.onPost('/pets').reply((config) => mockHandler(config));\n\n      const res = await client.paths['/pets'].post(null, pet);\n      expect(res.data).toEqual(mockResponse);\n      expect(mockHandler).toBeCalled();\n      const mockContext = mockHandler.mock.calls[mockHandler.mock.calls.length - 1][0];\n      expect(mockContext.data).toEqual(JSON.stringify(pet));\n    });\n\n    test(`paths['/pets/{petId}'].put(1) calls PUT /pets/1`, async () => {\n      const api = new OpenAPIClientAxios({ definition });\n      const client = await api.init();\n\n      const mock = new MockAdapter(api.client);\n      const pet = { id: 1, name: 'Garfield' };\n      const mockResponse = pet;\n      const mockHandler = jest.fn((config) => [200, mockResponse]);\n      mock.onPut('/pets/1').reply((config) => mockHandler(config));\n\n      const res = await client.paths['/pets/{petId}'].put(1, pet);\n      expect(res.data).toEqual(mockResponse);\n      expect(mockHandler).toBeCalled();\n      const mockContext = mockHandler.mock.calls[mockHandler.mock.calls.length - 1][0];\n      expect(mockContext.data).toEqual(JSON.stringify(pet));\n    });\n\n    test(`paths['/pets/{petId}'].delete(1) calls DELETE /pets/1`, async () => {\n      const api = new OpenAPIClientAxios({ definition });\n      const client = await api.init();\n\n      const mock = new MockAdapter(api.client);\n      const mockResponse = { id: 1, name: 'Garfield' };\n      const mockHandler = jest.fn((config) => [200, mockResponse]);\n      mock.onDelete('/pets/1').reply((config) => mockHandler(config));\n\n      const res = await client.paths['/pets/{petId}'].delete(1);\n      expect(res.data).toEqual(mockResponse);\n      expect(mockHandler).toBeCalled();\n    });\n\n    test(`paths['/pets/{petId}/owner/{ownerId}'].get({ petId: 1, ownerId: 2 }) calls GET /pets/1/owner/2`, async () => {\n      const api = new OpenAPIClientAxios({ definition });\n      const client = await api.init();\n\n      const mock = new MockAdapter(api.client);\n      const mockResponse = { name: 'Jon' };\n      const mockHandler = jest.fn((config) => [200, mockResponse]);\n      mock.onGet('/pets/1/owner/2').reply((config) => mockHandler(config));\n\n      const res = await client.paths['/pets/{petId}/owner/{ownerId}'].get({ petId: 1, ownerId: 2 });\n      expect(res.data).toEqual(mockResponse);\n      expect(mockHandler).toBeCalled();\n    });\n  });\n\n  describe('getRequestConfigForOperation()', () => {\n    test('getPets() calls GET /pets', async () => {\n      const api = new OpenAPIClientAxios({ definition });\n      const client = await api.init();\n      const config = api.getRequestConfigForOperation('getPets', []);\n\n      expect(config.method).toEqual('get');\n      expect(config.path).toEqual('/pets');\n    });\n\n    test('getPets({ q: \"cat\" }) calls GET /pets?q=cat', async () => {\n      const api = new OpenAPIClientAxios({ definition });\n      const client = await api.init();\n      const config = api.getRequestConfigForOperation('getPets', [{ q: 'cat' }]);\n\n      expect(config.method).toEqual('get');\n      expect(config.path).toEqual('/pets');\n      expect(config.url).toMatch('/pets?q=cat');\n      expect(config.query).toEqual({ q: 'cat' });\n      expect(config.queryString).toEqual('q=cat');\n    });\n\n    test('getPets({ q: [\"cat\"] }) calls GET /pets?q=cat', async () => {\n      const api = new OpenAPIClientAxios({ definition });\n      const client = await api.init();\n      const config = api.getRequestConfigForOperation('getPets', [{ q: ['cat'] }]);\n\n      expect(config.method).toEqual('get');\n      expect(config.path).toEqual('/pets');\n      expect(config.url).toMatch('/pets?q=cat');\n      expect(config.query).toEqual({ q: ['cat'] });\n      expect(config.queryString).toEqual('q=cat');\n    });\n\n    test('getPetById({ petId: 1 }) calls GET /pets/1', async () => {\n      const api = new OpenAPIClientAxios({ definition });\n      const client = await api.init();\n      const config = api.getRequestConfigForOperation('getPetById', [{ petId: 1 }]);\n\n      expect(config.method).toEqual('get');\n      expect(config.path).toEqual('/pets/1');\n      expect(config.pathParams).toEqual({ petId: '1' });\n    });\n\n    test('getPetById(1) calls GET /pets/1', async () => {\n      const api = new OpenAPIClientAxios({ definition });\n      const client = await api.init();\n      const config = api.getRequestConfigForOperation('getPetById', [1]);\n\n      expect(config.method).toEqual('get');\n      expect(config.path).toEqual('/pets/1');\n      expect(config.pathParams).toEqual({ petId: '1' });\n    });\n\n    test('createPet(null, pet) calls POST /pets with JSON payload', async () => {\n      const api = new OpenAPIClientAxios({ definition });\n      const client = await api.init();\n      const pet = { name: 'Garfield' };\n      const config = api.getRequestConfigForOperation('createPet', [null, pet]);\n\n      expect(config.method).toEqual('post');\n      expect(config.path).toEqual('/pets');\n      expect(config.payload).toEqual(pet);\n    });\n\n    test('replacePetById(1, pet) calls PUT /pets/1 with JSON payload', async () => {\n      const api = new OpenAPIClientAxios({ definition });\n      const client = await api.init();\n      const pet = { id: 1, name: 'Garfield' };\n      const config = api.getRequestConfigForOperation('replacePetById', [1, pet]);\n\n      expect(config.method).toEqual('put');\n      expect(config.path).toEqual('/pets/1');\n      expect(config.pathParams).toEqual({ petId: '1' });\n      expect(config.payload).toEqual(pet);\n    });\n\n    test('deletePetById(1) calls DELETE /pets/1', async () => {\n      const api = new OpenAPIClientAxios({ definition });\n      const client = await api.init();\n      const config = api.getRequestConfigForOperation('deletePetById', [1]);\n\n      expect(config.method).toEqual('delete');\n      expect(config.path).toEqual('/pets/1');\n      expect(config.pathParams).toEqual({ petId: '1' });\n    });\n\n    test('getOwnerByPetId(1) calls GET /pets/1/owner', async () => {\n      const api = new OpenAPIClientAxios({ definition });\n      const client = await api.init();\n      const config = api.getRequestConfigForOperation('getOwnerByPetId', [1]);\n\n      expect(config.method).toEqual('get');\n      expect(config.path).toEqual('/pets/1/owner');\n      expect(config.pathParams).toEqual({ petId: '1' });\n    });\n\n    test('getPetOwner({ petId: 1, ownerId: 2 }) calls GET /pets/1/owner/2', async () => {\n      const api = new OpenAPIClientAxios({ definition });\n      const client = await api.init();\n      const config = api.getRequestConfigForOperation('getPetOwner', [{ petId: 1, ownerId: 2 }]);\n\n      expect(config.method).toEqual('get');\n      expect(config.path).toEqual('/pets/1/owner/2');\n      expect(config.pathParams).toEqual({ petId: '1', ownerId: '2' });\n    });\n\n    test('getPetsMeta() calls GET /pets/meta', async () => {\n      const api = new OpenAPIClientAxios({ definition });\n      const client = await api.init();\n      const config = api.getRequestConfigForOperation('getPetsMeta', []);\n\n      expect(config.method).toEqual('get');\n      expect(config.path).toEqual('/pets/meta');\n    });\n\n    test('should url encode path parameters', async () => {\n      const api = new OpenAPIClientAxios({ definition: createDefinition({\n        paths: {\n          '/discounts/{name}': {\n            get: {\n              operationId: 'getDiscount',\n              parameters: [{ name: 'name', in: 'path', required: true, schema: { type: 'string' } }],\n              responses: { '200': { description: 'ok' } } },\n            }\n          }\n      })});\n      const client = await api.init();\n      const config = api.getRequestConfigForOperation('getDiscount', ['20% / 30% off']);\n      expect(config.path).toEqual('/discounts/20%25%20%2F%2030%25%20off');\n    });\n  });\n\n  describe('query parameter array serialization', () => {\n    test('array query param with default style (form, explode: true) serializes as repeated params', async () => {\n      const api = new OpenAPIClientAxios({ definition: createDefinition({\n        paths: {\n          '/items': {\n            get: {\n              operationId: 'getItems',\n              parameters: [{\n                name: 'id',\n                in: 'query',\n                schema: { type: 'array', items: { type: 'integer' } },\n                // default is style: 'form', explode: true\n              }],\n              responses: { '200': { description: 'ok' } }\n            }\n          }\n        }\n      })});\n      await api.init();\n      const config = api.getRequestConfigForOperation('getItems', [{ id: [3, 4, 5] }]);\n      expect(config.queryString).toEqual('id=3&id=4&id=5');\n    });\n\n    test('array query param with style: form, explode: false serializes as comma-separated', async () => {\n      const api = new OpenAPIClientAxios({ definition: createDefinition({\n        paths: {\n          '/items': {\n            get: {\n              operationId: 'getItems',\n              parameters: [{\n                name: 'id',\n                in: 'query',\n                schema: { type: 'array', items: { type: 'integer' } },\n                style: 'form',\n                explode: false\n              }],\n              responses: { '200': { description: 'ok' } }\n            }\n          }\n        }\n      })});\n      await api.init();\n      const config = api.getRequestConfigForOperation('getItems', [{ id: [3, 4, 5] }]);\n      expect(config.queryString).toEqual('id=3,4,5');\n    });\n\n    test('array query param with style: spaceDelimited serializes as space-separated', async () => {\n      const api = new OpenAPIClientAxios({ definition: createDefinition({\n        paths: {\n          '/items': {\n            get: {\n              operationId: 'getItems',\n              parameters: [{\n                name: 'id',\n                in: 'query',\n                schema: { type: 'array', items: { type: 'integer' } },\n                style: 'spaceDelimited',\n                explode: false\n              }],\n              responses: { '200': { description: 'ok' } }\n            }\n          }\n        }\n      })});\n      await api.init();\n      const config = api.getRequestConfigForOperation('getItems', [{ id: [3, 4, 5] }]);\n      expect(config.queryString).toEqual('id=3%204%205');\n    });\n\n    test('array query param with style: pipeDelimited serializes as pipe-separated', async () => {\n      const api = new OpenAPIClientAxios({ definition: createDefinition({\n        paths: {\n          '/items': {\n            get: {\n              operationId: 'getItems',\n              parameters: [{\n                name: 'id',\n                in: 'query',\n                schema: { type: 'array', items: { type: 'integer' } },\n                style: 'pipeDelimited',\n                explode: false\n              }],\n              responses: { '200': { description: 'ok' } }\n            }\n          }\n        }\n      })});\n      await api.init();\n      const config = api.getRequestConfigForOperation('getItems', [{ id: [3, 4, 5] }]);\n      expect(config.queryString).toEqual('id=3%7C4%7C5');\n    });\n\n    test('object query param with style: deepObject serializes with bracket notation', async () => {\n      const api = new OpenAPIClientAxios({ definition: createDefinition({\n        paths: {\n          '/users': {\n            get: {\n              operationId: 'getUsers',\n              parameters: [{\n                name: 'filter',\n                in: 'query',\n                schema: { type: 'object' },\n                style: 'deepObject',\n                explode: true\n              }],\n              responses: { '200': { description: 'ok' } }\n            }\n          }\n        }\n      })});\n      await api.init();\n      const config = api.getRequestConfigForOperation('getUsers', [{ filter: { role: 'admin', firstName: 'Alex' } } as any]);\n      expect(config.queryString).toMatch(/filter\\[role\\]=admin/);\n      expect(config.queryString).toMatch(/filter\\[firstName\\]=Alex/);\n    });\n\n    test('object query param with style: form, explode: true serializes as flat params', async () => {\n      const api = new OpenAPIClientAxios({ definition: createDefinition({\n        paths: {\n          '/users': {\n            get: {\n              operationId: 'getUsers',\n              parameters: [{\n                name: 'filter',\n                in: 'query',\n                schema: { type: 'object' },\n                style: 'form',\n                explode: true\n              }],\n              responses: { '200': { description: 'ok' } }\n            }\n          }\n        }\n      })});\n      await api.init();\n      const config = api.getRequestConfigForOperation('getUsers', [{ filter: { role: 'admin', firstName: 'Alex' } } as any]);\n      expect(config.queryString).toMatch(/role=admin/);\n      expect(config.queryString).toMatch(/firstName=Alex/);\n    });\n\n    test('object query param with style: form, explode: false serializes as comma-separated key-value pairs', async () => {\n      const api = new OpenAPIClientAxios({ definition: createDefinition({\n        paths: {\n          '/users': {\n            get: {\n              operationId: 'getUsers',\n              parameters: [{\n                name: 'filter',\n                in: 'query',\n                schema: { type: 'object' },\n                style: 'form',\n                explode: false\n              }],\n              responses: { '200': { description: 'ok' } }\n            }\n          }\n        }\n      })});\n      await api.init();\n      const config = api.getRequestConfigForOperation('getUsers', [{ filter: { role: 'admin', firstName: 'Alex' } } as any]);\n      expect(config.queryString).toMatch(/filter=role,admin,firstName,Alex/);\n    });\n\n    test('array of strings with special characters is properly encoded', async () => {\n      const api = new OpenAPIClientAxios({ definition: createDefinition({\n        paths: {\n          '/items': {\n            get: {\n              operationId: 'getItems',\n              parameters: [{\n                name: 'tags',\n                in: 'query',\n                schema: { type: 'array', items: { type: 'string' } },\n                style: 'form',\n                explode: true\n              }],\n              responses: { '200': { description: 'ok' } }\n            }\n          }\n        }\n      })});\n      await api.init();\n      const config = api.getRequestConfigForOperation('getItems', [{ tags: ['foo bar', 'baz&qux'] }]);\n      expect(config.queryString).toEqual('tags=foo%20bar&tags=baz%26qux');\n    });\n  });\n\n  describe('axios methods', () => {\n    test(\"get('/pets') calls GET /pets\", async () => {\n      const api = new OpenAPIClientAxios({ definition });\n      const client = await api.init();\n\n      const mock = new MockAdapter(api.client);\n      const mockResponse = [{ id: 1, name: 'Garfield' }];\n      const mockHandler = jest.fn((config) => [200, mockResponse]);\n      mock.onGet('/pets').reply((config) => mockHandler(config));\n\n      const res = await client.get('/pets');\n      expect(res.data).toEqual(mockResponse);\n      expect(mockHandler).toBeCalled();\n    });\n\n    test(\"({ method: 'get', url: '/pets' }) calls GET /pets\", async () => {\n      const api = new OpenAPIClientAxios({ definition });\n      const client = await api.init();\n\n      const mock = new MockAdapter(api.client);\n      const mockResponse = [{ id: 1, name: 'Garfield' }];\n      const mockHandler = jest.fn((config) => [200, mockResponse]);\n      mock.onGet('/pets').reply((config) => mockHandler(config));\n\n      const res = await client({ method: 'get', url: '/pets' });\n      expect(res.data).toEqual(mockResponse);\n      expect(mockHandler).toBeCalled();\n    });\n  });\n\n  describe('transforms', () => {\n    test('transformOperationName', async () => {\n      const api = new OpenAPIClientAxios({\n        definition,\n        transformOperationName: (operationName) => `${operationName}V1`,\n      });\n      const client = await api.init();\n\n      const mock = new MockAdapter(api.client);\n      const mockResponse = { name: 'Jon' };\n      const mockHandler = jest.fn((config) => [200, mockResponse]);\n      mock.onGet('/pets/1/owner/2').reply((config) => mockHandler(config));\n\n      const res = await client.getPetOwnerV1({ petId: 1, ownerId: 2 });\n      expect(res.data).toEqual(mockResponse);\n      expect(mockHandler).toBeCalled();\n    });\n  });\n\n  test('transformOperationMethod', async () => {\n    const api = new OpenAPIClientAxios({\n      definition,\n      transformOperationMethod: (operationMethod) => {\n        return (params: any, body, config) => {\n          params['petId'] = 1;\n          params['ownerId'] = 2;\n          return operationMethod(params, body, config);\n        };\n      },\n    });\n    const client = await api.init();\n\n    const mock = new MockAdapter(api.client);\n    const mockResponse = { name: 'Jon' };\n    const mockHandler = jest.fn((config) => [200, mockResponse]);\n    mock.onGet('/pets/1/owner/2').reply((config) => mockHandler(config));\n\n    const res = await client.getPetOwner({});\n    expect(res.data).toEqual(mockResponse);\n    expect(mockHandler).toBeCalled();\n  });\n\n  test('transformOperationMethod based on operation', async () => {\n    const api = new OpenAPIClientAxios({\n      definition,\n      transformOperationMethod: (operationMethod, operation) => {\n        return (params: any, body, config) => {\n          if (operation.operationId === 'getPetOwner') {\n            params['petId'] = 1;\n            params['ownerId'] = 2;\n          }\n          return operationMethod(params, body, config);\n        };\n      },\n    });\n    const client = await api.init();\n\n    const mock = new MockAdapter(api.client);\n    const mockResponse = { name: 'Jon' };\n    const mockHandler = jest.fn((config) => [200, mockResponse]);\n    mock.onGet('/pets/1/owner/2').reply((config) => mockHandler(config));\n\n    const res = await client.getPetOwner({});\n    expect(res.data).toEqual(mockResponse);\n    expect(mockHandler).toBeCalled();\n  });\n});\n"
  },
  {
    "path": "src/client.ts",
    "content": "import axios, { AxiosInstance, AxiosRequestConfig, AxiosRequestHeaders, AxiosResponse, Method } from 'axios';\nimport bath from 'bath-es5';\nimport { dereferenceSync } from 'dereference-json-schema';\n\nimport {\n  Document,\n  Operation,\n  UnknownOperationMethod,\n  OperationMethodArguments,\n  UnknownOperationMethods,\n  RequestConfig,\n  ParamType,\n  HttpMethod,\n  UnknownPathsDictionary,\n  Server,\n  ParameterObject,\n} from './types/client';\nimport { serializeQueryParameter } from './query-serializer';\n\n/**\n * OpenAPIClient is an AxiosInstance extended with operation methods\n */\nexport type OpenAPIClient<\n  OperationMethods = UnknownOperationMethods,\n  PathsDictionary = UnknownPathsDictionary,\n> = AxiosInstance &\n  OperationMethods & {\n    api: OpenAPIClientAxios;\n    paths: PathsDictionary;\n  };\n\n/**\n * By default OpenAPIClient will use axios as request runner. You can register a different runner,\n * in case you want to switch over from axios.\n */\nexport declare type Runner = {\n  runRequest: RunRequestFunc;\n  context?: UnknownContext;\n};\n\n/**\n * Context to be injected into Runner.runRequest\n */\nexport declare type UnknownContext = Record<string, unknown>;\n\n/**\n * Type for runRequest function. It allows extending/switching from axios to another method of running http requests.\n */\nexport declare type RunRequestFunc = (\n  axiosConfig: AxiosRequestConfig,\n  operation: Operation,\n  context?: UnknownContext,\n) => Promise<AxiosResponse>;\n\nconst DefaultRunnerKey = 'default';\n\nexport type OpenAPIClientAxiosOptions = {\n  definition: Document | string;\n  quick?: boolean;\n  withServer?: number | string | Server;\n  baseURLVariables?: { [key: string]: string | number };\n  applyMethodCommonHeaders?: boolean;\n  transformOperationName?: (operation: string) => string;\n  transformOperationMethod?: (\n    operationMethod: UnknownOperationMethod,\n    operationToTransform: Operation,\n  ) => UnknownOperationMethod;\n  axiosRunner?: (axiosConfig: AxiosRequestConfig) => Promise<AxiosResponse>;\n  axiosConfigDefaults?: AxiosRequestConfig;\n} & ({\n  axiosConfigDefaults?: AxiosRequestConfig;\n  axiosInstance?: never;\n} | {\n  axiosConfigDefaults?: never;\n  axiosInstance?: AxiosInstance;\n});\n\n/**\n * Main class and the default export of the 'openapi-client-axios' module\n *\n * @export\n * @class OpenAPIClientAxios\n */\nexport class OpenAPIClientAxios {\n  public document: Document;\n  public inputDocument: Document | string;\n  public definition: Document;\n\n  public quick: boolean;\n\n  public initialized: boolean;\n  public instance: any;\n\n  public axiosConfigDefaults: AxiosRequestConfig;\n\n  private defaultServer: number | string | Server;\n  private baseURLVariables: { [key: string]: string | number };\n  private applyMethodCommonHeaders: boolean;\n\n  private transformOperationName: (operation: string) => string;\n  private transformOperationMethod: (\n    operationMethod: UnknownOperationMethod,\n    operationToTransform: Operation,\n  ) => UnknownOperationMethod;\n\n  // maps operationId to Runner\n  private runners: Record<string, Runner>;\n\n  /**\n   * Creates an instance of OpenAPIClientAxios.\n   *\n   * @param opts - constructor options\n   * @param {Document | string} opts.definition - the OpenAPI definition, file path or Document object\n   * @param {boolean} opts.quick - quick mode, skips validation and doesn't guarantee document is unchanged\n   * @param {boolean} opts.applyMethodCommonHeaders Should method (patch / post / put / etc.) specific default headers (from axios.defaults.headers.{method}) be applied to operation methods?\n   * @param {boolean} opts.axiosConfigDefaults - default axios config for the instance\n   * @param {boolean} opts.axiosInstance - axios instance to use\n   * @memberof OpenAPIClientAxios\n   */\n  constructor(opts: OpenAPIClientAxiosOptions) {\n    this.inputDocument = opts.definition;\n    this.quick = opts.quick ?? false;\n    this.axiosConfigDefaults = opts.axiosConfigDefaults ?? {};\n    this.instance = opts.axiosInstance;\n    this.defaultServer = opts.withServer ?? 0;\n    this.baseURLVariables = opts.baseURLVariables ?? {};\n    this.applyMethodCommonHeaders = opts.applyMethodCommonHeaders ?? false;\n    this.transformOperationName = opts.transformOperationName ?? ((operationId: string) => operationId);\n    this.transformOperationMethod =\n      opts.transformOperationMethod ?? ((operationMethod: UnknownOperationMethod) => operationMethod);\n    this.runners = {\n      [DefaultRunnerKey]: {\n        runRequest: opts.axiosRunner ?? ((axiosConfig: AxiosRequestConfig) => this.client.request(axiosConfig)),\n      },\n    };\n  }\n\n  /**\n   * Returns the instance of OpenAPIClient\n   *\n   * @readonly\n   * @type {OpenAPIClient}\n   * @memberof OpenAPIClientAxios\n   */\n  get client() {\n    return this.instance as OpenAPIClient;\n  }\n\n  /**\n   * Returns the instance of OpenAPIClient\n   *\n   * @returns\n   * @memberof OpenAPIClientAxios\n   */\n  public getClient = async <Client = OpenAPIClient>(): Promise<Client> => {\n    if (!this.initialized) {\n      return this.init<Client>();\n    }\n    return this.instance as Client;\n  };\n\n  public withServer(server: number | string | Server, variables: { [key: string]: string | number } = {}) {\n    this.defaultServer = server;\n    this.baseURLVariables = variables;\n  }\n\n  /**\n   * Initializes OpenAPIClientAxios and creates a member axios client instance\n   *\n   * The init() method should be called right after creating a new instance of OpenAPIClientAxios\n   *\n   * @returns AxiosInstance\n   * @memberof OpenAPIClientAxios\n   */\n  public init = async <Client = OpenAPIClient>(): Promise<Client> => {\n    await this.loadDocument();\n\n    // dereference the document into definition\n    this.definition = dereferenceSync(this.document) as Document;\n\n    // create axios instance\n    this.instance = this.createAxiosInstance();\n\n    // we are now initialized\n    this.initialized = true;\n    return this.instance as Client;\n  };\n\n  /**\n   * Loads document from inputDocument\n   *\n   * Supports loading from a string (url) or an object (json)\n   *\n   * @memberof OpenAPIClientAxios\n   */\n  public async loadDocument() {\n    if (typeof this.inputDocument === 'object') {\n      this.document = this.inputDocument;\n    } else {\n      // create temporary instance to get the document\n      const client = this.getAxiosInstance();\n\n      // load the document\n      const documentRes = await client.get(this.inputDocument);\n\n      // set document\n      if (typeof documentRes.data === 'object') {\n        // json response\n        this.document = documentRes.data;\n      } else if (typeof documentRes.data === 'string' && documentRes.headers['content-type']?.match(/ya?ml/)) {\n        // yaml response\n        const yaml = await import('js-yaml');\n        this.document = yaml.load(documentRes.data) as Document;\n      } else {\n        const err = new Error(`Invalid response fetching OpenAPI definition: ${documentRes}`) as any;\n        err.response = documentRes;\n        throw err;\n      }\n    }\n\n    return this.document;\n  }\n\n  /**\n   * Synchronous version of .init()\n   *\n   * Note: Only works when the input definition is a valid OpenAPI v3 object (URLs are not supported)\n   *\n   * @memberof OpenAPIClientAxios\n   */\n  public initSync = <Client = OpenAPIClient>(): Client => {\n    if (typeof this.inputDocument !== 'object') {\n      throw new Error(`.initSync() can't be called with a non-object definition. Please use .init()`);\n    }\n\n    // set document\n    this.document = this.inputDocument;\n\n    // dereference the document into definition\n    this.definition = dereferenceSync(this.document) as Document;\n\n    // create axios instance\n    this.instance = this.createAxiosInstance();\n\n    // we are now initialized\n    this.initialized = true;\n    return this.instance as Client;\n  };\n\n  /**\n   * Creates a new axios instance, if necessary, and returns it\n   */\n  public getAxiosInstance = (): AxiosInstance => {\n    let instance = this.instance;\n    if (!instance) {\n      instance = axios.create(this.axiosConfigDefaults) as OpenAPIClient;\n    }\n    return instance;\n  };\n\n  /**\n   * Creates a new axios instance, extends it and returns it\n   *\n   * @memberof OpenAPIClientAxios\n   */\n  public createAxiosInstance = <Client = OpenAPIClient>(): Client => {\n    // create axios instance\n    const instance = this.getAxiosInstance() as OpenAPIClient;\n\n    // set baseURL to the one found in the definition servers (if not set in axios defaults)\n    const baseURL = this.getBaseURL();\n    if (baseURL && !instance.defaults.baseURL) {\n      instance.defaults.baseURL = baseURL;\n    }\n\n    // create methods for operationIds\n    const operations = this.getOperations();\n    for (const operation of operations) {\n      const { operationId } = operation;\n      if (operationId) {\n        instance[this.transformOperationName(operationId)] = this.createOperationMethod(operation);\n      }\n    }\n\n    // create paths dictionary\n    // Example: api.paths['/pets/{id}'].get({ id: 1 });\n    instance.paths = {};\n    for (const path in this.definition.paths) {\n      if (this.definition.paths[path]) {\n        if (!instance.paths[path]) {\n          instance.paths[path] = {};\n        }\n        const methods = this.definition.paths[path];\n        for (const m in methods) {\n          if (methods[m as HttpMethod] && Object.values(HttpMethod).includes(m as HttpMethod)) {\n            const method = m as HttpMethod;\n            const operation = this.getOperations().find((op) => op.method === method && op.path === path);\n            instance.paths[path][method] = this.createOperationMethod(operation);\n          }\n        }\n      }\n    }\n\n    // add reference to parent class instance\n    instance.api = this;\n    return instance as any as Client;\n  };\n\n  /**\n   * Gets the API baseurl defined in the first OpenAPI specification servers property\n   *\n   * @returns string\n   * @memberof OpenAPIClientAxios\n   */\n  public getBaseURL = (operation?: Operation): string | undefined => {\n    if (!this.definition) {\n      return undefined;\n    }\n    if (operation) {\n      if (typeof operation === 'string') {\n        operation = this.getOperation(operation);\n      }\n      if (operation.servers && operation.servers[0]) {\n        return operation.servers[0].url;\n      }\n    }\n\n    // get the target server from this.defaultServer\n    let targetServer;\n    if (typeof this.defaultServer === 'number') {\n      if (this.definition.servers && this.definition.servers[this.defaultServer]) {\n        targetServer = this.definition.servers[this.defaultServer];\n      }\n    } else if (typeof this.defaultServer === 'string') {\n      for (const server of this.definition.servers) {\n        if (server.description === this.defaultServer) {\n          targetServer = server;\n          break;\n        }\n      }\n    } else if (this.defaultServer.url) {\n      targetServer = this.defaultServer;\n    }\n\n    // if no targetServer is found, return undefined\n    if (!targetServer) {\n      return undefined;\n    }\n\n    const baseURL = targetServer.url;\n    const baseURLVariableSet = targetServer.variables;\n\n    // get baseURL var names\n    const baseURLBuilder = bath(baseURL);\n\n    // if there are no variables to resolve: return baseURL as is\n    if (!baseURLBuilder.names.length) {\n      return baseURL;\n    }\n\n    // object to place variables resolved from this.baseURLVariables\n    const baseURLVariablesResolved: { [key: string]: string } = {};\n\n    // step through names and assign value from this.baseURLVariables or the default value\n    // note: any variables defined in baseURLVariables but not actually variables in baseURL are ignored\n    for (const name of baseURLBuilder.names) {\n      const varValue = this.baseURLVariables[name];\n\n      if (varValue !== undefined && baseURLVariableSet[name].enum) {\n        // if varValue exists assign to baseURLVariablesResolved object\n        if (typeof varValue === 'number') {\n          // if number, get value from enum array\n\n          const enumVal = baseURLVariableSet[name].enum[varValue];\n\n          if (enumVal) {\n            baseURLVariablesResolved[name] = enumVal;\n          } else {\n            // if supplied value out of range: throw error\n\n            throw new Error(\n              `index ${varValue} out of range for enum of baseURL variable: ${name}; \\\n              enum max index is ${baseURLVariableSet[name].enum.length - 1}`,\n            );\n          }\n        } else if (typeof varValue === 'string') {\n          // if string, validate against enum array\n\n          if (baseURLVariableSet[name].enum.includes(varValue)) {\n            baseURLVariablesResolved[name] = varValue;\n          } else {\n            // if supplied value doesn't exist on enum: throw error\n\n            throw new Error(\n              `${varValue} is not a valid entry for baseURL variable ${name}; \\\n                variable must be of the following: ${baseURLVariableSet[name].enum.join(', ')}`,\n            );\n          }\n        }\n      } else {\n        // if varValue doesn't exist: get default\n\n        baseURLVariablesResolved[name] = baseURLVariableSet[name].default;\n      }\n    }\n\n    // return resolved baseURL\n    return baseURLBuilder.path(baseURLVariablesResolved);\n  };\n\n  /**\n   * Creates an axios config object for operation + arguments\n   * @memberof OpenAPIClientAxios\n   */\n  public getAxiosConfigForOperation = (\n    operation: Operation | string,\n    args: OperationMethodArguments,\n  ): AxiosRequestConfig => {\n    if (typeof operation === 'string') {\n      operation = this.getOperation(operation);\n    }\n    const request = this.getRequestConfigForOperation(operation, args);\n\n    // construct axios request config\n    const axiosConfig: AxiosRequestConfig = {\n      method: request.method as Method,\n      url: request.path,\n      data: request.payload,\n      params: request.query,\n      headers: request.headers,\n    };\n\n    // allow overriding baseURL with operation / path specific servers\n    const { servers } = operation;\n    if (servers && servers[0]) {\n      axiosConfig.baseURL = servers[0].url;\n    }\n\n    // allow overriding any parameters in AxiosRequestConfig\n    const [, , config] = args;\n    return {\n      ...axiosConfig,\n      ...config,\n      params: {\n        ...axiosConfig?.params,\n        ...config?.params,\n      },\n      headers: {\n        ...axiosConfig?.headers,\n        ...config?.headers,\n      },\n    };\n  };\n\n  /**\n   * Creates a generic request config object for operation + arguments.\n   *\n   * This function contains the logic that handles operation method parameters.\n   *\n   * @memberof OpenAPIClientAxios\n   */\n  public getRequestConfigForOperation = (operation: Operation | string, args: OperationMethodArguments) => {\n    if (typeof operation === 'string') {\n      operation = this.getOperation(operation);\n    }\n\n    const pathParams = {} as RequestConfig['pathParams'];\n    const query = {} as RequestConfig['query'];\n    const queryStringParts: string[] = [];\n    const headers = {} as RequestConfig['headers'];\n    const cookies = {} as RequestConfig['cookies'];\n    const parameters = (operation.parameters || []) as ParameterObject[];\n\n    const setRequestParam = (name: string, value: any, type: ParamType | string) => {\n      switch (type) {\n        case ParamType.Path:\n          pathParams[name] = value;\n          break;\n        case ParamType.Query: {\n          query[name] = value;\n          // Find the parameter definition to get style and explode\n          const param = parameters.find((p) => p.name === name && p.in === 'query');\n          const serialized = serializeQueryParameter(param, name, value);\n          queryStringParts.push(...serialized);\n          break;\n        }\n        case ParamType.Header:\n          headers[name] = value;\n          break;\n        case ParamType.Cookie:\n          cookies[name] = value;\n          break;\n      }\n    };\n\n    const getParamType = (paramName: string): ParamType => {\n      const param = parameters.find(({ name }) => name === paramName);\n      if (param) {\n        return param.in as ParamType;\n      }\n      // default all params to query if operation doesn't specify param\n      return ParamType.Query;\n    };\n\n    const getFirstOperationParam = () => {\n      const firstRequiredParam = parameters.find(({ required }) => required === true);\n      if (firstRequiredParam) {\n        return firstRequiredParam;\n      }\n      const firstParam = parameters[0];\n      if (firstParam) {\n        return firstParam;\n      }\n    };\n\n    const [paramsArg, payload] = args;\n    if (Array.isArray(paramsArg)) {\n      // ParamsArray\n      for (const param of paramsArg) {\n        setRequestParam(param.name, param.value, param.in || getParamType(param.name));\n      }\n    } else if (typeof paramsArg === 'object') {\n      // ParamsObject\n      for (const name in paramsArg) {\n        if (paramsArg[name] !== undefined) {\n          setRequestParam(name, paramsArg[name], getParamType(name));\n        }\n      }\n    } else if (paramsArg) {\n      const firstParam = getFirstOperationParam();\n      if (!firstParam) {\n        throw new Error(`No parameters found for operation ${operation.operationId}`);\n      }\n      setRequestParam(firstParam.name, paramsArg, firstParam.in as ParamType);\n    }\n\n    // path parameters\n    const pathBuilder = bath(operation.path);\n    // make sure all path parameters are set\n    for (const name of pathBuilder.names) {\n      const value = pathParams[name];\n      pathParams[name] = `${value}`;\n    }\n    const path = pathBuilder.path(pathParams);\n\n    // queryString parameter\n    const queryString = queryStringParts.join('&');\n\n    // full url with query string\n    const url = `${this.getBaseURL(operation)}${path}${queryString ? `?${queryString}` : ''}`;\n\n    // add default common headers\n    const defaultHeaders = this.client.defaults.headers;\n    for (const [key, val] of Object.entries(defaultHeaders.common ?? {})) {\n      headers[key] = val;\n    }\n\n    // add method specific default headers\n    if (this.applyMethodCommonHeaders) {\n      const methodHeaders: AxiosRequestHeaders = (defaultHeaders as any)[operation.method] ?? {};\n      for (const [key, val] of Object.entries(methodHeaders)) {\n        headers[key] = val;\n      }\n    }\n\n    // construct request config\n    const config: RequestConfig = {\n      method: operation.method,\n      url,\n      path,\n      pathParams,\n      query,\n      queryString,\n      headers,\n      cookies,\n      payload,\n    };\n    return config;\n  };\n\n  /**\n   * Flattens operations into a simple array of Operation objects easy to work with\n   *\n   * @returns {Operation[]}\n   * @memberof OpenAPIBackend\n   */\n  public getOperations = (): Operation[] => {\n    const paths = this.definition?.paths || {};\n    return Object.entries(paths).flatMap(([path, pathObject]) => {\n      return Object.values(HttpMethod)\n        .map((method) => ({ path, method, operation: pathObject[method] }))\n        .filter(({ operation }) => operation)\n        .map(({ operation, method }) => {\n          const op: Partial<Operation> = {\n            ...(typeof operation === 'object' ? operation : {}),\n            path,\n            method: method as HttpMethod,\n          };\n          if (pathObject.parameters) {\n            op.parameters = [...(op.parameters || []), ...pathObject.parameters];\n          }\n          if (pathObject.servers) {\n            op.servers = [...(op.servers || []), ...pathObject.servers];\n          }\n          op.security = op.security ?? this.definition.security;\n          return op as Operation;\n        });\n    });\n  };\n\n  /**\n   * Gets a single operation based on operationId\n   *\n   * @param {string} operationId\n   * @returns {Operation}\n   * @memberof OpenAPIBackend\n   */\n  public getOperation = (operationId: string): Operation | undefined => {\n    return this.getOperations().find((op) => op.operationId === operationId);\n  };\n\n  /**\n   * By default OpenAPIClient will use axios as request runner. You can register a different runner,\n   * in case you want to switch over from axios. This allows transitioning from axios to your library of choice.\n   * @param runner - request runner to be registered, either for all operations, or just one operation.\n   * @param operationId - optional parameter. If provided, runner will be registered for a single operation. Else, it will be registered for all operations.\n   */\n  public registerRunner(runner: Runner, operationId?: string) {\n    this.runners[operationId ?? DefaultRunnerKey] = runner;\n  }\n\n  private getRunner(operationId: string) {\n    return this.runners[operationId] ?? this.runners[DefaultRunnerKey];\n  }\n\n  /**\n   * Creates an axios method for an operation\n   * (...pathParams, data?, config?) => Promise<AxiosResponse>\n   *\n   * @param {Operation} operation\n   * @memberof OpenAPIClientAxios\n   */\n  private createOperationMethod = (operation: Operation): UnknownOperationMethod => {\n    const originalOperationMethod = async (...args: OperationMethodArguments) => {\n      const axiosConfig = this.getAxiosConfigForOperation(operation, args);\n      // run the axios request with the registered runner\n      // by default: axios runner\n      const runner = this.getRunner(operation.operationId);\n      return runner.runRequest(axiosConfig, operation, runner.context);\n    };\n\n    return this.transformOperationMethod(originalOperationMethod, operation);\n  };\n}\n"
  },
  {
    "path": "src/index.ts",
    "content": "import { OpenAPIClientAxios } from './client';\nexport default OpenAPIClientAxios;\nexport * from './client';\nexport * from './types/client';\n\n// re-export axios types\nexport type { Axios, AxiosInstance, AxiosRequestConfig, AxiosResponse, AxiosError } from 'axios';\n"
  },
  {
    "path": "src/query-serializer.ts",
    "content": "import { ParameterObject } from './types/client';\n\n/**\n * Serializes a query parameter according to OpenAPI 3.0 specification\n *\n * @param param - The parameter definition from OpenAPI spec\n * @param name - The parameter name\n * @param value - The parameter value (can be primitive, array, or object)\n * @returns Array of query string parts (key=value pairs)\n */\nexport const serializeQueryParameter = (\n  param: ParameterObject | undefined,\n  name: string,\n  value: any,\n): string[] => {\n  // Get style and explode from parameter definition with defaults\n  // Per OpenAPI spec: default style for query is 'form', default explode is true\n  const style = param?.style || 'form';\n  const explode = param?.explode !== undefined ? param.explode : true;\n\n  // Handle null/undefined values\n  if (value === null || value === undefined) {\n    return [];\n  }\n\n  // Handle arrays\n  if (Array.isArray(value)) {\n    return serializeArrayParameter(name, value, style, explode);\n  }\n\n  // Handle objects\n  if (typeof value === 'object') {\n    return serializeObjectParameter(name, value, style, explode);\n  }\n\n  // Handle primitive values\n  return [`${encodeURIComponent(name)}=${encodeURIComponent(String(value))}`];\n};\n\n/**\n * Serializes an array query parameter\n */\nconst serializeArrayParameter = (\n  name: string,\n  value: any[],\n  style: string,\n  explode: boolean,\n): string[] => {\n  if (value.length === 0) {\n    return [];\n  }\n\n  switch (style) {\n    case 'form':\n      if (explode) {\n        // form explode=true: id=3&id=4&id=5\n        return value.map((item) => `${encodeURIComponent(name)}=${encodeURIComponent(String(item))}`);\n      } else {\n        // form explode=false: id=3,4,5\n        const encodedValues = value.map((item) => encodeURIComponent(String(item))).join(',');\n        return [`${encodeURIComponent(name)}=${encodedValues}`];\n      }\n\n    case 'spaceDelimited':\n      if (explode) {\n        // spaceDelimited with explode=true is not valid per spec, but fallback to form explode=true\n        return value.map((item) => `${encodeURIComponent(name)}=${encodeURIComponent(String(item))}`);\n      } else {\n        // spaceDelimited explode=false: id=3%204%205\n        const encodedValues = value.map((item) => encodeURIComponent(String(item))).join('%20');\n        return [`${encodeURIComponent(name)}=${encodedValues}`];\n      }\n\n    case 'pipeDelimited':\n      if (explode) {\n        // pipeDelimited with explode=true is not valid per spec, but fallback to form explode=true\n        return value.map((item) => `${encodeURIComponent(name)}=${encodeURIComponent(String(item))}`);\n      } else {\n        // pipeDelimited explode=false: id=3%7C4%7C5\n        const encodedValues = value.map((item) => encodeURIComponent(String(item))).join('%7C');\n        return [`${encodeURIComponent(name)}=${encodedValues}`];\n      }\n\n    default:\n      // Default to form explode=true\n      return value.map((item) => `${encodeURIComponent(name)}=${encodeURIComponent(String(item))}`);\n  }\n};\n\n/**\n * Serializes an object query parameter\n */\nconst serializeObjectParameter = (\n  name: string,\n  value: Record<string, any>,\n  style: string,\n  explode: boolean,\n): string[] => {\n  const keys = Object.keys(value);\n\n  if (keys.length === 0) {\n    return [];\n  }\n\n  switch (style) {\n    case 'deepObject':\n      if (explode) {\n        // deepObject explode=true: filter[role]=admin&filter[firstName]=Alex\n        return keys.map((key) =>\n          `${encodeURIComponent(name)}[${encodeURIComponent(key)}]=${encodeURIComponent(String(value[key]))}`\n        );\n      } else {\n        // deepObject with explode=false is not valid per spec, but fallback to form\n        const pairs: string[] = [];\n        for (const key of keys) {\n          pairs.push(encodeURIComponent(key));\n          pairs.push(encodeURIComponent(String(value[key])));\n        }\n        return [`${encodeURIComponent(name)}=${pairs.join(',')}`];\n      }\n\n    case 'form':\n      if (explode) {\n        // form explode=true: role=admin&firstName=Alex (flattened)\n        return keys.map((key) =>\n          `${encodeURIComponent(key)}=${encodeURIComponent(String(value[key]))}`\n        );\n      } else {\n        // form explode=false: filter=role,admin,firstName,Alex\n        const pairs: string[] = [];\n        for (const key of keys) {\n          pairs.push(encodeURIComponent(key));\n          pairs.push(encodeURIComponent(String(value[key])));\n        }\n        return [`${encodeURIComponent(name)}=${pairs.join(',')}`];\n      }\n\n    default:\n      // Default to form explode=true\n      return keys.map((key) =>\n        `${encodeURIComponent(key)}=${encodeURIComponent(String(value[key]))}`\n      );\n  }\n};\n"
  },
  {
    "path": "src/types/client.ts",
    "content": "import type { AxiosResponse, AxiosRequestConfig } from 'axios';\nimport type { OpenAPIV3, OpenAPIV3_1 } from 'openapi-types';\nexport type { OpenAPIV3, OpenAPIV3_1 } from 'openapi-types';\n\n/**\n * Type alias for OpenAPI document. We only support v3\n */\nexport declare type Document = OpenAPIV3.Document | OpenAPIV3_1.Document;\nexport declare type Server = OpenAPIV3.ServerObject | OpenAPIV3_1.ServerObject;\nexport declare type ParameterObject = OpenAPIV3.ParameterObject | OpenAPIV3_1.ParameterObject;\n\n/**\n * OpenAPI allowed HTTP methods\n */\nexport enum HttpMethod {\n  Get = 'get',\n  Put = 'put',\n  Post = 'post',\n  Patch = 'patch',\n  Delete = 'delete',\n  Options = 'options',\n  Head = 'head',\n  Trace = 'trace',\n}\n\n/**\n * OpenAPI parameters \"in\"\n */\nexport enum ParamType {\n  Query = 'query',\n  Header = 'header',\n  Path = 'path',\n  Cookie = 'cookie',\n}\n\n/**\n * Operation method spec\n */\nexport declare type ImplicitParamValue = string | number;\nexport interface ExplicitParamValue {\n  value: string | number;\n  name: string;\n  in?: ParamType | string;\n}\nexport interface UnknownParamsObject {\n  [parameter: string]: ImplicitParamValue | ImplicitParamValue[];\n}\nexport declare type ParamsArray = ExplicitParamValue[];\nexport declare type SingleParam = ImplicitParamValue;\nexport declare type Parameters<ParamsObject = UnknownParamsObject> = ParamsObject | ParamsArray | SingleParam;\nexport declare type RequestPayload = any;\nexport declare type OperationMethodArguments = [Parameters?, RequestPayload?, AxiosRequestConfig?];\nexport declare type OperationResponse<Response> = Promise<AxiosResponse<Response>>;\nexport declare type UnknownOperationMethod = (\n  parameters?: Parameters,\n  data?: RequestPayload,\n  config?: AxiosRequestConfig,\n) => OperationResponse<any>;\nexport interface UnknownOperationMethods {\n  [operationId: string]: UnknownOperationMethod;\n}\n\n/**\n * Generic request config object\n */\nexport interface RequestConfig {\n  method: HttpMethod;\n  url: string;\n  path: string;\n  pathParams: {\n    [key: string]: string;\n  };\n  query: {\n    [key: string]: string | string[];\n  };\n  queryString: string;\n  headers: AxiosRequestConfig['headers'];\n  cookies: {\n    [cookie: string]: string;\n  };\n  payload?: RequestPayload;\n}\n\n/**\n * Operation object extended with path and method for easy looping\n */\nexport interface Operation extends OpenAPIV3.OperationObject {\n  path: string;\n  method: HttpMethod;\n}\n\n/**\n * A dictionary of paths and their methods\n */\nexport interface UnknownPathsDictionary {\n  [path: string]: {\n    [method in HttpMethod]?: UnknownOperationMethod;\n  };\n}\n"
  },
  {
    "path": "tsconfig.json",
    "content": "{\n  \"compilerOptions\": {\n    \"strict\": true,\n    \"target\": \"es5\",\n    \"module\": \"commonjs\",\n    \"moduleResolution\": \"node\",\n    \"lib\": [\"esnext\", \"dom\"],\n    \"esModuleInterop\": true,\n    \"noImplicitAny\": true,\n    \"strictPropertyInitialization\": false,\n    \"strictNullChecks\": false,\n    \"baseUrl\": \".\",\n    \"rootDir\": \"src/\",\n    \"outDir\": \"\",\n    \"sourceMap\": true,\n    \"declaration\": true,\n    \"downlevelIteration\": true,\n    \"allowSyntheticDefaultImports\": true\n  },\n  \"include\": [\n    \"src/**/*\"\n  ],\n  \"exclude\": [\n    \"**/*.test.ts\"\n  ]\n}\n"
  }
]