{"id":26119271,"url":"https://github.com/aleksandryackovlev/openapi-client-sdk-loader","last_synced_at":"2026-01-28T19:01:44.954Z","repository":{"id":36931619,"uuid":"227444259","full_name":"aleksandryackovlev/openapi-client-sdk-loader","owner":"aleksandryackovlev","description":"Open API loader for webpack. Compiles yaml to client sdk.","archived":false,"fork":false,"pushed_at":"2023-01-07T12:45:34.000Z","size":3285,"stargazers_count":2,"open_issues_count":17,"forks_count":0,"subscribers_count":2,"default_branch":"master","last_synced_at":"2025-09-21T17:47:25.642Z","etag":null,"topics":["api-client","codegen","openapi-generator","sdk-client","swagger-generator","webpack","webpack-loader"],"latest_commit_sha":null,"homepage":"","language":"JavaScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/aleksandryackovlev.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":".github/CONTRIBUTING.md","funding":null,"license":"LICENSE","code_of_conduct":".github/CODE_OF_CONDUCT.md","threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2019-12-11T19:30:23.000Z","updated_at":"2021-05-14T04:32:31.000Z","dependencies_parsed_at":"2023-01-17T07:30:39.931Z","dependency_job_id":null,"html_url":"https://github.com/aleksandryackovlev/openapi-client-sdk-loader","commit_stats":null,"previous_names":[],"tags_count":25,"template":false,"template_full_name":null,"purl":"pkg:github/aleksandryackovlev/openapi-client-sdk-loader","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/aleksandryackovlev%2Fopenapi-client-sdk-loader","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/aleksandryackovlev%2Fopenapi-client-sdk-loader/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/aleksandryackovlev%2Fopenapi-client-sdk-loader/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/aleksandryackovlev%2Fopenapi-client-sdk-loader/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/aleksandryackovlev","download_url":"https://codeload.github.com/aleksandryackovlev/openapi-client-sdk-loader/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/aleksandryackovlev%2Fopenapi-client-sdk-loader/sbom","scorecard":{"id":179102,"data":{"date":"2025-08-11","repo":{"name":"github.com/aleksandryackovlev/openapi-client-sdk-loader","commit":"23f63626bffa52303f573bd691b4da66cab27e77"},"scorecard":{"version":"v5.2.1-40-gf6ed084d","commit":"f6ed084d17c9236477efd66e5b258b9d4cc7b389"},"score":1.7,"checks":[{"name":"Maintained","score":0,"reason":"0 commit(s) and 0 issue activity found in the last 90 days -- score normalized to 0","details":null,"documentation":{"short":"Determines if the project is \"actively maintained\".","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#maintained"}},{"name":"Dangerous-Workflow","score":-1,"reason":"no workflows found","details":null,"documentation":{"short":"Determines if the project's GitHub Action workflows avoid dangerous patterns.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#dangerous-workflow"}},{"name":"Code-Review","score":0,"reason":"Found 0/3 approved changesets -- score normalized to 0","details":null,"documentation":{"short":"Determines if the project requires human code review before pull requests (aka merge requests) are merged.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#code-review"}},{"name":"Packaging","score":-1,"reason":"packaging workflow not detected","details":["Warn: no GitHub/GitLab publishing workflow detected."],"documentation":{"short":"Determines if the project is published as a package that others can easily download, install, easily update, and uninstall.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#packaging"}},{"name":"Token-Permissions","score":-1,"reason":"No tokens found","details":null,"documentation":{"short":"Determines if the project's workflows follow the principle of least privilege.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#token-permissions"}},{"name":"Binary-Artifacts","score":10,"reason":"no binaries found in the repo","details":null,"documentation":{"short":"Determines if the project has generated executable (binary) artifacts in the source repository.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#binary-artifacts"}},{"name":"Pinned-Dependencies","score":-1,"reason":"no dependencies found","details":null,"documentation":{"short":"Determines if the project has declared and pinned the dependencies of its build process.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#pinned-dependencies"}},{"name":"CII-Best-Practices","score":0,"reason":"no effort to earn an OpenSSF best practices badge detected","details":null,"documentation":{"short":"Determines if the project has an OpenSSF (formerly CII) Best Practices Badge.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#cii-best-practices"}},{"name":"Security-Policy","score":0,"reason":"security policy file not detected","details":["Warn: no security policy file detected","Warn: no security file to analyze","Warn: no security file to analyze","Warn: no security file to analyze"],"documentation":{"short":"Determines if the project has published a security policy.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#security-policy"}},{"name":"Fuzzing","score":0,"reason":"project is not fuzzed","details":["Warn: no fuzzer integrations found"],"documentation":{"short":"Determines if the project uses fuzzing.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#fuzzing"}},{"name":"Signed-Releases","score":-1,"reason":"no releases found","details":null,"documentation":{"short":"Determines if the project cryptographically signs release artifacts.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#signed-releases"}},{"name":"License","score":10,"reason":"license file detected","details":["Info: project has a license file: LICENSE:0","Info: FSF or OSI recognized license: MIT License: LICENSE:0"],"documentation":{"short":"Determines if the project has defined a license.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#license"}},{"name":"Branch-Protection","score":0,"reason":"branch protection not enabled on development/release branches","details":["Warn: branch protection not enabled for branch 'master'"],"documentation":{"short":"Determines if the default and release branches are protected with GitHub's branch protection settings.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#branch-protection"}},{"name":"SAST","score":0,"reason":"SAST tool is not run on all commits -- score normalized to 0","details":["Warn: 0 commits out of 30 are checked with a SAST tool"],"documentation":{"short":"Determines if the project uses static code analysis.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#sast"}},{"name":"Vulnerabilities","score":0,"reason":"58 existing vulnerabilities detected","details":["Warn: Project is vulnerable to: GHSA-968p-4wvh-cqc8","Warn: Project is vulnerable to: GHSA-67hx-6x53-jw92","Warn: Project is vulnerable to: GHSA-93q8-gq69-wqmw","Warn: Project is vulnerable to: GHSA-v6h2-p8h4-qcjw","Warn: Project is vulnerable to: GHSA-grv7-fg5c-xmjg","Warn: Project is vulnerable to: GHSA-x9w5-v3q2-3rhw","Warn: Project is vulnerable to: GHSA-w8qv-6jwh-64r5","Warn: Project is vulnerable to: GHSA-7gc6-qh9x-w6h8","Warn: Project is vulnerable to: GHSA-3xgq-45jj-v275","Warn: Project is vulnerable to: GHSA-w573-4hg7-7wgq","Warn: Project is vulnerable to: GHSA-r9p9-mrjm-926w","Warn: Project is vulnerable to: GHSA-434g-2637-qmqr","Warn: Project is vulnerable to: GHSA-49q7-c7j4-3p7m","Warn: Project is vulnerable to: GHSA-977x-g7h5-7qgw","Warn: Project is vulnerable to: GHSA-f7q4-pwc6-w24p","Warn: Project is vulnerable to: GHSA-fc9h-whq2-v747","Warn: Project is vulnerable to: GHSA-vjh7-7g9h-fjfh","Warn: Project is vulnerable to: GHSA-4gmj-3p3h-gm8h","Warn: Project is vulnerable to: GHSA-fjxv-7rqg-78g4","Warn: Project is vulnerable to: GHSA-ww39-953v-wcq6","Warn: Project is vulnerable to: GHSA-765h-qjxv-5f44","Warn: Project is vulnerable to: GHSA-f2jv-r9rf-7988","Warn: Project is vulnerable to: GHSA-43f8-2h32-f4cj","Warn: Project is vulnerable to: GHSA-896r-f27r-55mw","Warn: Project is vulnerable to: GHSA-9c47-m6qq-7p4h","Warn: Project is vulnerable to: GHSA-76p3-8jx3-jpfq","Warn: Project is vulnerable to: GHSA-3rfm-jhwj-7488","Warn: Project is vulnerable to: GHSA-hhq3-ff78-jv3g","Warn: Project is vulnerable to: GHSA-29mw-wpgm-hmr9","Warn: Project is vulnerable to: GHSA-35jh-r3h4-6jhm","Warn: Project is vulnerable to: GHSA-7wpw-2hjm-89gp","Warn: Project is vulnerable to: GHSA-952p-6rrq-rcjv","Warn: Project is vulnerable to: GHSA-f8q6-p94x-37v3","Warn: Project is vulnerable to: GHSA-xvch-5gv4-984h","Warn: Project is vulnerable to: GHSA-w7rc-rwvf-8q5r","Warn: Project is vulnerable to: GHSA-r683-j2x4-v87g","Warn: Project is vulnerable to: GHSA-hj48-42vr-x3v9","Warn: Project is vulnerable to: GHSA-h7cp-r72f-jxh6","Warn: Project is vulnerable to: GHSA-v62p-rq8g-8h59","Warn: Project is vulnerable to: GHSA-hrpp-h998-j3pp","Warn: Project is vulnerable to: GHSA-p8p7-x288-28g6","Warn: Project is vulnerable to: GHSA-c2qf-rxjj-qqgw","Warn: Project is vulnerable to: GHSA-44c6-4v22-4mhx","Warn: Project is vulnerable to: GHSA-4x5v-gmq8-25ch","Warn: Project is vulnerable to: GHSA-4rq4-32rv-6wp6","Warn: Project is vulnerable to: GHSA-64g7-mvw6-v9qj","Warn: Project is vulnerable to: GHSA-vx3p-948g-6vhq","Warn: Project is vulnerable to: GHSA-4wf5-vphf-c2xc","Warn: Project is vulnerable to: GHSA-52f5-9888-hmc6","Warn: Project is vulnerable to: GHSA-jgrx-mgxx-jf9v","Warn: Project is vulnerable to: GHSA-72xf-g2v4-qvf3","Warn: Project is vulnerable to: GHSA-7p7h-4mm5-852v","Warn: Project is vulnerable to: GHSA-38fc-wpqx-33j7","Warn: Project is vulnerable to: GHSA-qgmg-gppg-76g5","Warn: Project is vulnerable to: GHSA-xx4c-jj58-r7x6","Warn: Project is vulnerable to: GHSA-j8xg-fqg3-53r7","Warn: Project is vulnerable to: GHSA-6fc8-4gx4-v693","Warn: Project is vulnerable to: GHSA-3h5v-q93c-6h6q"],"documentation":{"short":"Determines if the project has open, known unfixed vulnerabilities.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#vulnerabilities"}}]},"last_synced_at":"2025-08-16T18:27:44.089Z","repository_id":36931619,"created_at":"2025-08-16T18:27:44.089Z","updated_at":"2025-08-16T18:27:44.089Z"},"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":28849359,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-01-28T15:15:36.453Z","status":"ssl_error","status_checked_at":"2026-01-28T15:15:13.020Z","response_time":57,"last_error":"SSL_read: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["api-client","codegen","openapi-generator","sdk-client","swagger-generator","webpack","webpack-loader"],"created_at":"2025-03-10T12:25:51.589Z","updated_at":"2026-01-28T19:01:44.939Z","avatar_url":"https://github.com/aleksandryackovlev.png","language":"JavaScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"\u003cdiv align=\"center\"\u003e\n  \u003ca href=\"https://swagger.io/docs/specification/about/\"\u003e\n    \u003cimg src=\"https://raw.githubusercontent.com/aleksandryackovlev/openapi-client-sdk-loader/master/assets/openapi-logo.png\" alt=\"Open API logo\" width=\"200\" height=\"200\"\u003e\n  \u003c/a\u003e\n  \u003ca href=\"https://github.com/webpack/webpack\"\u003e\n    \u003cimg width=\"200\" height=\"200\" src=\"https://webpack.js.org/assets/icon-square-big.svg\"\u003e\n  \u003c/a\u003e\n\u003c/div\u003e\n\n[![npm][npm]][npm-url]\n[![deps][deps]][deps-url]\n[![Build Status](https://travis-ci.org/aleksandryackovlev/openapi-client-sdk-loader.svg?branch=master)](https://travis-ci.org/aleksandryackovlev/openapi-client-sdk-loader)\n[![codecov](https://codecov.io/gh/aleksandryackovlev/openapi-client-sdk-loader/branch/master/graph/badge.svg)](https://codecov.io/gh/aleksandryackovlev/openapi-client-sdk-loader)\n[![size](https://packagephobia.now.sh/badge?p=openapi-client-sdk-loader)](https://packagephobia.now.sh/result?p=openapi-client-sdk-loader)\n\n# openapi-client-sdk-loader\n\nGenerates the client sdk from [Open API 3.0](https://swagger.io/docs/specification/about/) documentation.\n\n## Getting Started\n\nTo begin, you'll need to install `openapi-client-sdk-loader`:\n\n```console\n$ npm install openapi-client-sdk-loader --save-dev\n```\n\nThen add the loader to your `webpack` config before ts-loader or babel-loader. For example:\n\n**file.ts**\n\n```js\nimport { someApiMethod } from 'api.yaml';\n```\n\n**webpack.config.js**\n\n```js\nmodule.exports = {\n  module: {\n    rules: [\n      {\n        test: /\\.(yaml|ts)$/i,\n        rules: [\n          {\n            loader: require.resolve('ts-loader'),\n            options: {\n              configFile: path.resolve(__dirname, '../tsconfig.json'),\n              appendTsSuffixTo: [/\\.yaml$/],\n            },\n          },\n          {\n            loader: require.resolve('openapi-client-sdk-loader'),\n            options: {\n              compiler: 'ts',\n              templateOptions: {\n                validateRequest: true,\n                validateResponse: true,\n              },\n              skipInvalid: true,\n              style: {\n                singleQuote: true,\n                trailingComma: 'es5',\n                printWidth: 100,\n              },\n            },\n          },\n        ],\n      },\n    ],\n  },\n};\n```\n\n\nAnd run `webpack` via your preferred method.\n\n## Options\n\n|                    Name                     |            Type             | Default  | Description                                                            |\n| :-----------------------------------------: | :-------------------------: | :------: | :--------------------------------------------------------------------- |\n|              **[`compiler`](#compiler)**              |    `{String\\|Function}`    |  `'ts'`  | Compiler to use for the processing of a swagger api object                  |\n|           **[`template`](#template)**           |    `{String}`    |  `'path_to_project/node_modules/openapi-client-sdk-loader/src/templates/ts'`  | Absolute path to the directory with a handlebars template                           |\n|          **[`templateOptions`](#templateOptions)**          | `{Object}` | `{ validateRequest: true, validateResponse: true }`  | A set of options passed to handlebars files during compilation                   |\n|        **[`skipInvalid`](#skipInvalid)**        |         `{Boolean}`         | `true`  | Enables/Disables failing on importing invalid swagger documents                             |\n|    **[`style`](#style)**    |         `{Object}`          |   `{ singleQuote: true, trailingComma: 'es5', printWidth: 100 }`    | A set of options to pass into prettier for formatting function |\n\n\n### `compiler`\n\nType: `String|Function`\nDefault: `'ts'`\n\nCompiler that is going to be used while processing the api object returned from the [`SwaggerParser`](https://github.com/APIDevTools/swagger-parser).\n\n#### `String`\nThe name of one of the build-in compilers. For now, there are `ts` (generates typescript client sdk) and `js` (generates javascript client sdk) compilers to choose from.\n\n#### `Function`\nCustom function that receives the api object and the loader options, and returns a Promise that resolves to the object with the shape, expected by the handlebars template.\n\n### `template`\n\nType: `String`\nDefault: `'path_to_project/node_modules/openapi-client-sdk-loader/src/templates/ts'`\n\nAbsolute path to the directory with the handlebars template that is going to be used during code generation.  In the folder there should be at least one file `index.handlebars`. If there are more handlebars files in the given directory, others become partials that can be used by their names in every handlebars file. See [`Handlebars docs`](https://github.com/wycats/handlebars.js) for more info on templates.\n\n### `templateOptions`\n\nType: `Object`\nDefault: `{ validateRequest: true, validateResponse: true }`\n\nA set of options passed to handlebars templates during compilation.\n\nIt is passed to the handlebars template as the `options` property. This option can have any shape. For the default typescript template it contains only two properties. See [`Templates`](#Templates) for more info.\n\n### `skipInvalid`\n\nType: `Boolean`\nDefault: `true`\n\nEnables/Disables failing on importing invalid swagger document.\n\nIf enabled, invalid documents will be imported as is and should be processed by other loaders or plugins. Useful when, for example, your Open API documentation is written in a json file and you use other types of json files in your application.\n\n### `style`\n\nType: `Object`\nDefault: `{ singleQuote: true, trailingComma: 'es5', printWidth: 100 }`\n\nA set of options to pass into prettier for formatting function.\n\nIf you use source maps, the generated code will be shown in the sources panel. Formatting can make it easier too read. See [`Prettier docs`](https://github.com/prettier/prettier) for the list of all available options.\n\n## Templates\n\n### ts template\nA built-in template for the typescript client sdk generation. Creates an sdk method for every operation. Every operation in the documentation has to have the `operationId`, this id is used as a name of a generated function in the resulting code.\n\n#### Template options\n|                    Name                     |            Type             | Default  | Description                                                            |\n| :-----------------------------------------: | :-------------------------: | :------: | :--------------------------------------------------------------------- |\n|        **validateRequest**        |         `{Boolean}`         | `true`  | Enables/Disables json schema validation for parameters, query strings, headers and request bodies                             |\n|        **validateResponse**        |         `{Boolean}`         | `true`  | Enables/Disables json schema validation for responses                             |\n|        **baseUrl**        |         `{String}`         | `null`  | The api base url. If this option is set, it overrides `api.servers.url`                             |\n\n#### Example\n\n**api.yaml**\n```\nopenapi: 3.0.1\ninfo:\n  title: Swagger Doc\n  description: 'This is a sample server.'\n  version: 1.0.3\nservers:\n- url: https://petstore.swagger.io/v2\n- url: http://petstore.swagger.io/v2\npaths:\n  /some-path/{id}:\n    post:\n      summary: Summary\n      description: Returns a single element\n      operationId: someApiMethod\n      parameters:\n      - name: id\n        in: path\n        required: true\n        schema:\n          type: integer\n          format: int64\n      - name: tag\n        in: query\n        required: true\n        schema:\n          type: string\n      requestBody:\n        description: Desc\n        content:\n          application/json:\n            schema:\n              type: object\n              required: [ order ]\n              properties:\n                order:\n                  type: string\n      responses:\n        200:\n          description: successful operation\n          content:\n            application/json:\n              schema:\n                type: object\n                properties:\n                  id:\n                    type: string\n```\n\n**file.ts**\n\n```js\nimport { someApiMethod } from './api.yaml';\n\n// Basic use case\nsomeApiMethod({\n    // url parameters\n    params: {\n        id: 3,\n    },\n    // query parameters\n    query: {\n        tag: 'some tag',\n    },\n    // request body\n    data: {\n        order: 'asc'\n    }\n})\n    .then(doSomeStuffWithTheResult)\n    .catch(handleError);\n    \n// Request with custom options\nsomeApiMethod({\n    // url parameters\n    params: {\n        id: 3,\n    },\n    // query parameters\n    query: {\n        tag: 'some tag',\n    },\n    // request body\n    data: {\n        order: 'asc',\n    },\n}, {\n   // API base url\n   baseUrl: 'https://github.com', // default process.env.API_BASE_URL || '{{templateOptions.baseUrl}}' || '{{api.server.url}}'\n   \n   // Middleware to run before fetching the request\n   preMiddleware: async (url: string, params: RequestInit): Promise\u003c[string, RequestInit]\u003e =\u003e { // default (url: string, params: RequestInit) =\u003e Promise.resolve([url, params])\n       // do some manipulation with the data. for example, get an auth token\n       const token = await getSomeTokenAsync(url, params);\n       \n       // return a tuple\n       return [\n        url,\n        {\n            ...params,\n            headers: { ...params.headers, Authorization: token },\n        }\n        ];\n   },\n})\n    .then(doSomeStuffWithTheResult)\n    .catch(handleError);\n```\n\n\n**Generated code of the sdk client:**\n\u003cdetails\u003e\n  \u003csummary\u003eSee code\u003c/summary\u003e\n  \n  \n```js\nimport Ajv from 'ajv';\nimport { stringify } from 'query-string';\n\nconst ajv = new Ajv({ unknownFormats: ['int32', 'int64', 'binary'] });\n\nexport class ApiError\u003cT\u003e extends Error {\n  status: number;\n\n  statusText: string;\n\n  headers: Headers;\n\n  response: T;\n\n  constructor({\n    status,\n    statusText,\n    response,\n    message,\n    headers,\n  }: {\n    status: number;\n    statusText: string;\n    response: T;\n    message: string;\n    headers: Headers;\n  }) {\n    super(message);\n    this.status = status;\n    this.response = response;\n    this.statusText = statusText;\n    this.headers = headers;\n  }\n}\n\nexport class ClientCodeError extends Error {}\n\nexport class RequestValidationError extends Error {\n  element: 'query' | 'params' | 'body' | 'headers';\n\n  method: string;\n\n  errors: Ajv.ErrorObject[];\n\n  constructor({\n    message,\n    element,\n    method,\n    errors = [],\n  }: {\n    message: string;\n    element: 'query' | 'params' | 'body' | 'headers';\n    method: string;\n    errors?: Ajv.ErrorObject[];\n  }) {\n    super(message);\n\n    this.element = element;\n    this.method = method;\n    this.errors = errors;\n  }\n}\n\nexport class ResponseValidationError extends Error {\n  method: string;\n\n  errors: Ajv.ErrorObject[];\n\n  constructor({\n    message,\n    method,\n    errors = [],\n  }: {\n    message: string;\n    method: string;\n    errors?: Ajv.ErrorObject[];\n  }) {\n    super(message);\n\n    this.method = method;\n    this.errors = errors;\n  }\n}\n\nexport interface Config {\n  baseUrl: string;\n  preMiddleware: (url: string, params: RequestInit) =\u003e Promise\u003c[string, RequestInit]\u003e;\n}\n\nconst defaultConfig: Config = {\n  baseUrl: process.env.API_BASE_URL || 'https://petstore.swagger.io/v2',\n  preMiddleware: (url: string, params: RequestInit) =\u003e Promise.resolve([url, params]),\n};\n\nexport interface SomeApiMethodParams {\n  id: number;\n}\n\nexport interface SomeApiMethodQuery {\n  tag: string;\n}\n\nexport interface SomeApiMethodRequestBodyJson {\n  order: string;\n}\n\nexport interface SomeApiMethodResponse {\n  id?: string;\n}\n\nexport interface SomeApiMethodRequest {\n  query?: SomeApiMethodQuery;\n  params?: SomeApiMethodParams;\n  data?: FormData | SomeApiMethodRequestBodyJson;\n}\nexport const someApiMethod: (\n  request: SomeApiMethodRequest,\n  config?: Partial\u003cConfig\u003e\n) =\u003e Promise\u003cSomeApiMethodResponse\u003e = async (\n  { query = {}, params = {}, data = {} } = {},\n  currentConfig = defaultConfig\n) =\u003e {\n  const config = { ...defaultConfig, ...currentConfig };\n\n  let requestUrl = `${config.baseUrl}/some-path/{id}`;\n\n  const querySchema = {\n    type: 'object',\n    required: ['tag'],\n    properties: { tag: { type: 'string' } },\n  };\n\n  function isQuery(obj: unknown): obj is SomeApiMethodQuery {\n    const isValid = ajv.validate(querySchema, obj);\n\n    return !!isValid;\n  }\n\n  if (!isQuery(query)) {\n    throw new RequestValidationError({\n      message: 'Request query string schema validation error',\n      method: 'someApiMethod',\n      element: 'query',\n      errors: ajv.errors || [],\n    });\n  }\n\n  if (Object.keys(query)) {\n    requestUrl = `${requestUrl}?${stringify(query, { arrayFormat: 'bracket' })}`;\n  }\n\n  const paramsSchema = {\n    type: 'object',\n    required: ['id'],\n    properties: { id: { type: 'integer', format: 'int64' } },\n  };\n\n  function isParams(obj: unknown): obj is SomeApiMethodParams {\n    const isValid = ajv.validate(paramsSchema, obj);\n\n    return !!isValid;\n  }\n\n  if (!isParams(params)) {\n    throw new RequestValidationError({\n      message: 'Request params schema validation error',\n      method: 'someApiMethod',\n      element: 'params',\n      errors: ajv.errors || [],\n    });\n  }\n\n  type SomeApiMethodParamsKeys = keyof SomeApiMethodParams;\n\n  const paramsKeys = Object.keys(params) as SomeApiMethodParamsKeys[];\n\n  if (paramsKeys.length) {\n    paramsKeys.forEach(param =\u003e {\n      requestUrl = requestUrl.replace(`{${param}}`, encodeURIComponent(String(params[param])));\n    });\n  }\n\n  const requestHeaders = {\n    'Content-Type': 'application/json',\n  };\n\n  if (!(data instanceof FormData)) {\n    const bodySchema = {\n      type: 'object',\n      required: ['order'],\n      properties: { order: { type: 'string' } },\n    };\n    const isBodyValid = ajv.validate(bodySchema, data);\n\n    if (!isBodyValid) {\n      throw new RequestValidationError({\n        message: 'Request body schema validation error',\n        method: 'someApiMethod',\n        element: 'body',\n        errors: ajv.errors || [],\n      });\n    }\n  }\n\n  let requestParams;\n\n  if (data) {\n    requestParams = {\n      method: 'POST',\n      headers: requestHeaders,\n      body: data instanceof FormData ? data : JSON.stringify(data),\n    };\n  } else {\n    requestParams = {\n      method: 'POST',\n      headers: requestHeaders,\n    };\n  }\n\n  let response: unknown;\n\n  try {\n    const [processedUrl, processedParams] = await config.preMiddleware(requestUrl, requestParams);\n    const responseObject = await fetch(processedUrl, processedParams);\n    response = await responseObject.json();\n\n    if (!responseObject.ok) {\n      throw new ApiError\u003ctypeof response\u003e({\n        message: 'Api error while fetching someApiMethod',\n        status: responseObject.status,\n        statusText: responseObject.statusText,\n        response,\n        headers: responseObject.headers,\n      });\n    }\n  } catch (error) {\n    if (error instanceof ApiError) {\n      throw error;\n    } else {\n      throw error as ClientCodeError;\n    }\n  }\n\n  const responseSchema = { type: 'object', properties: { id: { type: 'string' } } };\n\n  function isResponse(obj: unknown): obj is SomeApiMethodResponse {\n    const isValid = ajv.validate(responseSchema, obj);\n\n    return !!isValid;\n  }\n\n  if (!isResponse(response)) {\n    throw new ResponseValidationError({\n      message: 'Response schema validation error',\n      method: 'someApiMethod',\n      errors: ajv.errors || [],\n    });\n  }\n\n  return response;\n};\n```\n\u003c/details\u003e\n\n### js template\nA built-in template for the javascript client sdk generation. Creates an sdk method for every operation. Every operation in the documentation has to have the `operationId`, this id is used as a name of a generated function in the resulting code.\n\n#### Template options\n|                    Name                     |            Type             | Default  | Description                                                            |\n| :-----------------------------------------: | :-------------------------: | :------: | :--------------------------------------------------------------------- |\n|        **validateRequest**        |         `{Boolean}`         | `true`  | Enables/Disables json schema validation for parameters, query strings, headers and request bodies                             |\n|        **validateResponse**        |         `{Boolean}`         | `true`  | Enables/Disables json schema validation for responses                             |\n|        **baseUrl**        |         `{String}`         | `null`  | The api base url. If this option is set, it overrides `api.servers.url`                             |\n\n#### Example\n\n**api.yaml**\n```\nopenapi: 3.0.1\ninfo:\n  title: Swagger Doc\n  description: 'This is a sample server.'\n  version: 1.0.3\nservers:\n- url: https://petstore.swagger.io/v2\n- url: http://petstore.swagger.io/v2\npaths:\n  /some-path/{id}:\n    post:\n      summary: Summary\n      description: Returns a single element\n      operationId: someApiMethod\n      parameters:\n      - name: id\n        in: path\n        required: true\n        schema:\n          type: integer\n          format: int64\n      - name: tag\n        in: query\n        required: true\n        schema:\n          type: string\n      requestBody:\n        description: Desc\n        content:\n          application/json:\n            schema:\n              type: object\n              required: [ order ]\n              properties:\n                order:\n                  type: string\n      responses:\n        200:\n          description: successful operation\n          content:\n            application/json:\n              schema:\n                type: object\n                properties:\n                  id:\n                    type: string\n```\n\n**file.ts**\n\n```js\nimport { someApiMethod } from './api.yaml';\n\n// Basic use case\nsomeApiMethod({\n    // url parameters\n    params: {\n        id: 3,\n    },\n    // query parameters\n    query: {\n        tag: 'some tag',\n    },\n    // request body\n    data: {\n        order: 'asc'\n    }\n})\n    .then(doSomeStuffWithTheResult)\n    .catch(handleError);\n    \n// Request with custom options\nsomeApiMethod({\n    // url parameters\n    params: {\n        id: 3,\n    },\n    // query parameters\n    query: {\n        tag: 'some tag',\n    },\n    // request body\n    data: {\n        order: 'asc',\n    },\n}, {\n    // API base url\n   baseUrl: 'https://github.com', // default process.env.API_BASE_URL || '{{templateOptions.baseUrl}}' || '{{api.server.url}}'\n   \n   // Middleware to run before fetching the request\n   preMiddleware: async (url, params) =\u003e { // default (url: string, params: RequestInit) =\u003e Promise.resolve([url, params])\n       // do some manipulation with the data. for example, get an auth token\n       const token = await getSomeTokenAsync(url, params);\n       \n       // return a tuple\n       return [\n        url,\n        {\n            ...params,\n            headers: { ...params.headers, Authorization: token },\n        }\n        ];\n   },\n})\n    .then(doSomeStuffWithTheResult)\n    .catch(handleError);\n```\n\n\n**Generated code of the sdk client:**\n\u003cdetails\u003e\n  \u003csummary\u003eSee code\u003c/summary\u003e\n  \n  \n```js\nimport Ajv from 'ajv';\nimport { stringify } from 'query-string';\n\nconst ajv = new Ajv({ unknownFormats: ['int32', 'int64', 'binary'] });\n\nexport class ApiError extends Error {\n  constructor({ status, statusText, response, message, headers }) {\n    super(message);\n    this.status = status;\n    this.response = response;\n    this.statusText = statusText;\n    this.headers = headers;\n  }\n}\n\nexport class ClientCodeError extends Error {}\n\nexport class RequestValidationError extends Error {\n  constructor({ message, element, method, errors = [] }) {\n    super(message);\n\n    this.element = element;\n    this.method = method;\n    this.errors = errors;\n  }\n}\n\nexport class ResponseValidationError extends Error {\n  constructor({ message, method, errors = [] }) {\n    super(message);\n\n    this.method = method;\n    this.errors = errors;\n  }\n}\n\nconst defaultConfig = {\n  baseUrl: process.env.API_BASE_URL || 'https://petstore.swagger.io/v2',\n  preMiddleware: (url, params) =\u003e Promise.resolve([url, params]),\n};\n\nexport const someApiMethod = async (\n  { query = {}, params = {}, data = {} } = {},\n  currentConfig = defaultConfig\n) =\u003e {\n  const config = { ...defaultConfig, ...currentConfig };\n\n  let requestUrl = `${config.baseUrl}/some-path/{id}`;\n\n  const querySchema = {\n    type: 'object',\n    required: ['tag'],\n    properties: { tag: { type: 'string' } },\n  };\n\n  function isQuery(obj) {\n    const isValid = ajv.validate(querySchema, obj);\n\n    return !!isValid;\n  }\n\n  if (!isQuery(query)) {\n    throw new RequestValidationError({\n      message: 'Request query string schema validation error',\n      method: 'someApiMethod',\n      element: 'query',\n      errors: ajv.errors || [],\n    });\n  }\n\n  if (Object.keys(query)) {\n    requestUrl = `${requestUrl}?${stringify(query, { arrayFormat: 'bracket' })}`;\n  }\n\n  const paramsSchema = {\n    type: 'object',\n    required: ['id'],\n    properties: { id: { type: 'integer', format: 'int64' } },\n  };\n\n  function isParams(obj) {\n    const isValid = ajv.validate(paramsSchema, obj);\n\n    return !!isValid;\n  }\n\n  if (!isParams(params)) {\n    throw new RequestValidationError({\n      message: 'Request params schema validation error',\n      method: 'someApiMethod',\n      element: 'params',\n      errors: ajv.errors || [],\n    });\n  }\n\n  const paramsKeys = Object.keys(params);\n\n  if (paramsKeys.length) {\n    paramsKeys.forEach((param) =\u003e {\n      requestUrl = requestUrl.replace(`{${param}}`, encodeURIComponent(String(params[param])));\n    });\n  }\n\n  const requestHeaders = {\n    'Content-Type': 'application/json',\n  };\n\n  if (!(data instanceof FormData)) {\n    const bodySchema = {\n      type: 'object',\n      required: ['order'],\n      properties: { order: { type: 'string' } },\n    };\n    const isBodyValid = ajv.validate(bodySchema, data);\n\n    if (!isBodyValid) {\n      throw new RequestValidationError({\n        message: 'Request body schema validation error',\n        method: 'someApiMethod',\n        element: 'body',\n        errors: ajv.errors || [],\n      });\n    }\n  }\n\n  let requestParams;\n\n  if (data) {\n    requestParams = {\n      method: 'POST',\n      headers: requestHeaders,\n      body: data instanceof FormData ? data : JSON.stringify(data),\n    };\n  } else {\n    requestParams = {\n      method: 'POST',\n      headers: requestHeaders,\n    };\n  }\n\n  const [processedUrl, processedParams] = await config.preMiddleware(requestUrl, requestParams);\n  const responseObject = await fetch(processedUrl, processedParams);\n  const response = await responseObject.json();\n\n  if (!responseObject.ok) {\n    throw new ApiError({\n      message: 'Api error while fetching someApiMethod',\n      status: responseObject.status,\n      statusText: responseObject.statusText,\n      response,\n      headers: responseObject.headers,\n    });\n  }\n\n  const responseSchema = { type: 'object', properties: { id: { type: 'string' } } };\n\n  function isResponse(obj) {\n    const isValid = ajv.validate(responseSchema, obj);\n\n    return !!isValid;\n  }\n\n  if (!isResponse(response)) {\n    throw new ResponseValidationError({\n      message: 'Response schema validation error',\n      method: 'someApiMethod',\n      errors: ajv.errors || [],\n    });\n  }\n\n  return response;\n};\n```\n\u003c/details\u003e\n\n## Contributing\n\nPlease take a moment to read our contributing guidelines if you haven't yet done so.\n\n[CONTRIBUTING](./.github/CONTRIBUTING.md)\n\n## License\n\n[MIT](./LICENSE)\n\n\n[npm]: https://img.shields.io/npm/v/openapi-client-sdk-loader.svg\n[npm-url]: https://npmjs.com/package/openapi-client-sdk-loader\n[deps]: https://david-dm.org/aleksandryackovlev/openapi-client-sdk-loader.svg\n[deps-url]: https://david-dm.org/aleksandryackovlev/openapi-client-sdk-loader\n\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Faleksandryackovlev%2Fopenapi-client-sdk-loader","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Faleksandryackovlev%2Fopenapi-client-sdk-loader","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Faleksandryackovlev%2Fopenapi-client-sdk-loader/lists"}