diff --git a/CHANGELOG.md b/CHANGELOG.md index 659694d86..a7859f80e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,15 @@ # Changelog All notable changes to this project will be documented in this file. +## [0.23.0] - 2022-06-02 +### Fixed +- Upgraded dependencies +- Added blank line at the end of generated files +- Added support for Node.js v12 +### Added +- Added `request` property inside `ApiError` +- Added support for `@depricated` inside models and operations + ## [0.22.0] - 2022-04-26 ### Fixed - Upgraded dependencies diff --git a/README.md b/README.md index a1a812950..7c3a945c1 100644 --- a/README.md +++ b/README.md @@ -69,6 +69,8 @@ Documentation - [Nullable props (OpenAPI v2)](docs/nullable-props.md) - [Authorization](docs/authorization.md) - [External references](docs/external-references.md) +- [Canceling requests](docs/canceling-requests.md) +- [Custom request file](docs/custom-request-file.md) Support === diff --git a/docs/canceling-requests.md b/docs/canceling-requests.md new file mode 100644 index 000000000..e7cf76658 --- /dev/null +++ b/docs/canceling-requests.md @@ -0,0 +1,42 @@ +# Canceling requests + +The generated clients support canceling of requests, this works by canceling the promise that +is returned from the request. Each method inside a service (operation) returns a `CancelablePromise` +object. This promise can be canceled by calling the `cancel()` method. + +Below is an example of canceling the request after a certain timeout: + +```typescript +import { UserService } from './myClient'; + +const getAllUsers = async () => { + + const request = UserService.getAllUsers(); + + setTimeout(() => { + if (!request.isResolved() && !request.isRejected()) { + console.warn('Canceling request due to timeout'); + request.cancel(); + } + }, 1000); + + await request; +}; +``` + +The API of the `CancelablePromise` is similar to a regular `Promise`, but it adds the +`cancel()` method and some additional properties: + +```typescript +interface CancelablePromise extends Promise { + readonly isResolved: boolean; + readonly isRejected: boolean; + readonly isCancelled: boolean; + cancel: () => void; +} +``` + +- `isResolved`: Indicates if the promise was resolved. +- `isRejected`: Indicates if the promise was rejected. +- `isCancelled`: Indicates if the promise was canceled. +- `cancel()`: Cancels the promise (and request) and throws a rejection error: `Request aborted`. diff --git a/docs/custom-request-file.md b/docs/custom-request-file.md new file mode 100644 index 000000000..2d50e3fe5 --- /dev/null +++ b/docs/custom-request-file.md @@ -0,0 +1,61 @@ +# Custom request file + +If you want to implement custom logic on the request level, +or implement a client based on a different library, then +one option is to write your own request file and tell +the generator to use this. + +The request file (`request.ts`) can be found inside the +`/core` folder of the generated client. You can modify +that file and use it, or alternatively, you can write +your own. Below is a very simplified example of an Axios +based request file: + +```typescript +import axios from 'axios'; +import type { AxiosError, AxiosRequestConfig, AxiosResponse } from 'axios'; + +import type { ApiRequestOptions } from './ApiRequestOptions'; +import { CancelablePromise } from './CancelablePromise'; +import type { OpenAPIConfig } from './OpenAPI'; + +const axiosInstance = axios.create({ + // Your custom Axios instance config +}); + +export const request = (config: OpenAPIConfig, options: ApiRequestOptions): CancelablePromise => { + return new CancelablePromise((resolve, reject, onCancel) => { + // Get the request URL. Depending on your needs, this might need additional processing, + // @see ./src/templates/core/functions/getUrl.hbs + const url = `${config.BASE}${options.path}`; + + // Optional: Get and link the cancelation token, so the request can be aborted. + const source = axiosInstance.CancelToken.source(); + onCancel(() => source.cancel('The user aborted a request.')); + + // Execute the request. This is a minimal example, in real world scenarios + // you will need to add headers, process form data, etc. + // @see ./src/templates/core/axios/request.hbs + axiosInstance.request({ + url, + data: options.body, + method: options.method, + cancelToken: source.token, + }).then(data => { + resolve(data); + }).catch(error => { + reject(error); + }); + }); +}; +``` + +To use this request file in your generated code you can execute the +following command: + +``` +npx openapi-typescript-codegen --input ./spec.json --output ./generated --request ./request.ts +``` + +The `--request` parameter will tell the generator to not generate the default +`request.ts` file, but instead copy over the custom file that was specified. diff --git a/package.json b/package.json index bc18f59f0..390ea3dc3 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "openapi-typescript-codegen", - "version": "0.22.0", + "version": "0.23.0", "description": "Library that generates Typescript clients based on the OpenAPI specification.", "author": "Ferdi Koomen", "homepage": "https://github.com/ferdikoomen/openapi-typescript-codegen",