From b1604181923636e902e7cb65392a7a1cc37b4762 Mon Sep 17 00:00:00 2001 From: John Egan Date: Wed, 13 Sep 2023 17:46:16 -0500 Subject: [PATCH 1/9] Update package.json --- package.json | 16 +++++----------- 1 file changed, 5 insertions(+), 11 deletions(-) diff --git a/package.json b/package.json index 1f5bb214a..a6ab97ee9 100644 --- a/package.json +++ b/package.json @@ -1,15 +1,15 @@ { "name": "openapi-typescript-codegen", "version": "0.25.0", - "description": "Library that generates Typescript clients based on the OpenAPI specification.", - "author": "Ferdi Koomen", - "homepage": "https://github.com/ferdikoomen/openapi-typescript-codegen", + "description": "Library that generates Typescript clients based on the OpenAPI specification. Fork of ferdikoomen/openapi-typescript-codegen", + "author": "John Egan", + "homepage": "https://github.com/jegan321/openapi-typescript-codegen", "repository": { "type": "git", - "url": "git+https://github.com/ferdikoomen/openapi-typescript-codegen.git" + "url": "git+https://github.com/jegan321/openapi-typescript-codegen.git" }, "bugs": { - "url": "https://github.com/ferdikoomen/openapi-typescript-codegen/issues" + "url": "https://github.com/jegan321/openapi-typescript-codegen/issues" }, "license": "MIT", "keywords": [ @@ -25,12 +25,6 @@ "angular", "node" ], - "maintainers": [ - { - "name": "Ferdi Koomen", - "email": "info@madebyferdi.com" - } - ], "main": "dist/index.js", "types": "types/index.d.ts", "bin": { From 66d562aaee29edfef60a2ee014d4429180991be8 Mon Sep 17 00:00:00 2001 From: John Egan Date: Wed, 13 Sep 2023 17:54:22 -0500 Subject: [PATCH 2/9] Change headers to always be optional --- src/openApi/v2/parser/getOperationParameter.ts | 2 +- src/openApi/v3/parser/getOperationParameter.ts | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/openApi/v2/parser/getOperationParameter.ts b/src/openApi/v2/parser/getOperationParameter.ts index 6b68c9d5a..1f9688ecb 100644 --- a/src/openApi/v2/parser/getOperationParameter.ts +++ b/src/openApi/v2/parser/getOperationParameter.ts @@ -24,7 +24,7 @@ export const getOperationParameter = (openApi: OpenApi, parameter: OpenApiParame description: parameter.description || null, isDefinition: false, isReadOnly: false, - isRequired: parameter.required === true, + isRequired: parameter.in === 'header' ? false : parameter.required === true, // Headers are always optional isNullable: parameter['x-nullable'] === true, format: parameter.format, maximum: parameter.maximum, diff --git a/src/openApi/v3/parser/getOperationParameter.ts b/src/openApi/v3/parser/getOperationParameter.ts index 97a719c96..a454652c7 100644 --- a/src/openApi/v3/parser/getOperationParameter.ts +++ b/src/openApi/v3/parser/getOperationParameter.ts @@ -23,7 +23,7 @@ export const getOperationParameter = (openApi: OpenApi, parameter: OpenApiParame deprecated: parameter.deprecated === true, isDefinition: false, isReadOnly: false, - isRequired: parameter.required === true, + isRequired: parameter.in === 'header' ? false : parameter.required === true, // Headers are always optional isNullable: parameter.nullable === true, imports: [], enum: [], From ca8159e05b0ca0333210cf640ac5a4d242d7457c Mon Sep 17 00:00:00 2001 From: John Egan Date: Wed, 13 Sep 2023 17:54:25 -0500 Subject: [PATCH 3/9] Update README.md --- README.md | 107 ++---------------------------------------------------- 1 file changed, 4 insertions(+), 103 deletions(-) diff --git a/README.md b/README.md index b851329a8..bb2191108 100644 --- a/README.md +++ b/README.md @@ -1,106 +1,7 @@ -# OpenAPI Typescript Codegen +# OpenAPI TypeScript Codegen -[![NPM][npm-image]][npm-url] -[![License][license-image]][license-url] -[![Coverage][coverage-image]][coverage-url] -[![Coverage][coverage-image]][coverage-url] -[![Downloads][downloads-image]][downloads-url] -[![Build][build-image]][build-url] +Fork of [ferdikoomen/openapi-typescript-codegen](https://github.com/ferdikoomen/openapi-typescript-codegen). See that repository for documentation. -> Node.js library that generates Typescript clients based on the OpenAPI specification. +## List of changes -## Why? -- Frontend ❤️ OpenAPI, but we do not want to use JAVA codegen in our builds -- Quick, lightweight, robust and framework-agnostic 🚀 -- Supports generation of TypeScript clients -- Supports generations of Fetch, Node-Fetch, Axios, Angular and XHR http clients -- Supports OpenAPI specification v2.0 and v3.0 -- Supports JSON and YAML files for input -- Supports generation through CLI, Node.js and NPX -- Supports tsc and @babel/plugin-transform-typescript -- Supports aborting of requests (cancelable promise pattern) -- Supports external references using [json-schema-ref-parser](https://github.com/APIDevTools/json-schema-ref-parser/) - -## Install - -``` -npm install openapi-typescript-codegen --save-dev -``` - -## Usage - -``` -$ openapi --help - - Usage: openapi [options] - - Options: - -V, --version output the version number - -i, --input OpenAPI specification, can be a path, url or string content (required) - -o, --output Output directory (required) - -c, --client HTTP client to generate [fetch, xhr, node, axios, angular] (default: "fetch") - --name Custom client class name - --useOptions Use options instead of arguments - --useUnionTypes Use union types instead of enums - --exportCore Write core files to disk (default: true) - --exportServices Write services to disk (default: true) - --exportModels Write models to disk (default: true) - --exportSchemas Write schemas to disk (default: false) - --indent Indentation options [4, 2, tab] (default: "4") - --postfixServices Service name postfix (default: "Service") - --postfixModels Model name postfix - --request Path to custom request file - -h, --help display help for command - - Examples - $ openapi --input ./spec.json --output ./generated - $ openapi --input ./spec.json --output ./generated --client xhr -``` - -## Docker usage - -To build the Docker container, execute the following command: - -``` -docker build . --tag openapi-typescript-codegen -``` - -After this is done, you can execute the CLI commands: - -``` -docker run openapi-typescript-codegen --help -docker run openapi-typescript-codegen --input sample.yaml --output client -``` - -Documentation -=== -- [Basic usage](docs/basic-usage.md) -- [OpenAPI object](docs/openapi-object.md) -- [Client instances](docs/client-instances.md) `--name` -- [Argument vs. Object style](docs/arguments-vs-object-style.md) `--useOptions` -- [Enums vs. Union types](docs/enum-vs-union-types.md) `--useUnionTypes` -- [Runtime schemas](docs/runtime-schemas.md) `--exportSchemas` -- [Enum with custom names and descriptions](docs/custom-enums.md) -- [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 -=== -- [Babel support](docs/babel-support.md) -- [Axios support](docs/axios-support.md) -- [Angular support](docs/angular-support.md) -- [Node-Fetch support](docs/node-fetch-support.md) - -[npm-url]: https://npmjs.org/package/openapi-typescript-codegen -[npm-image]: https://img.shields.io/npm/v/openapi-typescript-codegen.svg -[license-url]: LICENSE -[license-image]: http://img.shields.io/npm/l/openapi-typescript-codegen.svg -[coverage-url]: https://codecov.io/gh/ferdikoomen/openapi-typescript-codegen -[coverage-image]: https://img.shields.io/codecov/c/github/ferdikoomen/openapi-typescript-codegen.svg -[downloads-url]: http://npm-stat.com/charts.html?package=openapi-typescript-codegen -[downloads-image]: http://img.shields.io/npm/dm/openapi-typescript-codegen.svg -[build-url]: https://circleci.com/gh/ferdikoomen/openapi-typescript-codegen/tree/master -[build-image]: https://circleci.com/gh/ferdikoomen/openapi-typescript-codegen/tree/master.svg?style=svg +1. Headers are always optional, whether the Open API JSON says they are required or not. \ No newline at end of file From fa46c7ceff0bfb992b990519d1385c806567b801 Mon Sep 17 00:00:00 2001 From: John Egan Date: Wed, 13 Sep 2023 18:01:13 -0500 Subject: [PATCH 4/9] Update package name for npm --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index a6ab97ee9..06f6ded5e 100644 --- a/package.json +++ b/package.json @@ -1,5 +1,5 @@ { - "name": "openapi-typescript-codegen", + "name": "@jegan321/openapi-typescript-codegen", "version": "0.25.0", "description": "Library that generates Typescript clients based on the OpenAPI specification. Fork of ferdikoomen/openapi-typescript-codegen", "author": "John Egan", From caebc0b8c4a79aebe23047be5096ea074b6d1a21 Mon Sep 17 00:00:00 2001 From: John Egan Date: Wed, 13 Sep 2023 18:01:48 -0500 Subject: [PATCH 5/9] Update package-lock.json --- package-lock.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/package-lock.json b/package-lock.json index f9369c33e..798f8ec6a 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,11 +1,11 @@ { - "name": "openapi-typescript-codegen", + "name": "@jegan321/openapi-typescript-codegen", "version": "0.25.0", "lockfileVersion": 3, "requires": true, "packages": { "": { - "name": "openapi-typescript-codegen", + "name": "@jegan321/openapi-typescript-codegen", "version": "0.25.0", "license": "MIT", "dependencies": { From fcfe86a07aa87fadc5e70b18842c99e0660669d9 Mon Sep 17 00:00:00 2001 From: John Egan Date: Wed, 13 Sep 2023 18:07:42 -0500 Subject: [PATCH 6/9] Add publishConfig --- package.json | 3 +++ 1 file changed, 3 insertions(+) diff --git a/package.json b/package.json index 06f6ded5e..010619f8e 100644 --- a/package.json +++ b/package.json @@ -11,6 +11,9 @@ "bugs": { "url": "https://github.com/jegan321/openapi-typescript-codegen/issues" }, + "publishConfig": { + "access": "public" + }, "license": "MIT", "keywords": [ "openapi", From 83c7341db26c43aa099979e32ba840423a362d97 Mon Sep 17 00:00:00 2001 From: John Egan Date: Tue, 2 Jan 2024 11:05:39 -0600 Subject: [PATCH 7/9] Version 0.25.1 Add error callback --- README.md | 9 ++++-- package.json | 2 +- src/templates/core/OpenAPI.hbs | 2 ++ src/templates/core/angular/request.hbs | 2 +- src/templates/core/axios/request.hbs | 2 +- src/templates/core/fetch/request.hbs | 2 +- .../core/functions/catchErrorCodes.hbs | 9 ++++-- src/templates/core/node/request.hbs | 2 +- src/templates/core/xhr/request.hbs | 2 +- test/__snapshots__/index.spec.ts.snap | 30 +++++++++++++------ 10 files changed, 43 insertions(+), 19 deletions(-) diff --git a/README.md b/README.md index bb2191108..9c871939e 100644 --- a/README.md +++ b/README.md @@ -1,7 +1,12 @@ # OpenAPI TypeScript Codegen -Fork of [ferdikoomen/openapi-typescript-codegen](https://github.com/ferdikoomen/openapi-typescript-codegen). See that repository for documentation. +Fork of [ferdikoomen/openapi-typescript-codegen](https://github.com/ferdikoomen/openapi-typescript-codegen). See that repository for more documentation. ## List of changes +1. Headers are always optional, whether the OpenAPI JSON says they are required or not. +2. Added an optional config property called `ERROR_CALLBACK` which is a function that will run before API errors are thrown. -1. Headers are always optional, whether the Open API JSON says they are required or not. \ No newline at end of file +## Testing +1. Run `npm test` to run automated tests +2. If a snapshot test fails due to an intentional change, run `npm run test:update` to update the snapshots +3. To test local changes with your application, first run `npm run build`. Then, replace `npx @jegan321/openapi-typescript-codegen` with `node ../openapi-typescript-codegen/bin/index.js` in your application-side script. diff --git a/package.json b/package.json index 010619f8e..a1d4eb731 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@jegan321/openapi-typescript-codegen", - "version": "0.25.0", + "version": "0.25.1", "description": "Library that generates Typescript clients based on the OpenAPI specification. Fork of ferdikoomen/openapi-typescript-codegen", "author": "John Egan", "homepage": "https://github.com/jegan321/openapi-typescript-codegen", diff --git a/src/templates/core/OpenAPI.hbs b/src/templates/core/OpenAPI.hbs index 7b9560a26..5e88418b5 100644 --- a/src/templates/core/OpenAPI.hbs +++ b/src/templates/core/OpenAPI.hbs @@ -1,6 +1,7 @@ {{>header}} import type { ApiRequestOptions } from './ApiRequestOptions'; +import { ApiError } from './ApiError'; type Resolver = (options: ApiRequestOptions) => Promise; type Headers = Record; @@ -15,6 +16,7 @@ export type OpenAPIConfig = { PASSWORD?: string | Resolver | undefined; HEADERS?: Headers | Resolver | undefined; ENCODE_PATH?: ((path: string) => string) | undefined; + ERROR_CALLBACK?: (error: ApiError) => void; }; export const OpenAPI: OpenAPIConfig = { diff --git a/src/templates/core/angular/request.hbs b/src/templates/core/angular/request.hbs index 57c98516e..dff442424 100644 --- a/src/templates/core/angular/request.hbs +++ b/src/templates/core/angular/request.hbs @@ -100,7 +100,7 @@ export const request = (config: OpenAPIConfig, http: HttpClient, options: Api } as ApiResult); }), map(result => { - catchErrorCodes(options, result); + catchErrorCodes(config, options, result); return result.body as T; }), catchError((error: ApiError) => { diff --git a/src/templates/core/axios/request.hbs b/src/templates/core/axios/request.hbs index 6612f1614..01434eccb 100644 --- a/src/templates/core/axios/request.hbs +++ b/src/templates/core/axios/request.hbs @@ -91,7 +91,7 @@ export const request = (config: OpenAPIConfig, options: ApiRequestOptions, ax body: responseHeader ?? responseBody, }; - catchErrorCodes(options, result); + catchErrorCodes(config, options, result); resolve(result.body); } diff --git a/src/templates/core/fetch/request.hbs b/src/templates/core/fetch/request.hbs index 4af6f9440..0e01ad80d 100644 --- a/src/templates/core/fetch/request.hbs +++ b/src/templates/core/fetch/request.hbs @@ -83,7 +83,7 @@ export const request = (config: OpenAPIConfig, options: ApiRequestOptions): C body: responseHeader ?? responseBody, }; - catchErrorCodes(options, result); + catchErrorCodes(config, options, result); resolve(result.body); } diff --git a/src/templates/core/functions/catchErrorCodes.hbs b/src/templates/core/functions/catchErrorCodes.hbs index 42f69d071..2c5c02fb6 100644 --- a/src/templates/core/functions/catchErrorCodes.hbs +++ b/src/templates/core/functions/catchErrorCodes.hbs @@ -1,6 +1,6 @@ -export const catchErrorCodes = (options: ApiRequestOptions, result: ApiResult): void => { +export const catchErrorCodes = (config: OpenAPIConfig, options: ApiRequestOptions, result: ApiResult): void => { const errors: Record = { 400: 'Bad Request', 401: 'Unauthorized', @@ -14,7 +14,12 @@ export const catchErrorCodes = (options: ApiRequestOptions, result: ApiResult): const error = errors[result.status]; if (error) { - throw new ApiError(options, result, error); + const apiError = new ApiError(options, result, error); + const errorCallback = config.ERROR_CALLBACK; + if (errorCallback) { + errorCallback(apiError); + } + throw apiError; } if (!result.ok) { diff --git a/src/templates/core/node/request.hbs b/src/templates/core/node/request.hbs index 8e6f6110e..0476d5995 100644 --- a/src/templates/core/node/request.hbs +++ b/src/templates/core/node/request.hbs @@ -88,7 +88,7 @@ export const request = (config: OpenAPIConfig, options: ApiRequestOptions): C body: responseHeader ?? responseBody, }; - catchErrorCodes(options, result); + catchErrorCodes(config, options, result); resolve(result.body); } diff --git a/src/templates/core/xhr/request.hbs b/src/templates/core/xhr/request.hbs index 47f92870b..ca8e4cba3 100644 --- a/src/templates/core/xhr/request.hbs +++ b/src/templates/core/xhr/request.hbs @@ -86,7 +86,7 @@ export const request = (config: OpenAPIConfig, options: ApiRequestOptions): C body: responseHeader ?? responseBody, }; - catchErrorCodes(options, result); + catchErrorCodes(config, options, result); resolve(result.body); } diff --git a/test/__snapshots__/index.spec.ts.snap b/test/__snapshots__/index.spec.ts.snap index ef6b18554..029be566c 100644 --- a/test/__snapshots__/index.spec.ts.snap +++ b/test/__snapshots__/index.spec.ts.snap @@ -206,6 +206,7 @@ exports[`v2 should generate: test/generated/v2/core/OpenAPI.ts 1`] = ` /* tslint:disable */ /* eslint-disable */ import type { ApiRequestOptions } from './ApiRequestOptions'; +import { ApiError } from './ApiError'; type Resolver = (options: ApiRequestOptions) => Promise; type Headers = Record; @@ -220,6 +221,7 @@ export type OpenAPIConfig = { PASSWORD?: string | Resolver | undefined; HEADERS?: Headers | Resolver | undefined; ENCODE_PATH?: ((path: string) => string) | undefined; + ERROR_CALLBACK?: (error: ApiError) => void; }; export const OpenAPI: OpenAPIConfig = { @@ -500,6 +502,10 @@ export const catchErrorCodes = (options: ApiRequestOptions, result: ApiResult): const error = errors[result.status]; if (error) { + const errorCallback = OpenAPI.ERROR_CALLBACK; + if (errorCallback) { + errorCallback(new ApiError(options, result, error)); + } throw new ApiError(options, result, error); } @@ -2821,19 +2827,19 @@ import { OpenAPI } from '../core/OpenAPI'; import { request as __request } from '../core/request'; export class ParametersService { /** - * @param parameterHeader This is the parameter that goes into the header * @param parameterQuery This is the parameter that goes into the query params * @param parameterForm This is the parameter that goes into the form data * @param parameterBody This is the parameter that is sent as request body * @param parameterPath This is the parameter that goes into the path + * @param parameterHeader This is the parameter that goes into the header * @throws ApiError */ public static callWithParameters( - parameterHeader: string, parameterQuery: string, parameterForm: string, parameterBody: string, parameterPath: string, + parameterHeader?: string, ): CancelablePromise { return __request(OpenAPI, { method: 'POST', @@ -2854,7 +2860,6 @@ export class ParametersService { }); } /** - * @param parameterHeader This is the parameter that goes into the request header * @param parameterQuery This is the parameter that goes into the request query params * @param parameterForm This is the parameter that goes into the request form data * @param parameterBody This is the parameter that is sent as request body @@ -2862,10 +2867,10 @@ export class ParametersService { * @param parameterPath2 This is the parameter that goes into the path * @param parameterPath3 This is the parameter that goes into the path * @param _default This is the parameter with a reserved keyword + * @param parameterHeader This is the parameter that goes into the request header * @throws ApiError */ public static callWithWeirdParameterNames( - parameterHeader: string, parameterQuery: string, parameterForm: string, parameterBody: string, @@ -2873,6 +2878,7 @@ export class ParametersService { parameterPath2?: string, parameterPath3?: string, _default?: string, + parameterHeader?: string, ): CancelablePromise { return __request(OpenAPI, { method: 'POST', @@ -3299,6 +3305,7 @@ exports[`v3 should generate: test/generated/v3/core/OpenAPI.ts 1`] = ` /* tslint:disable */ /* eslint-disable */ import type { ApiRequestOptions } from './ApiRequestOptions'; +import { ApiError } from './ApiError'; type Resolver = (options: ApiRequestOptions) => Promise; type Headers = Record; @@ -3313,6 +3320,7 @@ export type OpenAPIConfig = { PASSWORD?: string | Resolver | undefined; HEADERS?: Headers | Resolver | undefined; ENCODE_PATH?: ((path: string) => string) | undefined; + ERROR_CALLBACK?: (error: ApiError) => void; }; export const OpenAPI: OpenAPIConfig = { @@ -3593,6 +3601,10 @@ export const catchErrorCodes = (options: ApiRequestOptions, result: ApiResult): const error = errors[result.status]; if (error) { + const errorCallback = OpenAPI.ERROR_CALLBACK; + if (errorCallback) { + errorCallback(new ApiError(options, result, error)); + } throw new ApiError(options, result, error); } @@ -6621,7 +6633,7 @@ export class DeprecatedService { * @throws ApiError */ public static deprecatedCall( - parameter: DeprecatedModel | null, + parameter?: DeprecatedModel | null, ): CancelablePromise { return __request(OpenAPI, { method: 'POST', @@ -6997,21 +7009,21 @@ import { OpenAPI } from '../core/OpenAPI'; import { request as __request } from '../core/request'; export class ParametersService { /** - * @param parameterHeader This is the parameter that goes into the header * @param parameterQuery This is the parameter that goes into the query params * @param parameterForm This is the parameter that goes into the form data * @param parameterCookie This is the parameter that goes into the cookie * @param parameterPath This is the parameter that goes into the path * @param requestBody This is the parameter that goes into the body + * @param parameterHeader This is the parameter that goes into the header * @throws ApiError */ public static callWithParameters( - parameterHeader: string | null, parameterQuery: string | null, parameterForm: string | null, parameterCookie: string | null, parameterPath: string | null, requestBody: ModelWithString | null, + parameterHeader?: string | null, ): CancelablePromise { return __request(OpenAPI, { method: 'POST', @@ -7036,7 +7048,6 @@ export class ParametersService { }); } /** - * @param parameterHeader This is the parameter that goes into the request header * @param parameterQuery This is the parameter that goes into the request query params * @param parameterForm This is the parameter that goes into the request form data * @param parameterCookie This is the parameter that goes into the cookie @@ -7045,10 +7056,10 @@ export class ParametersService { * @param parameterPath2 This is the parameter that goes into the path * @param parameterPath3 This is the parameter that goes into the path * @param _default This is the parameter with a reserved keyword + * @param parameterHeader This is the parameter that goes into the request header * @throws ApiError */ public static callWithWeirdParameterNames( - parameterHeader: string | null, parameterQuery: string | null, parameterForm: string | null, parameterCookie: string | null, @@ -7057,6 +7068,7 @@ export class ParametersService { parameterPath2?: string, parameterPath3?: string, _default?: string, + parameterHeader?: string | null, ): CancelablePromise { return __request(OpenAPI, { method: 'POST', From f32ebefe80c615dfd7859cdd238d6905e2d9f126 Mon Sep 17 00:00:00 2001 From: John Egan Date: Tue, 12 Nov 2024 13:34:38 -0600 Subject: [PATCH 8/9] Version 0.25.2 --- README.md | 7 +++++++ package.json | 2 +- src/templates/core/OpenAPI.hbs | 3 +++ src/templates/core/angular/request.hbs | 10 +++++++++- src/templates/core/axios/request.hbs | 7 +++++++ src/templates/core/fetch/request.hbs | 7 +++++++ src/templates/core/node/request.hbs | 7 +++++++ src/templates/core/xhr/request.hbs | 7 +++++++ test/__snapshots__/index.spec.ts.snap | 22 ++++++++++++---------- 9 files changed, 60 insertions(+), 12 deletions(-) diff --git a/README.md b/README.md index 9c871939e..b16bc6d8e 100644 --- a/README.md +++ b/README.md @@ -5,8 +5,15 @@ Fork of [ferdikoomen/openapi-typescript-codegen](https://github.com/ferdikoomen/ ## List of changes 1. Headers are always optional, whether the OpenAPI JSON says they are required or not. 2. Added an optional config property called `ERROR_CALLBACK` which is a function that will run before API errors are thrown. +3. Ability to run code before or after each request using `BEFORE_REQUEST` and `BEFORE_REQUEST` config ## Testing 1. Run `npm test` to run automated tests 2. If a snapshot test fails due to an intentional change, run `npm run test:update` to update the snapshots 3. To test local changes with your application, first run `npm run build`. Then, replace `npx @jegan321/openapi-typescript-codegen` with `node ../openapi-typescript-codegen/bin/index.js` in your application-side script. + +## Release +1. Update package.json with a new version +2. `npm run release` +3. `npm publish` +4. Commit changes diff --git a/package.json b/package.json index a1d4eb731..cc6562ac5 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@jegan321/openapi-typescript-codegen", - "version": "0.25.1", + "version": "0.25.2", "description": "Library that generates Typescript clients based on the OpenAPI specification. Fork of ferdikoomen/openapi-typescript-codegen", "author": "John Egan", "homepage": "https://github.com/jegan321/openapi-typescript-codegen", diff --git a/src/templates/core/OpenAPI.hbs b/src/templates/core/OpenAPI.hbs index 5e88418b5..5b5781000 100644 --- a/src/templates/core/OpenAPI.hbs +++ b/src/templates/core/OpenAPI.hbs @@ -2,6 +2,7 @@ import type { ApiRequestOptions } from './ApiRequestOptions'; import { ApiError } from './ApiError'; +import { ApiResult } from './ApiResult'; type Resolver = (options: ApiRequestOptions) => Promise; type Headers = Record; @@ -17,6 +18,8 @@ export type OpenAPIConfig = { HEADERS?: Headers | Resolver | undefined; ENCODE_PATH?: ((path: string) => string) | undefined; ERROR_CALLBACK?: (error: ApiError) => void; + BEFORE_REQUEST?: (options: ApiRequestOptions) => void; + AFTER_REQUEST?: (apiResult: ApiResult) => void; }; export const OpenAPI: OpenAPIConfig = { diff --git a/src/templates/core/angular/request.hbs b/src/templates/core/angular/request.hbs index dff442424..4ba61ee66 100644 --- a/src/templates/core/angular/request.hbs +++ b/src/templates/core/angular/request.hbs @@ -72,6 +72,10 @@ export const request = (config: OpenAPIConfig, http: HttpClient, options: Api const formData = getFormData(options); const body = getRequestBody(options); + if (config.BEFORE_REQUEST) { + config.BEFORE_REQUEST(options); + } + return getHeaders(config, options).pipe( switchMap(headers => { return sendRequest(config, options, http, url, formData, body, headers); @@ -79,13 +83,17 @@ export const request = (config: OpenAPIConfig, http: HttpClient, options: Api map(response => { const responseBody = getResponseBody(response); const responseHeader = getResponseHeader(response, options.responseHeader); - return { + const result = { url, ok: response.ok, status: response.status, statusText: response.statusText, body: responseHeader ?? responseBody, } as ApiResult; + if (config.AFTER_REQUEST) { + config.AFTER_REQUEST(result); + } + return result; }), catchError((error: HttpErrorResponse) => { if (!error.status) { diff --git a/src/templates/core/axios/request.hbs b/src/templates/core/axios/request.hbs index 01434eccb..39944ecb8 100644 --- a/src/templates/core/axios/request.hbs +++ b/src/templates/core/axios/request.hbs @@ -73,6 +73,9 @@ import type { OpenAPIConfig } from './OpenAPI'; export const request = (config: OpenAPIConfig, options: ApiRequestOptions, axiosClient: AxiosInstance = axios): CancelablePromise => { return new CancelablePromise(async (resolve, reject, onCancel) => { try { + if (config.BEFORE_REQUEST) { + config.BEFORE_REQUEST(options); + } const url = getUrl(config, options); const formData = getFormData(options); const body = getRequestBody(options); @@ -91,6 +94,10 @@ export const request = (config: OpenAPIConfig, options: ApiRequestOptions, ax body: responseHeader ?? responseBody, }; + if (config.AFTER_REQUEST) { + config.AFTER_REQUEST(result); + } + catchErrorCodes(config, options, result); resolve(result.body); diff --git a/src/templates/core/fetch/request.hbs b/src/templates/core/fetch/request.hbs index 0e01ad80d..ff253083b 100644 --- a/src/templates/core/fetch/request.hbs +++ b/src/templates/core/fetch/request.hbs @@ -65,6 +65,9 @@ import type { OpenAPIConfig } from './OpenAPI'; export const request = (config: OpenAPIConfig, options: ApiRequestOptions): CancelablePromise => { return new CancelablePromise(async (resolve, reject, onCancel) => { try { + if (config.BEFORE_REQUEST) { + config.BEFORE_REQUEST(options); + } const url = getUrl(config, options); const formData = getFormData(options); const body = getRequestBody(options); @@ -83,6 +86,10 @@ export const request = (config: OpenAPIConfig, options: ApiRequestOptions): C body: responseHeader ?? responseBody, }; + if (config.AFTER_REQUEST) { + config.AFTER_REQUEST(result); + } + catchErrorCodes(config, options, result); resolve(result.body); diff --git a/src/templates/core/node/request.hbs b/src/templates/core/node/request.hbs index 0476d5995..5d72596b9 100644 --- a/src/templates/core/node/request.hbs +++ b/src/templates/core/node/request.hbs @@ -70,6 +70,9 @@ import type { OpenAPIConfig } from './OpenAPI'; export const request = (config: OpenAPIConfig, options: ApiRequestOptions): CancelablePromise => { return new CancelablePromise(async (resolve, reject, onCancel) => { try { + if (config.BEFORE_REQUEST) { + config.BEFORE_REQUEST(options); + } const url = getUrl(config, options); const formData = getFormData(options); const body = getRequestBody(options); @@ -88,6 +91,10 @@ export const request = (config: OpenAPIConfig, options: ApiRequestOptions): C body: responseHeader ?? responseBody, }; + if (config.AFTER_REQUEST) { + config.AFTER_REQUEST(result); + } + catchErrorCodes(config, options, result); resolve(result.body); diff --git a/src/templates/core/xhr/request.hbs b/src/templates/core/xhr/request.hbs index ca8e4cba3..bb62e78c5 100644 --- a/src/templates/core/xhr/request.hbs +++ b/src/templates/core/xhr/request.hbs @@ -68,6 +68,9 @@ import type { OpenAPIConfig } from './OpenAPI'; export const request = (config: OpenAPIConfig, options: ApiRequestOptions): CancelablePromise => { return new CancelablePromise(async (resolve, reject, onCancel) => { try { + if (config.BEFORE_REQUEST) { + config.BEFORE_REQUEST(options); + } const url = getUrl(config, options); const formData = getFormData(options); const body = getRequestBody(options); @@ -86,6 +89,10 @@ export const request = (config: OpenAPIConfig, options: ApiRequestOptions): C body: responseHeader ?? responseBody, }; + if (config.AFTER_REQUEST) { + config.AFTER_REQUEST(result); + } + catchErrorCodes(config, options, result); resolve(result.body); diff --git a/test/__snapshots__/index.spec.ts.snap b/test/__snapshots__/index.spec.ts.snap index 029be566c..d80eb06a3 100644 --- a/test/__snapshots__/index.spec.ts.snap +++ b/test/__snapshots__/index.spec.ts.snap @@ -488,7 +488,7 @@ export const getResponseBody = async (response: Response): Promise => { return undefined; }; -export const catchErrorCodes = (options: ApiRequestOptions, result: ApiResult): void => { +export const catchErrorCodes = (config: OpenAPIConfig, options: ApiRequestOptions, result: ApiResult): void => { const errors: Record = { 400: 'Bad Request', 401: 'Unauthorized', @@ -502,11 +502,12 @@ export const catchErrorCodes = (options: ApiRequestOptions, result: ApiResult): const error = errors[result.status]; if (error) { - const errorCallback = OpenAPI.ERROR_CALLBACK; + const apiError = new ApiError(options, result, error); + const errorCallback = config.ERROR_CALLBACK; if (errorCallback) { - errorCallback(new ApiError(options, result, error)); + errorCallback(apiError); } - throw new ApiError(options, result, error); + throw apiError; } if (!result.ok) { @@ -554,7 +555,7 @@ export const request = (config: OpenAPIConfig, options: ApiRequestOptions): C body: responseHeader ?? responseBody, }; - catchErrorCodes(options, result); + catchErrorCodes(config, options, result); resolve(result.body); } @@ -3587,7 +3588,7 @@ export const getResponseBody = async (response: Response): Promise => { return undefined; }; -export const catchErrorCodes = (options: ApiRequestOptions, result: ApiResult): void => { +export const catchErrorCodes = (config: OpenAPIConfig, options: ApiRequestOptions, result: ApiResult): void => { const errors: Record = { 400: 'Bad Request', 401: 'Unauthorized', @@ -3601,11 +3602,12 @@ export const catchErrorCodes = (options: ApiRequestOptions, result: ApiResult): const error = errors[result.status]; if (error) { - const errorCallback = OpenAPI.ERROR_CALLBACK; + const apiError = new ApiError(options, result, error); + const errorCallback = config.ERROR_CALLBACK; if (errorCallback) { - errorCallback(new ApiError(options, result, error)); + errorCallback(apiError); } - throw new ApiError(options, result, error); + throw apiError; } if (!result.ok) { @@ -3653,7 +3655,7 @@ export const request = (config: OpenAPIConfig, options: ApiRequestOptions): C body: responseHeader ?? responseBody, }; - catchErrorCodes(options, result); + catchErrorCodes(config, options, result); resolve(result.body); } From 77fcf413717596aab1f972d12e061bcd005dd50a Mon Sep 17 00:00:00 2001 From: John Egan Date: Thu, 14 Nov 2024 12:47:33 -0600 Subject: [PATCH 9/9] Version 0.25.3 --- package.json | 2 +- src/templates/core/OpenAPI.hbs | 2 +- test/__snapshots__/index.spec.ts.snap | 20 ++++++++++++++++++++ 3 files changed, 22 insertions(+), 2 deletions(-) diff --git a/package.json b/package.json index cc6562ac5..f0baf3df9 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@jegan321/openapi-typescript-codegen", - "version": "0.25.2", + "version": "0.25.3", "description": "Library that generates Typescript clients based on the OpenAPI specification. Fork of ferdikoomen/openapi-typescript-codegen", "author": "John Egan", "homepage": "https://github.com/jegan321/openapi-typescript-codegen", diff --git a/src/templates/core/OpenAPI.hbs b/src/templates/core/OpenAPI.hbs index 5b5781000..1a273fdfc 100644 --- a/src/templates/core/OpenAPI.hbs +++ b/src/templates/core/OpenAPI.hbs @@ -1,8 +1,8 @@ {{>header}} import type { ApiRequestOptions } from './ApiRequestOptions'; +import type { ApiResult } from './ApiResult'; import { ApiError } from './ApiError'; -import { ApiResult } from './ApiResult'; type Resolver = (options: ApiRequestOptions) => Promise; type Headers = Record; diff --git a/test/__snapshots__/index.spec.ts.snap b/test/__snapshots__/index.spec.ts.snap index d80eb06a3..9f32216b2 100644 --- a/test/__snapshots__/index.spec.ts.snap +++ b/test/__snapshots__/index.spec.ts.snap @@ -207,6 +207,7 @@ exports[`v2 should generate: test/generated/v2/core/OpenAPI.ts 1`] = ` /* eslint-disable */ import type { ApiRequestOptions } from './ApiRequestOptions'; import { ApiError } from './ApiError'; +import { ApiResult } from './ApiResult'; type Resolver = (options: ApiRequestOptions) => Promise; type Headers = Record; @@ -222,6 +223,8 @@ export type OpenAPIConfig = { HEADERS?: Headers | Resolver | undefined; ENCODE_PATH?: ((path: string) => string) | undefined; ERROR_CALLBACK?: (error: ApiError) => void; + BEFORE_REQUEST?: (options: ApiRequestOptions) => void; + AFTER_REQUEST?: (apiResult: ApiResult) => void; }; export const OpenAPI: OpenAPIConfig = { @@ -537,6 +540,9 @@ export const catchErrorCodes = (config: OpenAPIConfig, options: ApiRequestOption export const request = (config: OpenAPIConfig, options: ApiRequestOptions): CancelablePromise => { return new CancelablePromise(async (resolve, reject, onCancel) => { try { + if (config.BEFORE_REQUEST) { + config.BEFORE_REQUEST(options); + } const url = getUrl(config, options); const formData = getFormData(options); const body = getRequestBody(options); @@ -555,6 +561,10 @@ export const request = (config: OpenAPIConfig, options: ApiRequestOptions): C body: responseHeader ?? responseBody, }; + if (config.AFTER_REQUEST) { + config.AFTER_REQUEST(result); + } + catchErrorCodes(config, options, result); resolve(result.body); @@ -3307,6 +3317,7 @@ exports[`v3 should generate: test/generated/v3/core/OpenAPI.ts 1`] = ` /* eslint-disable */ import type { ApiRequestOptions } from './ApiRequestOptions'; import { ApiError } from './ApiError'; +import { ApiResult } from './ApiResult'; type Resolver = (options: ApiRequestOptions) => Promise; type Headers = Record; @@ -3322,6 +3333,8 @@ export type OpenAPIConfig = { HEADERS?: Headers | Resolver | undefined; ENCODE_PATH?: ((path: string) => string) | undefined; ERROR_CALLBACK?: (error: ApiError) => void; + BEFORE_REQUEST?: (options: ApiRequestOptions) => void; + AFTER_REQUEST?: (apiResult: ApiResult) => void; }; export const OpenAPI: OpenAPIConfig = { @@ -3637,6 +3650,9 @@ export const catchErrorCodes = (config: OpenAPIConfig, options: ApiRequestOption export const request = (config: OpenAPIConfig, options: ApiRequestOptions): CancelablePromise => { return new CancelablePromise(async (resolve, reject, onCancel) => { try { + if (config.BEFORE_REQUEST) { + config.BEFORE_REQUEST(options); + } const url = getUrl(config, options); const formData = getFormData(options); const body = getRequestBody(options); @@ -3655,6 +3671,10 @@ export const request = (config: OpenAPIConfig, options: ApiRequestOptions): C body: responseHeader ?? responseBody, }; + if (config.AFTER_REQUEST) { + config.AFTER_REQUEST(result); + } + catchErrorCodes(config, options, result); resolve(result.body);