From 372d31cacbe5b9cb011d8b0a4f1ff7d92fc1c220 Mon Sep 17 00:00:00 2001 From: Ferdi Koomen Date: Mon, 24 Jan 2022 23:06:51 +0100 Subject: [PATCH 01/19] - Bumped version --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 40ba6bc4..fe8f9b22 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "openapi-typescript-codegen", - "version": "0.13.0", + "version": "0.14.0", "description": "Library that generates Typescript clients based on the OpenAPI specification.", "author": "Ferdi Koomen", "homepage": "https://github.com/ferdikoomen/openapi-typescript-codegen", From c5bace8535b6e35f41f8adece9dce91923fc26bf Mon Sep 17 00:00:00 2001 From: Ferdi Koomen Date: Mon, 24 Jan 2022 23:16:21 +0100 Subject: [PATCH 02/19] - Added changelog --- CHANGELOG.md | 9 +++++++++ 1 file changed, 9 insertions(+) create mode 100644 CHANGELOG.md diff --git a/CHANGELOG.md b/CHANGELOG.md new file mode 100644 index 00000000..c287ab18 --- /dev/null +++ b/CHANGELOG.md @@ -0,0 +1,9 @@ +# Changelog +All notable changes to this project will be documented in this file. + +## [0.14.0] - 2021-01-24 +### Changed +- Updated escaping of comments and descriptions +- Added missing `postfix` options to typedef +- Better handling of services without tags +- Updated dependencies From cecc7c5a7ccd2aa5084d83fe6a2a36afb2d30c92 Mon Sep 17 00:00:00 2001 From: Ferdi Koomen Date: Mon, 24 Jan 2022 23:18:43 +0100 Subject: [PATCH 03/19] v0.15.0 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index fe8f9b22..0008a311 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "openapi-typescript-codegen", - "version": "0.14.0", + "version": "0.15.0", "description": "Library that generates Typescript clients based on the OpenAPI specification.", "author": "Ferdi Koomen", "homepage": "https://github.com/ferdikoomen/openapi-typescript-codegen", From ad854a9738cd6ba1a2e53fcbc07a1fea15347ff2 Mon Sep 17 00:00:00 2001 From: Ferdi Koomen Date: Mon, 24 Jan 2022 23:19:43 +0100 Subject: [PATCH 04/19] - Fixed typo --- CHANGELOG.md | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index c287ab18..edeb2a4e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,9 +1,13 @@ # Changelog All notable changes to this project will be documented in this file. +## [0.15.0] - 2021-01-24 +### Added +- Added change log and releases on GitHub + ## [0.14.0] - 2021-01-24 -### Changed -- Updated escaping of comments and descriptions +### Fixed - Added missing `postfix` options to typedef +- Updated escaping of comments and descriptions - Better handling of services without tags - Updated dependencies From 6f2a714a159fee1acbef5cb32211a3ea9f26525e Mon Sep 17 00:00:00 2001 From: Ferdi Koomen Date: Tue, 25 Jan 2022 00:00:47 +0100 Subject: [PATCH 05/19] - Working on formatter for spacing --- .editorconfig | 3 + .eslintignore | 1 + src/templates/core/ApiError.hbs | 24 +-- src/templates/core/ApiRequestOptions.hbs | 20 +- src/templates/core/ApiResult.hbs | 10 +- src/templates/core/CancelablePromise.hbs | 200 +++++++++--------- src/templates/core/OpenAPI.hbs | 36 ++-- src/templates/core/axios/getHeaders.hbs | 48 ++--- src/templates/core/axios/getRequestBody.hbs | 8 +- src/templates/core/axios/getResponseBody.hbs | 8 +- .../core/axios/getResponseHeader.hbs | 14 +- src/templates/core/axios/request.hbs | 48 ++--- src/templates/core/axios/sendRequest.hbs | 50 ++--- src/templates/core/fetch/getHeaders.hbs | 68 +++--- src/templates/core/fetch/getRequestBody.hbs | 20 +- src/templates/core/fetch/getResponseBody.hbs | 32 +-- .../core/fetch/getResponseHeader.hbs | 14 +- src/templates/core/fetch/request.hbs | 48 ++--- src/templates/core/fetch/sendRequest.hbs | 36 ++-- src/templates/core/functions/base64.hbs | 12 +- src/templates/core/functions/catchErrors.hbs | 34 +-- src/templates/core/functions/getFormData.hbs | 42 ++-- .../core/functions/getQueryString.hbs | 48 ++--- src/templates/core/functions/getUrl.hbs | 12 +- src/templates/core/functions/isBlob.hbs | 20 +- src/templates/core/functions/isDefined.hbs | 2 +- src/templates/core/functions/isFormData.hbs | 4 +- src/templates/core/functions/isString.hbs | 2 +- .../core/functions/isStringWithValue.hbs | 2 +- src/templates/core/functions/isSuccess.hbs | 2 +- src/templates/core/functions/resolve.hbs | 8 +- src/templates/core/node/getHeaders.hbs | 68 +++--- src/templates/core/node/getRequestBody.hbs | 20 +- src/templates/core/node/getResponseBody.hbs | 32 +-- src/templates/core/node/getResponseHeader.hbs | 14 +- src/templates/core/node/request.hbs | 48 ++--- src/templates/core/node/sendRequest.hbs | 30 +-- src/templates/core/xhr/getHeaders.hbs | 68 +++--- src/templates/core/xhr/getRequestBody.hbs | 20 +- src/templates/core/xhr/getResponseBody.hbs | 32 +-- src/templates/core/xhr/getResponseHeader.hbs | 14 +- src/templates/core/xhr/request.hbs | 48 ++--- src/templates/core/xhr/sendRequest.hbs | 38 ++-- src/templates/exportService.hbs | 158 +++++++------- src/templates/partials/exportComposition.hbs | 24 +-- src/templates/partials/exportEnum.hbs | 24 +-- src/templates/partials/exportInterface.hbs | 40 ++-- src/templates/partials/schemaArray.hbs | 16 +- src/templates/partials/schemaComposition.hbs | 12 +- src/templates/partials/schemaDictionary.hbs | 16 +- src/templates/partials/schemaEnum.hbs | 8 +- src/templates/partials/schemaGeneric.hbs | 38 ++-- src/templates/partials/schemaInterface.hbs | 18 +- src/utils/format.spec.ts | 8 +- src/utils/format.ts | 2 +- src/utils/indent.ts | 9 + src/utils/writeClientCore.ts | 13 +- src/utils/writeClientModels.ts | 3 +- src/utils/writeClientSchemas.ts | 3 +- src/utils/writeClientServices.ts | 3 +- 60 files changed, 860 insertions(+), 843 deletions(-) create mode 100644 src/utils/indent.ts diff --git a/.editorconfig b/.editorconfig index d741e40b..14a33bde 100755 --- a/.editorconfig +++ b/.editorconfig @@ -7,3 +7,6 @@ trim_trailing_whitespace = true insert_final_newline = true indent_style = space indent_size = 4 + +[*.hbs] +indent_style = tab diff --git a/.eslintignore b/.eslintignore index 8d68273b..9c1a3bc4 100644 --- a/.eslintignore +++ b/.eslintignore @@ -1,4 +1,5 @@ dist +samples test/generated test/e2e/generated node_modules diff --git a/src/templates/core/ApiError.hbs b/src/templates/core/ApiError.hbs index a9eee2a6..19af17e1 100644 --- a/src/templates/core/ApiError.hbs +++ b/src/templates/core/ApiError.hbs @@ -3,18 +3,18 @@ import type { ApiResult } from './ApiResult'; export class ApiError extends Error { - public readonly url: string; - public readonly status: number; - public readonly statusText: string; - public readonly body: any; + public readonly url: string; + public readonly status: number; + public readonly statusText: string; + public readonly body: any; - constructor(response: ApiResult, message: string) { - super(message); + constructor(response: ApiResult, message: string) { + super(message); - this.name = 'ApiError'; - this.url = response.url; - this.status = response.status; - this.statusText = response.statusText; - this.body = response.body; - } + this.name = 'ApiError'; + this.url = response.url; + this.status = response.status; + this.statusText = response.statusText; + this.body = response.body; + } } diff --git a/src/templates/core/ApiRequestOptions.hbs b/src/templates/core/ApiRequestOptions.hbs index 5b4b5836..690c19f8 100644 --- a/src/templates/core/ApiRequestOptions.hbs +++ b/src/templates/core/ApiRequestOptions.hbs @@ -1,14 +1,14 @@ {{>header}} export type ApiRequestOptions = { - readonly method: 'GET' | 'PUT' | 'POST' | 'DELETE' | 'OPTIONS' | 'HEAD' | 'PATCH'; - readonly path: string; - readonly cookies?: Record; - readonly headers?: Record; - readonly query?: Record; - readonly formData?: Record; - readonly body?: any; - readonly mediaType?: string; - readonly responseHeader?: string; - readonly errors?: Record; + readonly method: 'GET' | 'PUT' | 'POST' | 'DELETE' | 'OPTIONS' | 'HEAD' | 'PATCH'; + readonly path: string; + readonly cookies?: Record; + readonly headers?: Record; + readonly query?: Record; + readonly formData?: Record; + readonly body?: any; + readonly mediaType?: string; + readonly responseHeader?: string; + readonly errors?: Record; }; diff --git a/src/templates/core/ApiResult.hbs b/src/templates/core/ApiResult.hbs index a89d0acf..a768b8c5 100644 --- a/src/templates/core/ApiResult.hbs +++ b/src/templates/core/ApiResult.hbs @@ -1,9 +1,9 @@ {{>header}} export type ApiResult = { - readonly url: string; - readonly ok: boolean; - readonly status: number; - readonly statusText: string; - readonly body: any; + readonly url: string; + readonly ok: boolean; + readonly status: number; + readonly statusText: string; + readonly body: any; }; diff --git a/src/templates/core/CancelablePromise.hbs b/src/templates/core/CancelablePromise.hbs index 596d8f26..67a92a67 100644 --- a/src/templates/core/CancelablePromise.hbs +++ b/src/templates/core/CancelablePromise.hbs @@ -2,126 +2,126 @@ export class CancelError extends Error { - constructor(message: string) { - super(message); - this.name = 'CancelError'; - } + constructor(message: string) { + super(message); + this.name = 'CancelError'; + } - public get isCancelled(): boolean { - return true; - } + public get isCancelled(): boolean { + return true; + } } export interface OnCancel { - readonly isResolved: boolean; - readonly isRejected: boolean; - readonly isCancelled: boolean; + readonly isResolved: boolean; + readonly isRejected: boolean; + readonly isCancelled: boolean; - (cancelHandler: () => void): void; + (cancelHandler: () => void): void; } export class CancelablePromise implements Promise { - readonly [Symbol.toStringTag]: string; + readonly [Symbol.toStringTag]: string; - #isResolved: boolean; - #isRejected: boolean; - #isCancelled: boolean; - readonly #cancelHandlers: (() => void)[]; - readonly #promise: Promise; - #resolve?: (value: T | PromiseLike) => void; - #reject?: (reason?: any) => void; + #isResolved: boolean; + #isRejected: boolean; + #isCancelled: boolean; + readonly #cancelHandlers: (() => void)[]; + readonly #promise: Promise; + #resolve?: (value: T | PromiseLike) => void; + #reject?: (reason?: any) => void; - constructor( - executor: ( - resolve: (value: T | PromiseLike) => void, - reject: (reason?: any) => void, - onCancel: OnCancel - ) => void - ) { - this.#isResolved = false; - this.#isRejected = false; - this.#isCancelled = false; - this.#cancelHandlers = []; - this.#promise = new Promise((resolve, reject) => { - this.#resolve = resolve; - this.#reject = reject; + constructor( + executor: ( + resolve: (value: T | PromiseLike) => void, + reject: (reason?: any) => void, + onCancel: OnCancel + ) => void + ) { + this.#isResolved = false; + this.#isRejected = false; + this.#isCancelled = false; + this.#cancelHandlers = []; + this.#promise = new Promise((resolve, reject) => { + this.#resolve = resolve; + this.#reject = reject; - const onResolve = (value: T | PromiseLike): void => { - if (this.#isResolved || this.#isRejected || this.#isCancelled) { - return; - } - this.#isResolved = true; - this.#resolve?.(value); - }; + const onResolve = (value: T | PromiseLike): void => { + if (this.#isResolved || this.#isRejected || this.#isCancelled) { + return; + } + this.#isResolved = true; + this.#resolve?.(value); + }; - const onReject = (reason?: any): void => { - if (this.#isResolved || this.#isRejected || this.#isCancelled) { - return; - } - this.#isRejected = true; - this.#reject?.(reason); - }; + const onReject = (reason?: any): void => { + if (this.#isResolved || this.#isRejected || this.#isCancelled) { + return; + } + this.#isRejected = true; + this.#reject?.(reason); + }; - const onCancel = (cancelHandler: () => void): void => { - if (this.#isResolved || this.#isRejected || this.#isCancelled) { - return; - } - this.#cancelHandlers.push(cancelHandler); - }; + const onCancel = (cancelHandler: () => void): void => { + if (this.#isResolved || this.#isRejected || this.#isCancelled) { + return; + } + this.#cancelHandlers.push(cancelHandler); + }; - Object.defineProperty(onCancel, 'isResolved', { - get: (): boolean => this.#isResolved, - }); + Object.defineProperty(onCancel, 'isResolved', { + get: (): boolean => this.#isResolved, + }); - Object.defineProperty(onCancel, 'isRejected', { - get: (): boolean => this.#isRejected, - }); + Object.defineProperty(onCancel, 'isRejected', { + get: (): boolean => this.#isRejected, + }); - Object.defineProperty(onCancel, 'isCancelled', { - get: (): boolean => this.#isCancelled, - }); + Object.defineProperty(onCancel, 'isCancelled', { + get: (): boolean => this.#isCancelled, + }); - return executor(onResolve, onReject, onCancel as OnCancel); - }); - } + return executor(onResolve, onReject, onCancel as OnCancel); + }); + } - public then( - onFulfilled?: ((value: T) => TResult1 | PromiseLike) | null, - onRejected?: ((reason: any) => TResult2 | PromiseLike) | null - ): Promise { - return this.#promise.then(onFulfilled, onRejected); - } + public then( + onFulfilled?: ((value: T) => TResult1 | PromiseLike) | null, + onRejected?: ((reason: any) => TResult2 | PromiseLike) | null + ): Promise { + return this.#promise.then(onFulfilled, onRejected); + } - public catch( - onRejected?: ((reason: any) => TResult | PromiseLike) | null - ): Promise { - return this.#promise.catch(onRejected); - } + public catch( + onRejected?: ((reason: any) => TResult | PromiseLike) | null + ): Promise { + return this.#promise.catch(onRejected); + } - public finally(onFinally?: (() => void) | null): Promise { - return this.#promise.finally(onFinally); - } + public finally(onFinally?: (() => void) | null): Promise { + return this.#promise.finally(onFinally); + } - public cancel(): void { - if (this.#isResolved || this.#isRejected || this.#isCancelled) { - return; - } - this.#isCancelled = true; - if (this.#cancelHandlers.length) { - try { - for (const cancelHandler of this.#cancelHandlers) { - cancelHandler(); - } - } catch (error) { - console.warn('Cancellation threw an error', error); - return; - } - } - this.#cancelHandlers.length = 0; - this.#reject?.(new CancelError('Request aborted')); - } + public cancel(): void { + if (this.#isResolved || this.#isRejected || this.#isCancelled) { + return; + } + this.#isCancelled = true; + if (this.#cancelHandlers.length) { + try { + for (const cancelHandler of this.#cancelHandlers) { + cancelHandler(); + } + } catch (error) { + console.warn('Cancellation threw an error', error); + return; + } + } + this.#cancelHandlers.length = 0; + this.#reject?.(new CancelError('Request aborted')); + } - public get isCancelled(): boolean { - return this.#isCancelled; - } + public get isCancelled(): boolean { + return this.#isCancelled; + } } diff --git a/src/templates/core/OpenAPI.hbs b/src/templates/core/OpenAPI.hbs index 6883c726..e80dbc30 100644 --- a/src/templates/core/OpenAPI.hbs +++ b/src/templates/core/OpenAPI.hbs @@ -6,25 +6,25 @@ type Resolver = (options: ApiRequestOptions) => Promise; type Headers = Record; type Config = { - BASE: string; - VERSION: string; - WITH_CREDENTIALS: boolean; - CREDENTIALS: 'include' | 'omit' | 'same-origin'; - TOKEN?: string | Resolver; - USERNAME?: string | Resolver; - PASSWORD?: string | Resolver; - HEADERS?: Headers | Resolver; - ENCODE_PATH?: (path: string) => string; + BASE: string; + VERSION: string; + WITH_CREDENTIALS: boolean; + CREDENTIALS: 'include' | 'omit' | 'same-origin'; + TOKEN?: string | Resolver; + USERNAME?: string | Resolver; + PASSWORD?: string | Resolver; + HEADERS?: Headers | Resolver; + ENCODE_PATH?: (path: string) => string; }; export const OpenAPI: Config = { - BASE: '{{{server}}}', - VERSION: '{{{version}}}', - WITH_CREDENTIALS: false, - CREDENTIALS: 'include', - TOKEN: undefined, - USERNAME: undefined, - PASSWORD: undefined, - HEADERS: undefined, - ENCODE_PATH: undefined, + BASE: '{{{server}}}', + VERSION: '{{{version}}}', + WITH_CREDENTIALS: false, + CREDENTIALS: 'include', + TOKEN: undefined, + USERNAME: undefined, + PASSWORD: undefined, + HEADERS: undefined, + ENCODE_PATH: undefined, }; diff --git a/src/templates/core/axios/getHeaders.hbs b/src/templates/core/axios/getHeaders.hbs index e5121528..d99f29cf 100644 --- a/src/templates/core/axios/getHeaders.hbs +++ b/src/templates/core/axios/getHeaders.hbs @@ -1,30 +1,30 @@ async function getHeaders(options: ApiRequestOptions, formData?: FormData): Promise> { - const token = await resolve(options, OpenAPI.TOKEN); - const username = await resolve(options, OpenAPI.USERNAME); - const password = await resolve(options, OpenAPI.PASSWORD); - const additionalHeaders = await resolve(options, OpenAPI.HEADERS); - const formHeaders = typeof formData?.getHeaders === 'function' && formData?.getHeaders() || {} + const token = await resolve(options, OpenAPI.TOKEN); + const username = await resolve(options, OpenAPI.USERNAME); + const password = await resolve(options, OpenAPI.PASSWORD); + const additionalHeaders = await resolve(options, OpenAPI.HEADERS); + const formHeaders = typeof formData?.getHeaders === 'function' && formData?.getHeaders() || {} - const headers = Object.entries({ - Accept: 'application/json', - ...additionalHeaders, - ...options.headers, - ...formHeaders, - }) - .filter(([_, value]) => isDefined(value)) - .reduce((headers, [key, value]) => ({ - ...headers, - [key]: String(value), - }), {} as Record); + const headers = Object.entries({ + Accept: 'application/json', + ...additionalHeaders, + ...options.headers, + ...formHeaders, + }) + .filter(([_, value]) => isDefined(value)) + .reduce((headers, [key, value]) => ({ + ...headers, + [key]: String(value), + }), {} as Record); - if (isStringWithValue(token)) { - headers['Authorization'] = `Bearer ${token}`; - } + if (isStringWithValue(token)) { + headers['Authorization'] = `Bearer ${token}`; + } - if (isStringWithValue(username) && isStringWithValue(password)) { - const credentials = base64(`${username}:${password}`); - headers['Authorization'] = `Basic ${credentials}`; - } + if (isStringWithValue(username) && isStringWithValue(password)) { + const credentials = base64(`${username}:${password}`); + headers['Authorization'] = `Basic ${credentials}`; + } - return headers; + return headers; } diff --git a/src/templates/core/axios/getRequestBody.hbs b/src/templates/core/axios/getRequestBody.hbs index 004108b2..01199074 100644 --- a/src/templates/core/axios/getRequestBody.hbs +++ b/src/templates/core/axios/getRequestBody.hbs @@ -1,6 +1,6 @@ function getRequestBody(options: ApiRequestOptions): any { - if (options.body) { - return options.body; - } - return; + if (options.body) { + return options.body; + } + return; } diff --git a/src/templates/core/axios/getResponseBody.hbs b/src/templates/core/axios/getResponseBody.hbs index c086c074..fba92dfa 100644 --- a/src/templates/core/axios/getResponseBody.hbs +++ b/src/templates/core/axios/getResponseBody.hbs @@ -1,6 +1,6 @@ function getResponseBody(response: AxiosResponse): any { - if (response.status !== 204) { - return response.data; - } - return; + if (response.status !== 204) { + return response.data; + } + return; } diff --git a/src/templates/core/axios/getResponseHeader.hbs b/src/templates/core/axios/getResponseHeader.hbs index ed4f24c4..033a35bf 100644 --- a/src/templates/core/axios/getResponseHeader.hbs +++ b/src/templates/core/axios/getResponseHeader.hbs @@ -1,9 +1,9 @@ function getResponseHeader(response: AxiosResponse, responseHeader?: string): string | undefined { - if (responseHeader) { - const content = response.headers[responseHeader]; - if (isString(content)) { - return content; - } - } - return; + if (responseHeader) { + const content = response.headers[responseHeader]; + if (isString(content)) { + return content; + } + } + return; } diff --git a/src/templates/core/axios/request.hbs b/src/templates/core/axios/request.hbs index b1542088..78a272a4 100644 --- a/src/templates/core/axios/request.hbs +++ b/src/templates/core/axios/request.hbs @@ -65,33 +65,33 @@ import { OpenAPI } from './OpenAPI'; * @throws ApiError */ export function request(options: ApiRequestOptions): CancelablePromise { - return new CancelablePromise(async (resolve, reject, onCancel) => { - try { - const url = getUrl(options); - const formData = getFormData(options); - const body = getRequestBody(options); - const headers = await getHeaders(options, formData); + return new CancelablePromise(async (resolve, reject, onCancel) => { + try { + const url = getUrl(options); + const formData = getFormData(options); + const body = getRequestBody(options); + const headers = await getHeaders(options, formData); - if (!onCancel.isCancelled) { - const response = await sendRequest(options, url, formData, body, headers, onCancel); - const responseBody = getResponseBody(response); - const responseHeader = getResponseHeader(response, options.responseHeader); + if (!onCancel.isCancelled) { + const response = await sendRequest(options, url, formData, body, headers, onCancel); + const responseBody = getResponseBody(response); + const responseHeader = getResponseHeader(response, options.responseHeader); - const result: ApiResult = { - url, - ok: isSuccess(response.status), - status: response.status, - statusText: response.statusText, - body: responseHeader || responseBody, - }; + const result: ApiResult = { + url, + ok: isSuccess(response.status), + status: response.status, + statusText: response.statusText, + body: responseHeader || responseBody, + }; - catchErrors(options, result); + catchErrors(options, result); - resolve(result.body); - } - } catch (error) { - reject(error); - } - }); + resolve(result.body); + } + } catch (error) { + reject(error); + } + }); } diff --git a/src/templates/core/axios/sendRequest.hbs b/src/templates/core/axios/sendRequest.hbs index ace61b38..66b75fe5 100644 --- a/src/templates/core/axios/sendRequest.hbs +++ b/src/templates/core/axios/sendRequest.hbs @@ -1,31 +1,31 @@ async function sendRequest( - options: ApiRequestOptions, - url: string, - formData: FormData | undefined, - body: any, - headers: Record, - onCancel: OnCancel + options: ApiRequestOptions, + url: string, + formData: FormData | undefined, + body: any, + headers: Record, + onCancel: OnCancel ): Promise> { - const source = axios.CancelToken.source(); + const source = axios.CancelToken.source(); - const config: AxiosRequestConfig = { - url, - headers, - data: body || formData, - method: options.method, - withCredentials: OpenAPI.WITH_CREDENTIALS, - cancelToken: source.token, - }; + const config: AxiosRequestConfig = { + url, + headers, + data: body || formData, + method: options.method, + withCredentials: OpenAPI.WITH_CREDENTIALS, + cancelToken: source.token, + }; - onCancel(() => source.cancel('The user aborted a request.')); + onCancel(() => source.cancel('The user aborted a request.')); - try { - return await axios.request(config); - } catch (error) { - const axiosError = error as AxiosError; - if (axiosError.response) { - return axiosError.response; - } - throw error; - } + try { + return await axios.request(config); + } catch (error) { + const axiosError = error as AxiosError; + if (axiosError.response) { + return axiosError.response; + } + throw error; + } } diff --git a/src/templates/core/fetch/getHeaders.hbs b/src/templates/core/fetch/getHeaders.hbs index 261cc9b8..57142a68 100644 --- a/src/templates/core/fetch/getHeaders.hbs +++ b/src/templates/core/fetch/getHeaders.hbs @@ -1,42 +1,42 @@ async function getHeaders(options: ApiRequestOptions): Promise { - const token = await resolve(options, OpenAPI.TOKEN); - const username = await resolve(options, OpenAPI.USERNAME); - const password = await resolve(options, OpenAPI.PASSWORD); - const additionalHeaders = await resolve(options, OpenAPI.HEADERS); + const token = await resolve(options, OpenAPI.TOKEN); + const username = await resolve(options, OpenAPI.USERNAME); + const password = await resolve(options, OpenAPI.PASSWORD); + const additionalHeaders = await resolve(options, OpenAPI.HEADERS); - const defaultHeaders = Object.entries({ - Accept: 'application/json', - ...additionalHeaders, - ...options.headers, - }) - .filter(([_, value]) => isDefined(value)) - .reduce((headers, [key, value]) => ({ - ...headers, - [key]: String(value), - }), {} as Record); + const defaultHeaders = Object.entries({ + Accept: 'application/json', + ...additionalHeaders, + ...options.headers, + }) + .filter(([_, value]) => isDefined(value)) + .reduce((headers, [key, value]) => ({ + ...headers, + [key]: String(value), + }), {} as Record); - const headers = new Headers(defaultHeaders); + const headers = new Headers(defaultHeaders); - if (isStringWithValue(token)) { - headers.append('Authorization', `Bearer ${token}`); - } + if (isStringWithValue(token)) { + headers.append('Authorization', `Bearer ${token}`); + } - if (isStringWithValue(username) && isStringWithValue(password)) { - const credentials = base64(`${username}:${password}`); - headers.append('Authorization', `Basic ${credentials}`); - } + if (isStringWithValue(username) && isStringWithValue(password)) { + const credentials = base64(`${username}:${password}`); + headers.append('Authorization', `Basic ${credentials}`); + } - if (options.body) { - if (options.mediaType) { - headers.append('Content-Type', options.mediaType); - } else if (isBlob(options.body)) { - headers.append('Content-Type', options.body.type || 'application/octet-stream'); - } else if (isString(options.body)) { - headers.append('Content-Type', 'text/plain'); - } else if (!isFormData(options.body)) { - headers.append('Content-Type', 'application/json'); - } - } + if (options.body) { + if (options.mediaType) { + headers.append('Content-Type', options.mediaType); + } else if (isBlob(options.body)) { + headers.append('Content-Type', options.body.type || 'application/octet-stream'); + } else if (isString(options.body)) { + headers.append('Content-Type', 'text/plain'); + } else if (!isFormData(options.body)) { + headers.append('Content-Type', 'application/json'); + } + } - return headers; + return headers; } diff --git a/src/templates/core/fetch/getRequestBody.hbs b/src/templates/core/fetch/getRequestBody.hbs index 5167ec72..72bb863d 100644 --- a/src/templates/core/fetch/getRequestBody.hbs +++ b/src/templates/core/fetch/getRequestBody.hbs @@ -1,12 +1,12 @@ function getRequestBody(options: ApiRequestOptions): BodyInit | undefined { - if (options.body) { - if (options.mediaType?.includes('/json')) { - return JSON.stringify(options.body) - } else if (isString(options.body) || isBlob(options.body) || isFormData(options.body)) { - return options.body; - } else { - return JSON.stringify(options.body); - } - } - return; + if (options.body) { + if (options.mediaType?.includes('/json')) { + return JSON.stringify(options.body) + } else if (isString(options.body) || isBlob(options.body) || isFormData(options.body)) { + return options.body; + } else { + return JSON.stringify(options.body); + } + } + return; } diff --git a/src/templates/core/fetch/getResponseBody.hbs b/src/templates/core/fetch/getResponseBody.hbs index 741747d6..31c4473f 100644 --- a/src/templates/core/fetch/getResponseBody.hbs +++ b/src/templates/core/fetch/getResponseBody.hbs @@ -1,18 +1,18 @@ async function getResponseBody(response: Response): Promise { - if (response.status !== 204) { - try { - const contentType = response.headers.get('Content-Type'); - if (contentType) { - const isJSON = contentType.toLowerCase().startsWith('application/json'); - if (isJSON) { - return await response.json(); - } else { - return await response.text(); - } - } - } catch (error) { - console.error(error); - } - } - return; + if (response.status !== 204) { + try { + const contentType = response.headers.get('Content-Type'); + if (contentType) { + const isJSON = contentType.toLowerCase().startsWith('application/json'); + if (isJSON) { + return await response.json(); + } else { + return await response.text(); + } + } + } catch (error) { + console.error(error); + } + } + return; } diff --git a/src/templates/core/fetch/getResponseHeader.hbs b/src/templates/core/fetch/getResponseHeader.hbs index bdc006ac..834ca2c7 100644 --- a/src/templates/core/fetch/getResponseHeader.hbs +++ b/src/templates/core/fetch/getResponseHeader.hbs @@ -1,9 +1,9 @@ function getResponseHeader(response: Response, responseHeader?: string): string | undefined { - if (responseHeader) { - const content = response.headers.get(responseHeader); - if (isString(content)) { - return content; - } - } - return; + if (responseHeader) { + const content = response.headers.get(responseHeader); + if (isString(content)) { + return content; + } + } + return; } diff --git a/src/templates/core/fetch/request.hbs b/src/templates/core/fetch/request.hbs index bd296458..4fda6558 100644 --- a/src/templates/core/fetch/request.hbs +++ b/src/templates/core/fetch/request.hbs @@ -62,32 +62,32 @@ import { OpenAPI } from './OpenAPI'; * @throws ApiError */ export function request(options: ApiRequestOptions): CancelablePromise { - return new CancelablePromise(async (resolve, reject, onCancel) => { - try { - const url = getUrl(options); - const formData = getFormData(options); - const body = getRequestBody(options); - const headers = await getHeaders(options); + return new CancelablePromise(async (resolve, reject, onCancel) => { + try { + const url = getUrl(options); + const formData = getFormData(options); + const body = getRequestBody(options); + const headers = await getHeaders(options); - if (!onCancel.isCancelled) { - const response = await sendRequest(options, url, formData, body, headers, onCancel); - const responseBody = await getResponseBody(response); - const responseHeader = getResponseHeader(response, options.responseHeader); + if (!onCancel.isCancelled) { + const response = await sendRequest(options, url, formData, body, headers, onCancel); + const responseBody = await getResponseBody(response); + const responseHeader = getResponseHeader(response, options.responseHeader); - const result: ApiResult = { - url, - ok: response.ok, - status: response.status, - statusText: response.statusText, - body: responseHeader || responseBody, - }; + const result: ApiResult = { + url, + ok: response.ok, + status: response.status, + statusText: response.statusText, + body: responseHeader || responseBody, + }; - catchErrors(options, result); + catchErrors(options, result); - resolve(result.body); - } - } catch (error) { - reject(error); - } - }); + resolve(result.body); + } + } catch (error) { + reject(error); + } + }); } diff --git a/src/templates/core/fetch/sendRequest.hbs b/src/templates/core/fetch/sendRequest.hbs index c48bd9f7..1c74ca1c 100644 --- a/src/templates/core/fetch/sendRequest.hbs +++ b/src/templates/core/fetch/sendRequest.hbs @@ -1,25 +1,25 @@ async function sendRequest( - options: ApiRequestOptions, - url: string, - formData: FormData | undefined, - body: BodyInit | undefined, - headers: Headers, - onCancel: OnCancel + options: ApiRequestOptions, + url: string, + formData: FormData | undefined, + body: BodyInit | undefined, + headers: Headers, + onCancel: OnCancel ): Promise { - const controller = new AbortController(); + const controller = new AbortController(); - const request: RequestInit = { - headers, - body: body || formData, - method: options.method, - signal: controller.signal, - }; + const request: RequestInit = { + headers, + body: body || formData, + method: options.method, + signal: controller.signal, + }; - if (OpenAPI.WITH_CREDENTIALS) { - request.credentials = OpenAPI.CREDENTIALS; - } + if (OpenAPI.WITH_CREDENTIALS) { + request.credentials = OpenAPI.CREDENTIALS; + } - onCancel(() => controller.abort()); + onCancel(() => controller.abort()); - return await fetch(url, request); + return await fetch(url, request); } diff --git a/src/templates/core/functions/base64.hbs b/src/templates/core/functions/base64.hbs index bca506a1..cb3dc8d4 100644 --- a/src/templates/core/functions/base64.hbs +++ b/src/templates/core/functions/base64.hbs @@ -1,8 +1,8 @@ function base64(str: string): string { - try { - return btoa(str); - } catch (err) { - // @ts-ignore - return Buffer.from(str).toString('base64'); - } + try { + return btoa(str); + } catch (err) { + // @ts-ignore + return Buffer.from(str).toString('base64'); + } } diff --git a/src/templates/core/functions/catchErrors.hbs b/src/templates/core/functions/catchErrors.hbs index e9edc085..c52163e1 100644 --- a/src/templates/core/functions/catchErrors.hbs +++ b/src/templates/core/functions/catchErrors.hbs @@ -1,21 +1,21 @@ function catchErrors(options: ApiRequestOptions, result: ApiResult): void { - const errors: Record = { - 400: 'Bad Request', - 401: 'Unauthorized', - 403: 'Forbidden', - 404: 'Not Found', - 500: 'Internal Server Error', - 502: 'Bad Gateway', - 503: 'Service Unavailable', - ...options.errors, - } + const errors: Record = { + 400: 'Bad Request', + 401: 'Unauthorized', + 403: 'Forbidden', + 404: 'Not Found', + 500: 'Internal Server Error', + 502: 'Bad Gateway', + 503: 'Service Unavailable', + ...options.errors, + } - const error = errors[result.status]; - if (error) { - throw new ApiError(result, error); - } + const error = errors[result.status]; + if (error) { + throw new ApiError(result, error); + } - if (!result.ok) { - throw new ApiError(result, 'Generic Error'); - } + if (!result.ok) { + throw new ApiError(result, 'Generic Error'); + } } diff --git a/src/templates/core/functions/getFormData.hbs b/src/templates/core/functions/getFormData.hbs index 7e6e5b9f..17f949dc 100644 --- a/src/templates/core/functions/getFormData.hbs +++ b/src/templates/core/functions/getFormData.hbs @@ -1,26 +1,26 @@ function getFormData(options: ApiRequestOptions): FormData | undefined { - if (options.formData) { - const formData = new FormData(); + if (options.formData) { + const formData = new FormData(); - const process = (key: string, value: any) => { - if (isString(value) || isBlob(value)) { - formData.append(key, value); - } else { - formData.append(key, JSON.stringify(value)); - } - }; + const process = (key: string, value: any) => { + if (isString(value) || isBlob(value)) { + formData.append(key, value); + } else { + formData.append(key, JSON.stringify(value)); + } + }; - Object.entries(options.formData) - .filter(([_, value]) => isDefined(value)) - .forEach(([key, value]) => { - if (Array.isArray(value)) { - value.forEach(v => process(key, v)); - } else { - process(key, value); - } - }); + Object.entries(options.formData) + .filter(([_, value]) => isDefined(value)) + .forEach(([key, value]) => { + if (Array.isArray(value)) { + value.forEach(v => process(key, v)); + } else { + process(key, value); + } + }); - return formData; - } - return; + return formData; + } + return; } diff --git a/src/templates/core/functions/getQueryString.hbs b/src/templates/core/functions/getQueryString.hbs index a1416123..dccac76f 100644 --- a/src/templates/core/functions/getQueryString.hbs +++ b/src/templates/core/functions/getQueryString.hbs @@ -1,30 +1,30 @@ function getQueryString(params: Record): string { - const searchParams = new URLSearchParams(); + const searchParams = new URLSearchParams(); - const process = (key: string, value: any) => { - if (isDefined(value)) { - if (Array.isArray(value)) { - value.forEach(v => { - process(key, v); - }); - } else if (typeof value === 'object') { - Object.entries(value).forEach(([k, v]) => { - process(`${key}[${k}]`, v); - }); - } else { - searchParams.append(key, value); - } - } - }; + const process = (key: string, value: any) => { + if (isDefined(value)) { + if (Array.isArray(value)) { + value.forEach(v => { + process(key, v); + }); + } else if (typeof value === 'object') { + Object.entries(value).forEach(([k, v]) => { + process(`${key}[${k}]`, v); + }); + } else { + searchParams.append(key, value); + } + } + }; - Object.entries(params).forEach(([key, value]) => { - process(key, value); - }); + Object.entries(params).forEach(([key, value]) => { + process(key, value); + }); - const query = searchParams.toString(); - if (query.length) { - return `?${query}`; - } + const query = searchParams.toString(); + if (query.length) { + return `?${query}`; + } - return ''; + return ''; } diff --git a/src/templates/core/functions/getUrl.hbs b/src/templates/core/functions/getUrl.hbs index e733d2d7..96957a5d 100644 --- a/src/templates/core/functions/getUrl.hbs +++ b/src/templates/core/functions/getUrl.hbs @@ -1,9 +1,9 @@ function getUrl(options: ApiRequestOptions): string { - const path = OpenAPI.ENCODE_PATH ? OpenAPI.ENCODE_PATH(options.path) : options.path; - const url = `${OpenAPI.BASE}${path}`; - if (options.query) { - return `${url}${getQueryString(options.query)}`; - } + const path = OpenAPI.ENCODE_PATH ? OpenAPI.ENCODE_PATH(options.path) : options.path; + const url = `${OpenAPI.BASE}${path}`; + if (options.query) { + return `${url}${getQueryString(options.query)}`; + } - return url; + return url; } diff --git a/src/templates/core/functions/isBlob.hbs b/src/templates/core/functions/isBlob.hbs index 4a27d5a9..e5a7b396 100644 --- a/src/templates/core/functions/isBlob.hbs +++ b/src/templates/core/functions/isBlob.hbs @@ -1,12 +1,12 @@ function isBlob(value: any): value is Blob { - return ( - typeof value === 'object' && - typeof value.type === 'string' && - typeof value.stream === 'function' && - typeof value.arrayBuffer === 'function' && - typeof value.constructor === 'function' && - typeof value.constructor.name === 'string' && - /^(Blob|File)$/.test(value.constructor.name) && - /^(Blob|File)$/.test(value[Symbol.toStringTag]) - ); + return ( + typeof value === 'object' && + typeof value.type === 'string' && + typeof value.stream === 'function' && + typeof value.arrayBuffer === 'function' && + typeof value.constructor === 'function' && + typeof value.constructor.name === 'string' && + /^(Blob|File)$/.test(value.constructor.name) && + /^(Blob|File)$/.test(value[Symbol.toStringTag]) + ); } diff --git a/src/templates/core/functions/isDefined.hbs b/src/templates/core/functions/isDefined.hbs index 0f76dfd5..afe3c25b 100644 --- a/src/templates/core/functions/isDefined.hbs +++ b/src/templates/core/functions/isDefined.hbs @@ -1,3 +1,3 @@ function isDefined(value: T | null | undefined): value is Exclude { - return value !== undefined && value !== null; + return value !== undefined && value !== null; } diff --git a/src/templates/core/functions/isFormData.hbs b/src/templates/core/functions/isFormData.hbs index 6e26ecfc..4691d2de 100644 --- a/src/templates/core/functions/isFormData.hbs +++ b/src/templates/core/functions/isFormData.hbs @@ -1,3 +1,3 @@ function isFormData(value: any): value is FormData { - return value instanceof FormData; -} \ No newline at end of file + return value instanceof FormData; +} diff --git a/src/templates/core/functions/isString.hbs b/src/templates/core/functions/isString.hbs index 054df919..c3934e59 100644 --- a/src/templates/core/functions/isString.hbs +++ b/src/templates/core/functions/isString.hbs @@ -1,3 +1,3 @@ function isString(value: any): value is string { - return typeof value === 'string'; + return typeof value === 'string'; } diff --git a/src/templates/core/functions/isStringWithValue.hbs b/src/templates/core/functions/isStringWithValue.hbs index 3ea45353..e0ba8965 100644 --- a/src/templates/core/functions/isStringWithValue.hbs +++ b/src/templates/core/functions/isStringWithValue.hbs @@ -1,3 +1,3 @@ function isStringWithValue(value: any): value is string { - return isString(value) && value !== ''; + return isString(value) && value !== ''; } diff --git a/src/templates/core/functions/isSuccess.hbs b/src/templates/core/functions/isSuccess.hbs index e61ffe29..4821f94d 100644 --- a/src/templates/core/functions/isSuccess.hbs +++ b/src/templates/core/functions/isSuccess.hbs @@ -1,3 +1,3 @@ function isSuccess(status: number): boolean { - return status >= 200 && status < 300; + return status >= 200 && status < 300; } diff --git a/src/templates/core/functions/resolve.hbs b/src/templates/core/functions/resolve.hbs index 1d8406e9..a4ff30b7 100644 --- a/src/templates/core/functions/resolve.hbs +++ b/src/templates/core/functions/resolve.hbs @@ -1,8 +1,8 @@ type Resolver = (options: ApiRequestOptions) => Promise; async function resolve(options: ApiRequestOptions, resolver?: T | Resolver): Promise { - if (typeof resolver === 'function') { - return (resolver as Resolver)(options); - } - return resolver; + if (typeof resolver === 'function') { + return (resolver as Resolver)(options); + } + return resolver; } diff --git a/src/templates/core/node/getHeaders.hbs b/src/templates/core/node/getHeaders.hbs index c8dcc9ff..0d880a3d 100644 --- a/src/templates/core/node/getHeaders.hbs +++ b/src/templates/core/node/getHeaders.hbs @@ -1,41 +1,41 @@ async function getHeaders(options: ApiRequestOptions): Promise { - const token = await resolve(options, OpenAPI.TOKEN); - const username = await resolve(options, OpenAPI.USERNAME); - const password = await resolve(options, OpenAPI.PASSWORD); - const additionalHeaders = await resolve(options, OpenAPI.HEADERS); + const token = await resolve(options, OpenAPI.TOKEN); + const username = await resolve(options, OpenAPI.USERNAME); + const password = await resolve(options, OpenAPI.PASSWORD); + const additionalHeaders = await resolve(options, OpenAPI.HEADERS); - const defaultHeaders = Object.entries({ - Accept: 'application/json', - ...additionalHeaders, - ...options.headers, - }) - .filter(([_, value]) => isDefined(value)) - .reduce((headers, [key, value]) => ({ - ...headers, - [key]: String(value), - }), {} as Record); + const defaultHeaders = Object.entries({ + Accept: 'application/json', + ...additionalHeaders, + ...options.headers, + }) + .filter(([_, value]) => isDefined(value)) + .reduce((headers, [key, value]) => ({ + ...headers, + [key]: String(value), + }), {} as Record); - const headers = new Headers(defaultHeaders); + const headers = new Headers(defaultHeaders); - if (isStringWithValue(token)) { - headers.append('Authorization', `Bearer ${token}`); - } + if (isStringWithValue(token)) { + headers.append('Authorization', `Bearer ${token}`); + } - if (isStringWithValue(username) && isStringWithValue(password)) { - const credentials = base64(`${username}:${password}`); - headers.append('Authorization', `Basic ${credentials}`); - } + if (isStringWithValue(username) && isStringWithValue(password)) { + const credentials = base64(`${username}:${password}`); + headers.append('Authorization', `Basic ${credentials}`); + } - if (options.body) { - if (options.mediaType) { - headers.append('Content-Type', options.mediaType); - } else if (isBlob(options.body)) { - headers.append('Content-Type', 'application/octet-stream'); - } else if (isString(options.body)) { - headers.append('Content-Type', 'text/plain'); - } else if (!isFormData(options.body)) { - headers.append('Content-Type', 'application/json'); - } - } - return headers; + if (options.body) { + if (options.mediaType) { + headers.append('Content-Type', options.mediaType); + } else if (isBlob(options.body)) { + headers.append('Content-Type', 'application/octet-stream'); + } else if (isString(options.body)) { + headers.append('Content-Type', 'text/plain'); + } else if (!isFormData(options.body)) { + headers.append('Content-Type', 'application/json'); + } + } + return headers; } diff --git a/src/templates/core/node/getRequestBody.hbs b/src/templates/core/node/getRequestBody.hbs index 3cf835ba..7661a404 100644 --- a/src/templates/core/node/getRequestBody.hbs +++ b/src/templates/core/node/getRequestBody.hbs @@ -1,12 +1,12 @@ function getRequestBody(options: ApiRequestOptions): BodyInit | undefined { - if (options.body) { - if (options.mediaType?.includes('/json')) { - return JSON.stringify(options.body) - } else if (isString(options.body) || isBlob(options.body) || isFormData(options.body)) { - return options.body as any; - } else { - return JSON.stringify(options.body); - } - } - return; + if (options.body) { + if (options.mediaType?.includes('/json')) { + return JSON.stringify(options.body) + } else if (isString(options.body) || isBlob(options.body) || isFormData(options.body)) { + return options.body as any; + } else { + return JSON.stringify(options.body); + } + } + return; } diff --git a/src/templates/core/node/getResponseBody.hbs b/src/templates/core/node/getResponseBody.hbs index 741747d6..31c4473f 100644 --- a/src/templates/core/node/getResponseBody.hbs +++ b/src/templates/core/node/getResponseBody.hbs @@ -1,18 +1,18 @@ async function getResponseBody(response: Response): Promise { - if (response.status !== 204) { - try { - const contentType = response.headers.get('Content-Type'); - if (contentType) { - const isJSON = contentType.toLowerCase().startsWith('application/json'); - if (isJSON) { - return await response.json(); - } else { - return await response.text(); - } - } - } catch (error) { - console.error(error); - } - } - return; + if (response.status !== 204) { + try { + const contentType = response.headers.get('Content-Type'); + if (contentType) { + const isJSON = contentType.toLowerCase().startsWith('application/json'); + if (isJSON) { + return await response.json(); + } else { + return await response.text(); + } + } + } catch (error) { + console.error(error); + } + } + return; } diff --git a/src/templates/core/node/getResponseHeader.hbs b/src/templates/core/node/getResponseHeader.hbs index bdc006ac..834ca2c7 100644 --- a/src/templates/core/node/getResponseHeader.hbs +++ b/src/templates/core/node/getResponseHeader.hbs @@ -1,9 +1,9 @@ function getResponseHeader(response: Response, responseHeader?: string): string | undefined { - if (responseHeader) { - const content = response.headers.get(responseHeader); - if (isString(content)) { - return content; - } - } - return; + if (responseHeader) { + const content = response.headers.get(responseHeader); + if (isString(content)) { + return content; + } + } + return; } diff --git a/src/templates/core/node/request.hbs b/src/templates/core/node/request.hbs index 5573aae4..5a57e65e 100644 --- a/src/templates/core/node/request.hbs +++ b/src/templates/core/node/request.hbs @@ -66,32 +66,32 @@ import { OpenAPI } from './OpenAPI'; * @throws ApiError */ export function request(options: ApiRequestOptions): CancelablePromise { - return new CancelablePromise(async (resolve, reject, onCancel) => { - try { - const url = getUrl(options); - const formData = getFormData(options); - const body = getRequestBody(options); - const headers = await getHeaders(options); + return new CancelablePromise(async (resolve, reject, onCancel) => { + try { + const url = getUrl(options); + const formData = getFormData(options); + const body = getRequestBody(options); + const headers = await getHeaders(options); - if (!onCancel.isCancelled) { - const response = await sendRequest(options, url, formData, body, headers, onCancel); - const responseBody = await getResponseBody(response); - const responseHeader = getResponseHeader(response, options.responseHeader); + if (!onCancel.isCancelled) { + const response = await sendRequest(options, url, formData, body, headers, onCancel); + const responseBody = await getResponseBody(response); + const responseHeader = getResponseHeader(response, options.responseHeader); - const result: ApiResult = { - url, - ok: response.ok, - status: response.status, - statusText: response.statusText, - body: responseHeader || responseBody, - }; + const result: ApiResult = { + url, + ok: response.ok, + status: response.status, + statusText: response.statusText, + body: responseHeader || responseBody, + }; - catchErrors(options, result); + catchErrors(options, result); - resolve(result.body); - } - } catch (error) { - reject(error); - } - }); + resolve(result.body); + } + } catch (error) { + reject(error); + } + }); } diff --git a/src/templates/core/node/sendRequest.hbs b/src/templates/core/node/sendRequest.hbs index 236a87c1..2067d2f0 100644 --- a/src/templates/core/node/sendRequest.hbs +++ b/src/templates/core/node/sendRequest.hbs @@ -1,21 +1,21 @@ async function sendRequest( - options: ApiRequestOptions, - url: string, - formData: FormData | undefined, - body: BodyInit | undefined, - headers: Headers, - onCancel: OnCancel + options: ApiRequestOptions, + url: string, + formData: FormData | undefined, + body: BodyInit | undefined, + headers: Headers, + onCancel: OnCancel ): Promise { - const controller = new AbortController(); + const controller = new AbortController(); - const request: RequestInit = { - headers, - method: options.method, - body: body || formData, - signal: controller.signal, - }; + const request: RequestInit = { + headers, + method: options.method, + body: body || formData, + signal: controller.signal, + }; - onCancel(() => controller.abort()); + onCancel(() => controller.abort()); - return await fetch(url, request); + return await fetch(url, request); } diff --git a/src/templates/core/xhr/getHeaders.hbs b/src/templates/core/xhr/getHeaders.hbs index bdb7db74..cbb43e57 100644 --- a/src/templates/core/xhr/getHeaders.hbs +++ b/src/templates/core/xhr/getHeaders.hbs @@ -1,41 +1,41 @@ async function getHeaders(options: ApiRequestOptions): Promise { - const token = await resolve(options, OpenAPI.TOKEN); - const username = await resolve(options, OpenAPI.USERNAME); - const password = await resolve(options, OpenAPI.PASSWORD); - const additionalHeaders = await resolve(options, OpenAPI.HEADERS); + const token = await resolve(options, OpenAPI.TOKEN); + const username = await resolve(options, OpenAPI.USERNAME); + const password = await resolve(options, OpenAPI.PASSWORD); + const additionalHeaders = await resolve(options, OpenAPI.HEADERS); - const defaultHeaders = Object.entries({ - Accept: 'application/json', - ...additionalHeaders, - ...options.headers, - }) - .filter(([_, value]) => isDefined(value)) - .reduce((headers, [key, value]) => ({ - ...headers, - [key]: String(value), - }), {} as Record); + const defaultHeaders = Object.entries({ + Accept: 'application/json', + ...additionalHeaders, + ...options.headers, + }) + .filter(([_, value]) => isDefined(value)) + .reduce((headers, [key, value]) => ({ + ...headers, + [key]: String(value), + }), {} as Record); - const headers = new Headers(defaultHeaders); + const headers = new Headers(defaultHeaders); - if (isStringWithValue(token)) { - headers.append('Authorization', `Bearer ${token}`); - } + if (isStringWithValue(token)) { + headers.append('Authorization', `Bearer ${token}`); + } - if (isStringWithValue(username) && isStringWithValue(password)) { - const credentials = base64(`${username}:${password}`); - headers.append('Authorization', `Basic ${credentials}`); - } + if (isStringWithValue(username) && isStringWithValue(password)) { + const credentials = base64(`${username}:${password}`); + headers.append('Authorization', `Basic ${credentials}`); + } - if (options.body) { - if (options.mediaType) { - headers.append('Content-Type', options.mediaType); - } else if (isBlob(options.body)) { - headers.append('Content-Type', options.body.type || 'application/octet-stream'); - } else if (isString(options.body)) { - headers.append('Content-Type', 'text/plain'); - } else if (!isFormData(options.body)) { - headers.append('Content-Type', 'application/json'); - } - } - return headers; + if (options.body) { + if (options.mediaType) { + headers.append('Content-Type', options.mediaType); + } else if (isBlob(options.body)) { + headers.append('Content-Type', options.body.type || 'application/octet-stream'); + } else if (isString(options.body)) { + headers.append('Content-Type', 'text/plain'); + } else if (!isFormData(options.body)) { + headers.append('Content-Type', 'application/json'); + } + } + return headers; } diff --git a/src/templates/core/xhr/getRequestBody.hbs b/src/templates/core/xhr/getRequestBody.hbs index c94aca18..3e0de31b 100644 --- a/src/templates/core/xhr/getRequestBody.hbs +++ b/src/templates/core/xhr/getRequestBody.hbs @@ -1,13 +1,13 @@ function getRequestBody(options: ApiRequestOptions): any { - if (options.body) { - if (options.mediaType?.includes('/json')) { - return JSON.stringify(options.body) - } else if (isString(options.body) || isBlob(options.body) || isFormData(options.body)) { - return options.body; - } else { - return JSON.stringify(options.body); - } - } + if (options.body) { + if (options.mediaType?.includes('/json')) { + return JSON.stringify(options.body) + } else if (isString(options.body) || isBlob(options.body) || isFormData(options.body)) { + return options.body; + } else { + return JSON.stringify(options.body); + } + } - return; + return; } diff --git a/src/templates/core/xhr/getResponseBody.hbs b/src/templates/core/xhr/getResponseBody.hbs index 00b0f6c4..47c21d85 100644 --- a/src/templates/core/xhr/getResponseBody.hbs +++ b/src/templates/core/xhr/getResponseBody.hbs @@ -1,18 +1,18 @@ function getResponseBody(xhr: XMLHttpRequest): any { - if (xhr.status !== 204) { - try { - const contentType = xhr.getResponseHeader('Content-Type'); - if (contentType) { - const isJSON = contentType.toLowerCase().startsWith('application/json'); - if (isJSON) { - return JSON.parse(xhr.responseText); - } else { - return xhr.responseText; - } - } - } catch (error) { - console.error(error); - } - } - return; + if (xhr.status !== 204) { + try { + const contentType = xhr.getResponseHeader('Content-Type'); + if (contentType) { + const isJSON = contentType.toLowerCase().startsWith('application/json'); + if (isJSON) { + return JSON.parse(xhr.responseText); + } else { + return xhr.responseText; + } + } + } catch (error) { + console.error(error); + } + } + return; } diff --git a/src/templates/core/xhr/getResponseHeader.hbs b/src/templates/core/xhr/getResponseHeader.hbs index 64e1aab0..9a1bf0b7 100644 --- a/src/templates/core/xhr/getResponseHeader.hbs +++ b/src/templates/core/xhr/getResponseHeader.hbs @@ -1,9 +1,9 @@ function getResponseHeader(xhr: XMLHttpRequest, responseHeader?: string): string | undefined { - if (responseHeader) { - const content = xhr.getResponseHeader(responseHeader); - if (isString(content)) { - return content; - } - } - return; + if (responseHeader) { + const content = xhr.getResponseHeader(responseHeader); + if (isString(content)) { + return content; + } + } + return; } diff --git a/src/templates/core/xhr/request.hbs b/src/templates/core/xhr/request.hbs index 65e6227b..3e589d51 100644 --- a/src/templates/core/xhr/request.hbs +++ b/src/templates/core/xhr/request.hbs @@ -65,32 +65,32 @@ import { OpenAPI } from './OpenAPI'; * @throws ApiError */ export function request(options: ApiRequestOptions): CancelablePromise { - return new CancelablePromise(async (resolve, reject, onCancel) => { - try { - const url = getUrl(options); - const formData = getFormData(options); - const body = getRequestBody(options); - const headers = await getHeaders(options); + return new CancelablePromise(async (resolve, reject, onCancel) => { + try { + const url = getUrl(options); + const formData = getFormData(options); + const body = getRequestBody(options); + const headers = await getHeaders(options); - if (!onCancel.isCancelled) { - const response = await sendRequest(options, url, formData, body, headers, onCancel); - const responseBody = getResponseBody(response); - const responseHeader = getResponseHeader(response, options.responseHeader); + if (!onCancel.isCancelled) { + const response = await sendRequest(options, url, formData, body, headers, onCancel); + const responseBody = getResponseBody(response); + const responseHeader = getResponseHeader(response, options.responseHeader); - const result: ApiResult = { - url, - ok: isSuccess(response.status), - status: response.status, - statusText: response.statusText, - body: responseHeader || responseBody, - }; + const result: ApiResult = { + url, + ok: isSuccess(response.status), + status: response.status, + statusText: response.statusText, + body: responseHeader || responseBody, + }; - catchErrors(options, result); + catchErrors(options, result); - resolve(result.body); - } - } catch (error) { - reject(error); - } - }); + resolve(result.body); + } + } catch (error) { + reject(error); + } + }); } diff --git a/src/templates/core/xhr/sendRequest.hbs b/src/templates/core/xhr/sendRequest.hbs index 0e409dc8..4badc36e 100644 --- a/src/templates/core/xhr/sendRequest.hbs +++ b/src/templates/core/xhr/sendRequest.hbs @@ -1,25 +1,25 @@ async function sendRequest( - options: ApiRequestOptions, - url: string, - formData: FormData | undefined, - body: any, - headers: Headers, - onCancel: OnCancel + options: ApiRequestOptions, + url: string, + formData: FormData | undefined, + body: any, + headers: Headers, + onCancel: OnCancel ): Promise { - const xhr = new XMLHttpRequest(); - xhr.open(options.method, url, true); - xhr.withCredentials = OpenAPI.WITH_CREDENTIALS; + const xhr = new XMLHttpRequest(); + xhr.open(options.method, url, true); + xhr.withCredentials = OpenAPI.WITH_CREDENTIALS; - headers.forEach((value, key) => { - xhr.setRequestHeader(key, value); - }); + headers.forEach((value, key) => { + xhr.setRequestHeader(key, value); + }); - return new Promise((resolve, reject) => { - xhr.onload = () => resolve(xhr); - xhr.onabort = () => reject(new Error('Request aborted')); - xhr.onerror = () => reject(new Error('Network error')); - xhr.send(body || formData); + return new Promise((resolve, reject) => { + xhr.onload = () => resolve(xhr); + xhr.onabort = () => reject(new Error('Request aborted')); + xhr.onerror = () => reject(new Error('Network error')); + xhr.send(body || formData); - onCancel(() => xhr.abort()); - }); + onCancel(() => xhr.abort()); + }); } diff --git a/src/templates/exportService.hbs b/src/templates/exportService.hbs index 10a389f3..7af37dd4 100644 --- a/src/templates/exportService.hbs +++ b/src/templates/exportService.hbs @@ -13,84 +13,84 @@ import { OpenAPI } from '../core/OpenAPI'; export class {{{name}}}{{{@root.postfix}}} { - {{#each operations}} - /** - {{#if deprecated}} - * @deprecated - {{/if}} - {{#if summary}} - * {{{escapeComment summary}}} - {{/if}} - {{#if description}} - * {{{escapeComment description}}} - {{/if}} - {{#unless @root.useOptions}} - {{#if parameters}} - {{#each parameters}} - * @param {{{name}}} {{#if description}}{{{escapeComment description}}}{{/if}} - {{/each}} - {{/if}} - {{/unless}} - {{#each results}} - * @returns {{{type}}} {{#if description}}{{{escapeComment description}}}{{/if}} - {{/each}} - * @throws ApiError - */ - public static {{{name}}}({{>parameters}}): CancelablePromise<{{>result}}> { - return __request({ - method: '{{{method}}}', - path: `{{{path}}}`, - {{#if parametersCookie}} - cookies: { - {{#each parametersCookie}} - '{{{prop}}}': {{{name}}}, - {{/each}} - }, - {{/if}} - {{#if parametersHeader}} - headers: { - {{#each parametersHeader}} - '{{{prop}}}': {{{name}}}, - {{/each}} - }, - {{/if}} - {{#if parametersQuery}} - query: { - {{#each parametersQuery}} - '{{{prop}}}': {{{name}}}, - {{/each}} - }, - {{/if}} - {{#if parametersForm}} - formData: { - {{#each parametersForm}} - '{{{prop}}}': {{{name}}}, - {{/each}} - }, - {{/if}} - {{#if parametersBody}} - {{#equals parametersBody.in 'formData'}} - formData: {{{parametersBody.name}}}, - {{/equals}} - {{#equals parametersBody.in 'body'}} - body: {{{parametersBody.name}}}, - {{/equals}} - {{#if parametersBody.mediaType}} - mediaType: '{{{parametersBody.mediaType}}}', - {{/if}} - {{/if}} - {{#if responseHeader}} - responseHeader: '{{{responseHeader}}}', - {{/if}} - {{#if errors}} - errors: { - {{#each errors}} - {{{code}}}: `{{{description}}}`, - {{/each}} - }, - {{/if}} - }); - } + {{#each operations}} + /** + {{#if deprecated}} + * @deprecated + {{/if}} + {{#if summary}} + * {{{escapeComment summary}}} + {{/if}} + {{#if description}} + * {{{escapeComment description}}} + {{/if}} + {{#unless @root.useOptions}} + {{#if parameters}} + {{#each parameters}} + * @param {{{name}}} {{#if description}}{{{escapeComment description}}}{{/if}} + {{/each}} + {{/if}} + {{/unless}} + {{#each results}} + * @returns {{{type}}} {{#if description}}{{{escapeComment description}}}{{/if}} + {{/each}} + * @throws ApiError + */ + public static {{{name}}}({{>parameters}}): CancelablePromise<{{>result}}> { + return __request({ + method: '{{{method}}}', + path: `{{{path}}}`, + {{#if parametersCookie}} + cookies: { + {{#each parametersCookie}} + '{{{prop}}}': {{{name}}}, + {{/each}} + }, + {{/if}} + {{#if parametersHeader}} + headers: { + {{#each parametersHeader}} + '{{{prop}}}': {{{name}}}, + {{/each}} + }, + {{/if}} + {{#if parametersQuery}} + query: { + {{#each parametersQuery}} + '{{{prop}}}': {{{name}}}, + {{/each}} + }, + {{/if}} + {{#if parametersForm}} + formData: { + {{#each parametersForm}} + '{{{prop}}}': {{{name}}}, + {{/each}} + }, + {{/if}} + {{#if parametersBody}} + {{#equals parametersBody.in 'formData'}} + formData: {{{parametersBody.name}}}, + {{/equals}} + {{#equals parametersBody.in 'body'}} + body: {{{parametersBody.name}}}, + {{/equals}} + {{#if parametersBody.mediaType}} + mediaType: '{{{parametersBody.mediaType}}}', + {{/if}} + {{/if}} + {{#if responseHeader}} + responseHeader: '{{{responseHeader}}}', + {{/if}} + {{#if errors}} + errors: { + {{#each errors}} + {{{code}}}: `{{{description}}}`, + {{/each}} + }, + {{/if}} + }); + } - {{/each}} + {{/each}} } diff --git a/src/templates/partials/exportComposition.hbs b/src/templates/partials/exportComposition.hbs index d1ea334c..a494260c 100644 --- a/src/templates/partials/exportComposition.hbs +++ b/src/templates/partials/exportComposition.hbs @@ -9,19 +9,19 @@ export type {{{name}}} = {{>type parent=name}}; export namespace {{{name}}} { - {{#each enums}} - {{#if description}} - /** - * {{{escapeComment description}}} - */ - {{/if}} - export enum {{{name}}} { - {{#each enum}} - {{{name}}} = {{{value}}}, - {{/each}} - } + {{#each enums}} + {{#if description}} + /** + * {{{escapeComment description}}} + */ + {{/if}} + export enum {{{name}}} { + {{#each enum}} + {{{name}}} = {{{value}}}, + {{/each}} + } - {{/each}} + {{/each}} } {{/unless}} diff --git a/src/templates/partials/exportEnum.hbs b/src/templates/partials/exportEnum.hbs index 34cec514..2b28749b 100644 --- a/src/templates/partials/exportEnum.hbs +++ b/src/templates/partials/exportEnum.hbs @@ -4,16 +4,16 @@ */ {{/if}} export enum {{{name}}} { - {{#each enum}} - {{#if description}} - /** - * {{{escapeComment description}}} - */ - {{/if}} - {{#containsSpaces name}} - "{{{name}}}" = {{{value}}}, - {{else}} - {{{name}}} = {{{value}}}, - {{/containsSpaces}} - {{/each}} + {{#each enum}} + {{#if description}} + /** + * {{{escapeComment description}}} + */ + {{/if}} + {{#containsSpaces name}} + "{{{name}}}" = {{{value}}}, + {{else}} + {{{name}}} = {{{value}}}, + {{/containsSpaces}} + {{/each}} } diff --git a/src/templates/partials/exportInterface.hbs b/src/templates/partials/exportInterface.hbs index 2a023043..645f8f42 100644 --- a/src/templates/partials/exportInterface.hbs +++ b/src/templates/partials/exportInterface.hbs @@ -4,33 +4,33 @@ */ {{/if}} export type {{{name}}} = { - {{#each properties}} - {{#if description}} - /** - * {{{escapeComment description}}} - */ - {{/if}} - {{>isReadOnly}}{{{name}}}{{>isRequired}}: {{>type parent=../name}}; - {{/each}} + {{#each properties}} + {{#if description}} + /** + * {{{escapeComment description}}} + */ + {{/if}} + {{>isReadOnly}}{{{name}}}{{>isRequired}}: {{>type parent=../name}}; + {{/each}} }; {{#if enums}} {{#unless @root.useUnionTypes}} export namespace {{{name}}} { - {{#each enums}} - {{#if description}} - /** - * {{{escapeComment description}}} - */ - {{/if}} - export enum {{{name}}} { - {{#each enum}} - {{{name}}} = {{{value}}}, - {{/each}} - } + {{#each enums}} + {{#if description}} + /** + * {{{escapeComment description}}} + */ + {{/if}} + export enum {{{name}}} { + {{#each enum}} + {{{name}}} = {{{value}}}, + {{/each}} + } - {{/each}} + {{/each}} } {{/unless}} diff --git a/src/templates/partials/schemaArray.hbs b/src/templates/partials/schemaArray.hbs index 8e1444b9..44871265 100644 --- a/src/templates/partials/schemaArray.hbs +++ b/src/templates/partials/schemaArray.hbs @@ -1,19 +1,19 @@ { - type: 'array', + type: 'array', {{#if link}} - contains: {{>schema link}}, + contains: {{>schema link}}, {{else}} - contains: { - type: '{{{base}}}', - }, + contains: { + type: '{{{base}}}', + }, {{/if}} {{#if isReadOnly}} - isReadOnly: {{{isReadOnly}}}, + isReadOnly: {{{isReadOnly}}}, {{/if}} {{#if isRequired}} - isRequired: {{{isRequired}}}, + isRequired: {{{isRequired}}}, {{/if}} {{#if isNullable}} - isNullable: {{{isNullable}}}, + isNullable: {{{isNullable}}}, {{/if}} } diff --git a/src/templates/partials/schemaComposition.hbs b/src/templates/partials/schemaComposition.hbs index f916e73d..050f6696 100644 --- a/src/templates/partials/schemaComposition.hbs +++ b/src/templates/partials/schemaComposition.hbs @@ -1,16 +1,16 @@ { - type: '{{export}}', + type: '{{export}}', {{#if description}} - description: `{{{escapeDescription description}}}`, + description: `{{{escapeDescription description}}}`, {{/if}} - contains: [{{#each properties}}{{>schema}}{{#unless @last}}, {{/unless}}{{/each}}], + contains: [{{#each properties}}{{>schema}}{{#unless @last}}, {{/unless}}{{/each}}], {{#if isReadOnly}} - isReadOnly: {{{isReadOnly}}}, + isReadOnly: {{{isReadOnly}}}, {{/if}} {{#if isRequired}} - isRequired: {{{isRequired}}}, + isRequired: {{{isRequired}}}, {{/if}} {{#if isNullable}} - isNullable: {{{isNullable}}}, + isNullable: {{{isNullable}}}, {{/if}} } diff --git a/src/templates/partials/schemaDictionary.hbs b/src/templates/partials/schemaDictionary.hbs index e980d0e7..1e755f7a 100644 --- a/src/templates/partials/schemaDictionary.hbs +++ b/src/templates/partials/schemaDictionary.hbs @@ -1,19 +1,19 @@ { - type: 'dictionary', + type: 'dictionary', {{#if link}} - contains: {{>schema link}}, + contains: {{>schema link}}, {{else}} - contains: { - type: '{{{base}}}', - }, + contains: { + type: '{{{base}}}', + }, {{/if}} {{#if isReadOnly}} - isReadOnly: {{{isReadOnly}}}, + isReadOnly: {{{isReadOnly}}}, {{/if}} {{#if isRequired}} - isRequired: {{{isRequired}}}, + isRequired: {{{isRequired}}}, {{/if}} {{#if isNullable}} - isNullable: {{{isNullable}}}, + isNullable: {{{isNullable}}}, {{/if}} } diff --git a/src/templates/partials/schemaEnum.hbs b/src/templates/partials/schemaEnum.hbs index 308cab5b..eaba3fc5 100644 --- a/src/templates/partials/schemaEnum.hbs +++ b/src/templates/partials/schemaEnum.hbs @@ -1,12 +1,12 @@ { - type: 'Enum', + type: 'Enum', {{#if isReadOnly}} - isReadOnly: {{{isReadOnly}}}, + isReadOnly: {{{isReadOnly}}}, {{/if}} {{#if isRequired}} - isRequired: {{{isRequired}}}, + isRequired: {{{isRequired}}}, {{/if}} {{#if isNullable}} - isNullable: {{{isNullable}}}, + isNullable: {{{isNullable}}}, {{/if}} } diff --git a/src/templates/partials/schemaGeneric.hbs b/src/templates/partials/schemaGeneric.hbs index 31ad8e46..23580a67 100644 --- a/src/templates/partials/schemaGeneric.hbs +++ b/src/templates/partials/schemaGeneric.hbs @@ -1,59 +1,59 @@ { {{#if type}} - type: '{{{type}}}', + type: '{{{type}}}', {{/if}} {{#if description}} - description: `{{{escapeDescription description}}}`, + description: `{{{escapeDescription description}}}`, {{/if}} {{#if isReadOnly}} - isReadOnly: {{{isReadOnly}}}, + isReadOnly: {{{isReadOnly}}}, {{/if}} {{#if isRequired}} - isRequired: {{{isRequired}}}, + isRequired: {{{isRequired}}}, {{/if}} {{#if isNullable}} - isNullable: {{{isNullable}}}, + isNullable: {{{isNullable}}}, {{/if}} {{#if format}} - format: '{{{format}}}', + format: '{{{format}}}', {{/if}} {{#if maximum}} - maximum: {{{maximum}}}, + maximum: {{{maximum}}}, {{/if}} {{#if exclusiveMaximum}} - exclusiveMaximum: {{{exclusiveMaximum}}}, + exclusiveMaximum: {{{exclusiveMaximum}}}, {{/if}} {{#if minimum}} - minimum: {{{minimum}}}, + minimum: {{{minimum}}}, {{/if}} {{#if exclusiveMinimum}} - exclusiveMinimum: {{{exclusiveMinimum}}}, + exclusiveMinimum: {{{exclusiveMinimum}}}, {{/if}} {{#if multipleOf}} - multipleOf: {{{multipleOf}}}, + multipleOf: {{{multipleOf}}}, {{/if}} {{#if maxLength}} - maxLength: {{{maxLength}}}, + maxLength: {{{maxLength}}}, {{/if}} {{#if minLength}} - minLength: {{{minLength}}}, + minLength: {{{minLength}}}, {{/if}} {{#if pattern}} - pattern: '{{{pattern}}}', + pattern: '{{{pattern}}}', {{/if}} {{#if maxItems}} - maxItems: {{{maxItems}}}, + maxItems: {{{maxItems}}}, {{/if}} {{#if minItems}} - minItems: {{{minItems}}}, + minItems: {{{minItems}}}, {{/if}} {{#if uniqueItems}} - uniqueItems: {{{uniqueItems}}}, + uniqueItems: {{{uniqueItems}}}, {{/if}} {{#if maxProperties}} - maxProperties: {{{maxProperties}}}, + maxProperties: {{{maxProperties}}}, {{/if}} {{#if minProperties}} - minProperties: {{{minProperties}}}, + minProperties: {{{minProperties}}}, {{/if}} } diff --git a/src/templates/partials/schemaInterface.hbs b/src/templates/partials/schemaInterface.hbs index 94770606..3417c5fb 100644 --- a/src/templates/partials/schemaInterface.hbs +++ b/src/templates/partials/schemaInterface.hbs @@ -1,21 +1,21 @@ { {{#if description}} - description: `{{{escapeDescription description}}}`, + description: `{{{escapeDescription description}}}`, {{/if}} - properties: { + properties: { {{#if properties}} - {{#each properties}} - {{{name}}}: {{>schema}}, - {{/each}} + {{#each properties}} + {{{name}}}: {{>schema}}, + {{/each}} {{/if}} - }, + }, {{#if isReadOnly}} - isReadOnly: {{{isReadOnly}}}, + isReadOnly: {{{isReadOnly}}}, {{/if}} {{#if isRequired}} - isRequired: {{{isRequired}}}, + isRequired: {{{isRequired}}}, {{/if}} {{#if isNullable}} - isNullable: {{{isNullable}}}, + isNullable: {{{isNullable}}}, {{/if}} } diff --git a/src/utils/format.spec.ts b/src/utils/format.spec.ts index dee81b5c..64751315 100644 --- a/src/utils/format.spec.ts +++ b/src/utils/format.spec.ts @@ -14,8 +14,8 @@ bar: 123 }`; const output3 = `{ - foo: true, - bar: 123 +\tfoo: true, +\tbar: 123 }`; const input4 = `{ @@ -24,8 +24,8 @@ const input4 = `{ }`; const output4 = `{ - foo: true, - bar: 123 +\tfoo: true, +\tbar: 123 }`; describe('format', () => { diff --git a/src/utils/format.ts b/src/utils/format.ts index 8b4fbca3..8479852a 100644 --- a/src/utils/format.ts +++ b/src/utils/format.ts @@ -13,7 +13,7 @@ export function format(s: string): string { indent--; i--; } - const result = `${' '.repeat(i)}${line}`; + const result = `${'\t'.repeat(i)}${line}`; if (result.trim() === '') { return ''; } diff --git a/src/utils/indent.ts b/src/utils/indent.ts new file mode 100644 index 00000000..e6566997 --- /dev/null +++ b/src/utils/indent.ts @@ -0,0 +1,9 @@ +import { EOL } from 'os'; + +export function indent(s: string): string { + let lines = s.split(EOL); + lines = lines.map(line => { + return line.replace(/\t/g, ' '); + }); + return lines.join(EOL); +} diff --git a/src/utils/writeClientCore.ts b/src/utils/writeClientCore.ts index 557956af..b2545603 100644 --- a/src/utils/writeClientCore.ts +++ b/src/utils/writeClientCore.ts @@ -3,6 +3,7 @@ import { resolve } from 'path'; import type { Client } from '../client/interfaces/Client'; import { HttpClient } from '../HttpClient'; import { copyFile, exists, writeFile } from './fileSystem'; +import { indent } from './indent'; import { Templates } from './registerHandlebarTemplates'; /** @@ -26,12 +27,12 @@ export async function writeClientCore( version: client.version, }; - await writeFile(resolve(outputPath, 'OpenAPI.ts'), templates.core.settings(context)); - await writeFile(resolve(outputPath, 'ApiError.ts'), templates.core.apiError({})); - await writeFile(resolve(outputPath, 'ApiRequestOptions.ts'), templates.core.apiRequestOptions({})); - await writeFile(resolve(outputPath, 'ApiResult.ts'), templates.core.apiResult({})); - await writeFile(resolve(outputPath, 'CancelablePromise.ts'), templates.core.cancelablePromise({})); - await writeFile(resolve(outputPath, 'request.ts'), templates.core.request(context)); + await writeFile(resolve(outputPath, 'OpenAPI.ts'), indent(templates.core.settings(context))); + await writeFile(resolve(outputPath, 'ApiError.ts'), indent(templates.core.apiError({}))); + await writeFile(resolve(outputPath, 'ApiRequestOptions.ts'), indent(templates.core.apiRequestOptions({}))); + await writeFile(resolve(outputPath, 'ApiResult.ts'), indent(templates.core.apiResult({}))); + await writeFile(resolve(outputPath, 'CancelablePromise.ts'), indent(templates.core.cancelablePromise({}))); + await writeFile(resolve(outputPath, 'request.ts'), indent(templates.core.request(context))); if (request) { const requestFile = resolve(process.cwd(), request); diff --git a/src/utils/writeClientModels.ts b/src/utils/writeClientModels.ts index 2a2b087d..ba8538e4 100644 --- a/src/utils/writeClientModels.ts +++ b/src/utils/writeClientModels.ts @@ -4,6 +4,7 @@ import type { Model } from '../client/interfaces/Model'; import { HttpClient } from '../HttpClient'; import { writeFile } from './fileSystem'; import { format } from './format'; +import { indent } from './indent'; import { Templates } from './registerHandlebarTemplates'; /** @@ -28,6 +29,6 @@ export async function writeClientModels( httpClient, useUnionTypes, }); - await writeFile(file, format(templateResult)); + await writeFile(file, indent(format(templateResult))); } } diff --git a/src/utils/writeClientSchemas.ts b/src/utils/writeClientSchemas.ts index f307b01a..68a551ed 100644 --- a/src/utils/writeClientSchemas.ts +++ b/src/utils/writeClientSchemas.ts @@ -4,6 +4,7 @@ import type { Model } from '../client/interfaces/Model'; import { HttpClient } from '../HttpClient'; import { writeFile } from './fileSystem'; import { format } from './format'; +import { indent } from './indent'; import { Templates } from './registerHandlebarTemplates'; /** @@ -28,6 +29,6 @@ export async function writeClientSchemas( httpClient, useUnionTypes, }); - await writeFile(file, format(templateResult)); + await writeFile(file, indent(format(templateResult))); } } diff --git a/src/utils/writeClientServices.ts b/src/utils/writeClientServices.ts index 731ed532..91124ecb 100644 --- a/src/utils/writeClientServices.ts +++ b/src/utils/writeClientServices.ts @@ -4,6 +4,7 @@ import type { Service } from '../client/interfaces/Service'; import { HttpClient } from '../HttpClient'; import { writeFile } from './fileSystem'; import { format } from './format'; +import { indent } from './indent'; import { Templates } from './registerHandlebarTemplates'; const VERSION_TEMPLATE_STRING = 'OpenAPI.VERSION'; @@ -38,6 +39,6 @@ export async function writeClientServices( useOptions, postfix, }); - await writeFile(file, format(templateResult)); + await writeFile(file, indent(format(templateResult))); } } From 15f7955ce4e48f8b3e38c590fc48b636e055b801 Mon Sep 17 00:00:00 2001 From: Ferdi Koomen Date: Tue, 25 Jan 2022 10:16:09 +0100 Subject: [PATCH 06/19] - Working indentation --- README.md | 3 ++- bin/index.js | 2 ++ src/Indent.ts | 5 +++++ src/index.ts | 7 +++++++ .../{format.spec.ts => formatCode.spec.ts} | 14 +++++++------- src/utils/{format.ts => formatCode.ts} | 2 +- src/utils/formatIndentation.ts | 18 ++++++++++++++++++ src/utils/indent.ts | 9 --------- src/utils/writeClient.spec.ts | 16 +++++++++++++++- src/utils/writeClient.ts | 10 +++++++--- src/utils/writeClientCore.spec.ts | 3 ++- src/utils/writeClientCore.ts | 17 ++++++++++------- src/utils/writeClientModels.spec.ts | 3 ++- src/utils/writeClientModels.ts | 11 +++++++---- src/utils/writeClientSchemas.spec.ts | 3 ++- src/utils/writeClientSchemas.ts | 11 +++++++---- src/utils/writeClientServices.spec.ts | 3 ++- src/utils/writeClientServices.ts | 9 ++++++--- test/index.js | 1 + types/index.d.ts | 7 +++++++ 20 files changed, 110 insertions(+), 44 deletions(-) create mode 100644 src/Indent.ts rename src/utils/{format.spec.ts => formatCode.spec.ts} (55%) rename src/utils/{format.ts => formatCode.ts} (92%) create mode 100644 src/utils/formatIndentation.ts delete mode 100644 src/utils/indent.ts diff --git a/README.md b/README.md index ec076f73..985dc7c5 100644 --- a/README.md +++ b/README.md @@ -47,7 +47,8 @@ $ openapi --help --exportServices Write services to disk (default: true) --exportModels Write models to disk (default: true) --exportSchemas Write schemas to disk (default: false) - --postfix Service name postfix (default: "Service") + --indent Service name postfix (default: "Service") + --postfix Indentation options [4, 2, tab] (default: "5") --request Path to custom request file -h, --help display help for command diff --git a/bin/index.js b/bin/index.js index 35c1c803..b1952439 100755 --- a/bin/index.js +++ b/bin/index.js @@ -19,6 +19,7 @@ const params = program .option('--exportServices ', 'Write services to disk', true) .option('--exportModels ', 'Write models to disk', true) .option('--exportSchemas ', 'Write schemas to disk', false) + .option('--indent ', 'Indentation options [4, 2, tabs]', '4') .option('--postfix ', 'Service name postfix', 'Service') .option('--request ', 'Path to custom request file') .parse(process.argv) @@ -37,6 +38,7 @@ if (OpenAPI) { exportServices: JSON.parse(params.exportServices) === true, exportModels: JSON.parse(params.exportModels) === true, exportSchemas: JSON.parse(params.exportSchemas) === true, + indent: params.indent, postfix: params.postfix, request: params.request, }) diff --git a/src/Indent.ts b/src/Indent.ts new file mode 100644 index 00000000..4203f34c --- /dev/null +++ b/src/Indent.ts @@ -0,0 +1,5 @@ +export enum Indent { + SPACE_4 = '4', + SPACE_2 = '2', + TAB = 'tab', +} diff --git a/src/index.ts b/src/index.ts index c27910c3..2edaa308 100644 --- a/src/index.ts +++ b/src/index.ts @@ -1,4 +1,5 @@ import { HttpClient } from './HttpClient'; +import { Indent } from './Indent'; import { parse as parseV2 } from './openApi/v2'; import { parse as parseV3 } from './openApi/v3'; import { getOpenApiSpec } from './utils/getOpenApiSpec'; @@ -9,6 +10,7 @@ import { registerHandlebarTemplates } from './utils/registerHandlebarTemplates'; import { writeClient } from './utils/writeClient'; export { HttpClient } from './HttpClient'; +export { Indent } from './Indent'; export type Options = { input: string | Record; @@ -20,6 +22,7 @@ export type Options = { exportServices?: boolean; exportModels?: boolean; exportSchemas?: boolean; + indent?: Indent; postfix?: string; request?: string; write?: boolean; @@ -38,6 +41,7 @@ export type Options = { * @param exportServices: Generate services * @param exportModels: Generate models * @param exportSchemas: Generate schemas + * @param indent: Indentation options (4, 2 or tab) * @param postfix: Service name postfix * @param request: Path to custom request file * @param write Write the files to disk (true or false) @@ -52,6 +56,7 @@ export async function generate({ exportServices = true, exportModels = true, exportSchemas = false, + indent = Indent.SPACE_4, postfix = 'Service', request, write = true, @@ -80,6 +85,7 @@ export async function generate({ exportServices, exportModels, exportSchemas, + indent, postfix, request ); @@ -101,6 +107,7 @@ export async function generate({ exportServices, exportModels, exportSchemas, + indent, postfix, request ); diff --git a/src/utils/format.spec.ts b/src/utils/formatCode.spec.ts similarity index 55% rename from src/utils/format.spec.ts rename to src/utils/formatCode.spec.ts index 64751315..df46263b 100644 --- a/src/utils/format.spec.ts +++ b/src/utils/formatCode.spec.ts @@ -1,4 +1,4 @@ -import { format } from './format'; +import { formatCode } from './formatCode'; const input1 = `{ foo: true }`; @@ -30,11 +30,11 @@ const output4 = `{ describe('format', () => { it('should produce correct result', () => { - expect(format(``)).toEqual(''); - expect(format(`{}`)).toEqual('{}'); - expect(format(input1)).toEqual(output1); - expect(format(input2)).toEqual(output2); - expect(format(input3)).toEqual(output3); - expect(format(input4)).toEqual(output4); + expect(formatCode(``)).toEqual(''); + expect(formatCode(`{}`)).toEqual('{}'); + expect(formatCode(input1)).toEqual(output1); + expect(formatCode(input2)).toEqual(output2); + expect(formatCode(input3)).toEqual(output3); + expect(formatCode(input4)).toEqual(output4); }); }); diff --git a/src/utils/format.ts b/src/utils/formatCode.ts similarity index 92% rename from src/utils/format.ts rename to src/utils/formatCode.ts index 8479852a..17e45774 100644 --- a/src/utils/format.ts +++ b/src/utils/formatCode.ts @@ -1,6 +1,6 @@ import { EOL } from 'os'; -export function format(s: string): string { +export function formatCode(s: string): string { let indent: number = 0; let lines = s.split(EOL); lines = lines.map(line => { diff --git a/src/utils/formatIndentation.ts b/src/utils/formatIndentation.ts new file mode 100644 index 00000000..903eec79 --- /dev/null +++ b/src/utils/formatIndentation.ts @@ -0,0 +1,18 @@ +import { EOL } from 'os'; + +import { Indent } from '../Indent'; + +export function formatIndentation(s: string, indent: Indent): string { + let lines = s.split(EOL); + lines = lines.map(line => { + switch (indent) { + case Indent.SPACE_4: + return line.replace(/\t/g, ' '); + case Indent.SPACE_2: + return line.replace(/\t/g, ' '); + case Indent.TAB: + return line; // Default output is tab formatted + } + }); + return lines.join(EOL); +} diff --git a/src/utils/indent.ts b/src/utils/indent.ts deleted file mode 100644 index e6566997..00000000 --- a/src/utils/indent.ts +++ /dev/null @@ -1,9 +0,0 @@ -import { EOL } from 'os'; - -export function indent(s: string): string { - let lines = s.split(EOL); - lines = lines.map(line => { - return line.replace(/\t/g, ' '); - }); - return lines.join(EOL); -} diff --git a/src/utils/writeClient.spec.ts b/src/utils/writeClient.spec.ts index 26802757..5c472bea 100644 --- a/src/utils/writeClient.spec.ts +++ b/src/utils/writeClient.spec.ts @@ -1,5 +1,6 @@ import type { Client } from '../client/interfaces/Client'; import { HttpClient } from '../HttpClient'; +import { Indent } from '../Indent'; import { mkdir, rmdir, writeFile } from './fileSystem'; import { Templates } from './registerHandlebarTemplates'; import { writeClient } from './writeClient'; @@ -32,7 +33,20 @@ describe('writeClient', () => { }, }; - await writeClient(client, templates, './dist', HttpClient.FETCH, false, false, true, true, true, true, ''); + await writeClient( + client, + templates, + './dist', + HttpClient.FETCH, + false, + false, + true, + true, + true, + true, + Indent.SPACE_4, + '' + ); expect(rmdir).toBeCalled(); expect(mkdir).toBeCalled(); diff --git a/src/utils/writeClient.ts b/src/utils/writeClient.ts index f1858bee..9f09ecd9 100644 --- a/src/utils/writeClient.ts +++ b/src/utils/writeClient.ts @@ -2,6 +2,7 @@ import { resolve } from 'path'; import type { Client } from '../client/interfaces/Client'; import { HttpClient } from '../HttpClient'; +import { Indent } from '../Indent'; import { mkdir, rmdir } from './fileSystem'; import { isSubDirectory } from './isSubdirectory'; import { Templates } from './registerHandlebarTemplates'; @@ -24,6 +25,7 @@ import { writeClientServices } from './writeClientServices'; * @param exportModels: Generate models * @param exportSchemas: Generate schemas * @param exportSchemas: Generate schemas + * @param indent: Indentation options (4, 2 or tab) * @param postfix: Service name postfix * @param request: Path to custom request file */ @@ -38,6 +40,7 @@ export async function writeClient( exportServices: boolean, exportModels: boolean, exportSchemas: boolean, + indent: Indent, postfix: string, request?: string ): Promise { @@ -54,7 +57,7 @@ export async function writeClient( if (exportCore) { await rmdir(outputPathCore); await mkdir(outputPathCore); - await writeClientCore(client, templates, outputPathCore, httpClient, request); + await writeClientCore(client, templates, outputPathCore, httpClient, indent, request); } if (exportServices) { @@ -67,6 +70,7 @@ export async function writeClient( httpClient, useUnionTypes, useOptions, + indent, postfix ); } @@ -74,13 +78,13 @@ export async function writeClient( if (exportSchemas) { await rmdir(outputPathSchemas); await mkdir(outputPathSchemas); - await writeClientSchemas(client.models, templates, outputPathSchemas, httpClient, useUnionTypes); + await writeClientSchemas(client.models, templates, outputPathSchemas, httpClient, useUnionTypes, indent); } if (exportModels) { await rmdir(outputPathModels); await mkdir(outputPathModels); - await writeClientModels(client.models, templates, outputPathModels, httpClient, useUnionTypes); + await writeClientModels(client.models, templates, outputPathModels, httpClient, useUnionTypes, indent); } if (exportCore || exportServices || exportSchemas || exportModels) { diff --git a/src/utils/writeClientCore.spec.ts b/src/utils/writeClientCore.spec.ts index 0b6e0c01..b96780ad 100644 --- a/src/utils/writeClientCore.spec.ts +++ b/src/utils/writeClientCore.spec.ts @@ -1,5 +1,6 @@ import type { Client } from '../client/interfaces/Client'; import { HttpClient } from '../HttpClient'; +import { Indent } from '../Indent'; import { writeFile } from './fileSystem'; import { Templates } from './registerHandlebarTemplates'; import { writeClientCore } from './writeClientCore'; @@ -32,7 +33,7 @@ describe('writeClientCore', () => { }, }; - await writeClientCore(client, templates, '/', HttpClient.FETCH); + await writeClientCore(client, templates, '/', HttpClient.FETCH, Indent.SPACE_4); expect(writeFile).toBeCalledWith('/OpenAPI.ts', 'settings'); expect(writeFile).toBeCalledWith('/ApiError.ts', 'apiError'); diff --git a/src/utils/writeClientCore.ts b/src/utils/writeClientCore.ts index b2545603..fe498f6b 100644 --- a/src/utils/writeClientCore.ts +++ b/src/utils/writeClientCore.ts @@ -2,8 +2,9 @@ import { resolve } from 'path'; import type { Client } from '../client/interfaces/Client'; import { HttpClient } from '../HttpClient'; +import { Indent } from '../Indent'; import { copyFile, exists, writeFile } from './fileSystem'; -import { indent } from './indent'; +import { formatIndentation as i } from './formatIndentation'; import { Templates } from './registerHandlebarTemplates'; /** @@ -12,6 +13,7 @@ import { Templates } from './registerHandlebarTemplates'; * @param templates The loaded handlebar templates * @param outputPath Directory to write the generated files to * @param httpClient The selected httpClient (fetch, xhr, node or axios) + * @param indent: Indentation options (4, 2 or tab) * @param request: Path to custom request file */ export async function writeClientCore( @@ -19,6 +21,7 @@ export async function writeClientCore( templates: Templates, outputPath: string, httpClient: HttpClient, + indent: Indent, request?: string ): Promise { const context = { @@ -27,12 +30,12 @@ export async function writeClientCore( version: client.version, }; - await writeFile(resolve(outputPath, 'OpenAPI.ts'), indent(templates.core.settings(context))); - await writeFile(resolve(outputPath, 'ApiError.ts'), indent(templates.core.apiError({}))); - await writeFile(resolve(outputPath, 'ApiRequestOptions.ts'), indent(templates.core.apiRequestOptions({}))); - await writeFile(resolve(outputPath, 'ApiResult.ts'), indent(templates.core.apiResult({}))); - await writeFile(resolve(outputPath, 'CancelablePromise.ts'), indent(templates.core.cancelablePromise({}))); - await writeFile(resolve(outputPath, 'request.ts'), indent(templates.core.request(context))); + await writeFile(resolve(outputPath, 'OpenAPI.ts'), i(templates.core.settings(context), indent)); + await writeFile(resolve(outputPath, 'ApiError.ts'), i(templates.core.apiError(context), indent)); + await writeFile(resolve(outputPath, 'ApiRequestOptions.ts'), i(templates.core.apiRequestOptions(context), indent)); + await writeFile(resolve(outputPath, 'ApiResult.ts'), i(templates.core.apiResult(context), indent)); + await writeFile(resolve(outputPath, 'CancelablePromise.ts'), i(templates.core.cancelablePromise(context), indent)); + await writeFile(resolve(outputPath, 'request.ts'), i(templates.core.request(context), indent)); if (request) { const requestFile = resolve(process.cwd(), request); diff --git a/src/utils/writeClientModels.spec.ts b/src/utils/writeClientModels.spec.ts index 67b093fe..359849dc 100644 --- a/src/utils/writeClientModels.spec.ts +++ b/src/utils/writeClientModels.spec.ts @@ -1,5 +1,6 @@ import type { Model } from '../client/interfaces/Model'; import { HttpClient } from '../HttpClient'; +import { Indent } from '../Indent'; import { writeFile } from './fileSystem'; import { Templates } from './registerHandlebarTemplates'; import { writeClientModels } from './writeClientModels'; @@ -45,7 +46,7 @@ describe('writeClientModels', () => { }, }; - await writeClientModels(models, templates, '/', HttpClient.FETCH, false); + await writeClientModels(models, templates, '/', HttpClient.FETCH, false, Indent.SPACE_4); expect(writeFile).toBeCalledWith('/User.ts', 'model'); }); diff --git a/src/utils/writeClientModels.ts b/src/utils/writeClientModels.ts index ba8538e4..7c58bd85 100644 --- a/src/utils/writeClientModels.ts +++ b/src/utils/writeClientModels.ts @@ -2,9 +2,10 @@ import { resolve } from 'path'; import type { Model } from '../client/interfaces/Model'; import { HttpClient } from '../HttpClient'; +import { Indent } from '../Indent'; import { writeFile } from './fileSystem'; -import { format } from './format'; -import { indent } from './indent'; +import { formatCode as f } from './formatCode'; +import { formatIndentation as i } from './formatIndentation'; import { Templates } from './registerHandlebarTemplates'; /** @@ -14,13 +15,15 @@ import { Templates } from './registerHandlebarTemplates'; * @param outputPath Directory to write the generated files to * @param httpClient The selected httpClient (fetch, xhr, node or axios) * @param useUnionTypes Use union types instead of enums + * @param indent: Indentation options (4, 2 or tab) */ export async function writeClientModels( models: Model[], templates: Templates, outputPath: string, httpClient: HttpClient, - useUnionTypes: boolean + useUnionTypes: boolean, + indent: Indent ): Promise { for (const model of models) { const file = resolve(outputPath, `${model.name}.ts`); @@ -29,6 +32,6 @@ export async function writeClientModels( httpClient, useUnionTypes, }); - await writeFile(file, indent(format(templateResult))); + await writeFile(file, i(f(templateResult), indent)); } } diff --git a/src/utils/writeClientSchemas.spec.ts b/src/utils/writeClientSchemas.spec.ts index dccc79fb..4c1f34ce 100644 --- a/src/utils/writeClientSchemas.spec.ts +++ b/src/utils/writeClientSchemas.spec.ts @@ -1,5 +1,6 @@ import type { Model } from '../client/interfaces/Model'; import { HttpClient } from '../HttpClient'; +import { Indent } from '../Indent'; import { writeFile } from './fileSystem'; import { Templates } from './registerHandlebarTemplates'; import { writeClientSchemas } from './writeClientSchemas'; @@ -45,7 +46,7 @@ describe('writeClientSchemas', () => { }, }; - await writeClientSchemas(models, templates, '/', HttpClient.FETCH, false); + await writeClientSchemas(models, templates, '/', HttpClient.FETCH, false, Indent.SPACE_4); expect(writeFile).toBeCalledWith('/$User.ts', 'schema'); }); diff --git a/src/utils/writeClientSchemas.ts b/src/utils/writeClientSchemas.ts index 68a551ed..74fdc0c9 100644 --- a/src/utils/writeClientSchemas.ts +++ b/src/utils/writeClientSchemas.ts @@ -2,9 +2,10 @@ import { resolve } from 'path'; import type { Model } from '../client/interfaces/Model'; import { HttpClient } from '../HttpClient'; +import { Indent } from '../Indent'; import { writeFile } from './fileSystem'; -import { format } from './format'; -import { indent } from './indent'; +import { formatCode as f } from './formatCode'; +import { formatIndentation as i } from './formatIndentation'; import { Templates } from './registerHandlebarTemplates'; /** @@ -14,13 +15,15 @@ import { Templates } from './registerHandlebarTemplates'; * @param outputPath Directory to write the generated files to * @param httpClient The selected httpClient (fetch, xhr, node or axios) * @param useUnionTypes Use union types instead of enums + * @param indent: Indentation options (4, 2 or tab) */ export async function writeClientSchemas( models: Model[], templates: Templates, outputPath: string, httpClient: HttpClient, - useUnionTypes: boolean + useUnionTypes: boolean, + indent: Indent ): Promise { for (const model of models) { const file = resolve(outputPath, `$${model.name}.ts`); @@ -29,6 +32,6 @@ export async function writeClientSchemas( httpClient, useUnionTypes, }); - await writeFile(file, indent(format(templateResult))); + await writeFile(file, i(f(templateResult), indent)); } } diff --git a/src/utils/writeClientServices.spec.ts b/src/utils/writeClientServices.spec.ts index 1f6798ef..1f185db8 100644 --- a/src/utils/writeClientServices.spec.ts +++ b/src/utils/writeClientServices.spec.ts @@ -1,5 +1,6 @@ import type { Service } from '../client/interfaces/Service'; import { HttpClient } from '../HttpClient'; +import { Indent } from '../Indent'; import { writeFile } from './fileSystem'; import { Templates } from './registerHandlebarTemplates'; import { writeClientServices } from './writeClientServices'; @@ -33,7 +34,7 @@ describe('writeClientServices', () => { }, }; - await writeClientServices(services, templates, '/', HttpClient.FETCH, false, false, 'Service'); + await writeClientServices(services, templates, '/', HttpClient.FETCH, false, false, Indent.SPACE_4, 'Service'); expect(writeFile).toBeCalledWith('/UserService.ts', 'service'); }); diff --git a/src/utils/writeClientServices.ts b/src/utils/writeClientServices.ts index 91124ecb..f094f69b 100644 --- a/src/utils/writeClientServices.ts +++ b/src/utils/writeClientServices.ts @@ -2,9 +2,10 @@ import { resolve } from 'path'; import type { Service } from '../client/interfaces/Service'; import { HttpClient } from '../HttpClient'; +import { Indent } from '../Indent'; import { writeFile } from './fileSystem'; -import { format } from './format'; -import { indent } from './indent'; +import { formatCode as f } from './formatCode'; +import { formatIndentation as i } from './formatIndentation'; import { Templates } from './registerHandlebarTemplates'; const VERSION_TEMPLATE_STRING = 'OpenAPI.VERSION'; @@ -17,6 +18,7 @@ const VERSION_TEMPLATE_STRING = 'OpenAPI.VERSION'; * @param httpClient The selected httpClient (fetch, xhr, node or axios) * @param useUnionTypes Use union types instead of enums * @param useOptions Use options or arguments functions + * @param indent: Indentation options (4, 2 or tab) * @param postfix: Service name postfix */ export async function writeClientServices( @@ -26,6 +28,7 @@ export async function writeClientServices( httpClient: HttpClient, useUnionTypes: boolean, useOptions: boolean, + indent: Indent, postfix: string ): Promise { for (const service of services) { @@ -39,6 +42,6 @@ export async function writeClientServices( useOptions, postfix, }); - await writeFile(file, indent(format(templateResult))); + await writeFile(file, i(f(templateResult), indent)); } } diff --git a/test/index.js b/test/index.js index 7817170f..db0a8d4b 100644 --- a/test/index.js +++ b/test/index.js @@ -14,6 +14,7 @@ const generate = async (input, output) => { exportSchemas: true, exportModels: true, exportServices: true, + // indent: OpenAPI.Indent.SPACE_2, // postfix: 'Api', // request: './test/custom/request.ts', }); diff --git a/types/index.d.ts b/types/index.d.ts index 261800bd..9104791f 100644 --- a/types/index.d.ts +++ b/types/index.d.ts @@ -5,6 +5,12 @@ export declare enum HttpClient { AXIOS = 'axios', } +export declare enum Indent { + SPACE_4 = '4', + SPACE_2 = '2', + TAB = 'tab', +} + export type Options = { input: string | Record; output: string; @@ -15,6 +21,7 @@ export type Options = { exportServices?: boolean; exportModels?: boolean; exportSchemas?: boolean; + indent?: Indent | '4' | '2' | 'tab'; postfix?: string; request?: string; write?: boolean; From d7479aef16cdf439f226b2d094ba4265d676b11c Mon Sep 17 00:00:00 2001 From: Ferdi Koomen Date: Tue, 25 Jan 2022 10:31:11 +0100 Subject: [PATCH 07/19] - Working on updating client export PR --- README.md | 28 ++++++++++++++++++++++++++++ bin/index.js | 2 ++ src/index.ts | 1 + test/index.js | 1 + types/index.d.ts | 2 ++ 5 files changed, 34 insertions(+) diff --git a/README.md b/README.md index 985dc7c5..03d076f7 100644 --- a/README.md +++ b/README.md @@ -41,6 +41,7 @@ $ openapi --help -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, axios, node] (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) @@ -96,6 +97,33 @@ OpenAPI.generate({ ## Features + +### Generate client instance with `--name` option +The OpenAPI generator allows creation of client instances to support the multiple backend services use case. +The generated client uses an instance of the server configuration and not the global `OpenAPI` constant. +To generate a client instance, set a custom name to the client class, use `--name` option. + +``` +openapi --input ./spec.json --output ./dist ---name AppClient +``` + +The generated client will be exported from the `index` file and can be used as shown below: + +```typescript +// Create the client instance with server and authentication details +const appClient = new AppClient({ + BASE: 'http://server-host.com', + TOKEN: '1234' +}); + +// Use the client instance to make the API call +const res = await appClient.organizations.createOrganization({ + name: 'OrgName', + description: 'OrgDescription', +}); +``` + + ### Argument style vs. Object style `--useOptions` There's no [named parameter](https://en.wikipedia.org/wiki/Named_parameter) in JavaScript or TypeScript, because of that, we offer the flag `--useOptions` to generate code in two different styles. diff --git a/bin/index.js b/bin/index.js index b1952439..77cf737b 100755 --- a/bin/index.js +++ b/bin/index.js @@ -13,6 +13,7 @@ const params = program .requiredOption('-i, --input ', 'OpenAPI specification, can be a path, url or string content (required)') .requiredOption('-o, --output ', 'Output directory (required)') .option('-c, --client ', 'HTTP client to generate [fetch, xhr, node, axios]', 'fetch') + .option('--name ', 'Custom client class name') .option('--useOptions', 'Use options instead of arguments') .option('--useUnionTypes', 'Use union types instead of enums') .option('--exportCore ', 'Write core files to disk', true) @@ -32,6 +33,7 @@ if (OpenAPI) { input: params.input, output: params.output, httpClient: params.client, + clientName: params.name, useOptions: params.useOptions, useUnionTypes: params.useUnionTypes, exportCore: JSON.parse(params.exportCore) === true, diff --git a/src/index.ts b/src/index.ts index 2edaa308..2949881a 100644 --- a/src/index.ts +++ b/src/index.ts @@ -16,6 +16,7 @@ export type Options = { input: string | Record; output: string; httpClient?: HttpClient; + clientName?: string; useOptions?: boolean; useUnionTypes?: boolean; exportCore?: boolean; diff --git a/test/index.js b/test/index.js index db0a8d4b..d945a191 100644 --- a/test/index.js +++ b/test/index.js @@ -14,6 +14,7 @@ const generate = async (input, output) => { exportSchemas: true, exportModels: true, exportServices: true, + clientName: 'AppClient', // indent: OpenAPI.Indent.SPACE_2, // postfix: 'Api', // request: './test/custom/request.ts', diff --git a/types/index.d.ts b/types/index.d.ts index 9104791f..39329e37 100644 --- a/types/index.d.ts +++ b/types/index.d.ts @@ -15,6 +15,7 @@ export type Options = { input: string | Record; output: string; httpClient?: HttpClient | 'fetch' | 'xhr' | 'node' | 'axios'; + clientName?: string; useOptions?: boolean; useUnionTypes?: boolean; exportCore?: boolean; @@ -31,5 +32,6 @@ export declare function generate(options: Options): Promise; export default { HttpClient, + Indent, generate, }; From cd243376500030480cbec04e09a98eca5d42f8e1 Mon Sep 17 00:00:00 2001 From: Ferdi Koomen Date: Tue, 25 Jan 2022 11:02:49 +0100 Subject: [PATCH 08/19] - Decoupled OpenAPI object from request files --- src/templates/core/OpenAPI.hbs | 4 ++-- src/templates/core/axios/getHeaders.hbs | 12 ++++++------ src/templates/core/axios/getRequestBody.hbs | 4 ++-- src/templates/core/axios/getResponseBody.hbs | 4 ++-- src/templates/core/axios/getResponseHeader.hbs | 4 ++-- src/templates/core/axios/request.hbs | 13 +++++++------ src/templates/core/axios/sendRequest.hbs | 9 +++++---- src/templates/core/fetch/getHeaders.hbs | 12 ++++++------ src/templates/core/fetch/getRequestBody.hbs | 4 ++-- src/templates/core/fetch/getResponseBody.hbs | 4 ++-- src/templates/core/fetch/getResponseHeader.hbs | 4 ++-- src/templates/core/fetch/request.hbs | 13 +++++++------ src/templates/core/fetch/sendRequest.hbs | 11 ++++++----- src/templates/core/functions/base64.hbs | 4 ++-- src/templates/core/functions/catchErrors.hbs | 4 ++-- src/templates/core/functions/getFormData.hbs | 4 ++-- src/templates/core/functions/getQueryString.hbs | 4 ++-- src/templates/core/functions/getUrl.hbs | 8 ++++---- src/templates/core/functions/isBlob.hbs | 4 ++-- src/templates/core/functions/isDefined.hbs | 4 ++-- src/templates/core/functions/isFormData.hbs | 4 ++-- src/templates/core/functions/isString.hbs | 4 ++-- src/templates/core/functions/isStringWithValue.hbs | 4 ++-- src/templates/core/functions/isSuccess.hbs | 4 ++-- src/templates/core/functions/resolve.hbs | 4 ++-- src/templates/core/node/getHeaders.hbs | 12 ++++++------ src/templates/core/node/getRequestBody.hbs | 4 ++-- src/templates/core/node/getResponseBody.hbs | 4 ++-- src/templates/core/node/getResponseHeader.hbs | 4 ++-- src/templates/core/node/request.hbs | 11 ++++++----- src/templates/core/node/sendRequest.hbs | 6 +++--- src/templates/core/xhr/getHeaders.hbs | 12 ++++++------ src/templates/core/xhr/getRequestBody.hbs | 4 ++-- src/templates/core/xhr/getResponseBody.hbs | 4 ++-- src/templates/core/xhr/getResponseHeader.hbs | 4 ++-- src/templates/core/xhr/request.hbs | 13 +++++++------ src/templates/core/xhr/sendRequest.hbs | 9 +++++---- src/templates/exportService.hbs | 2 +- 38 files changed, 123 insertions(+), 116 deletions(-) diff --git a/src/templates/core/OpenAPI.hbs b/src/templates/core/OpenAPI.hbs index e80dbc30..19e66fbf 100644 --- a/src/templates/core/OpenAPI.hbs +++ b/src/templates/core/OpenAPI.hbs @@ -5,7 +5,7 @@ import type { ApiRequestOptions } from './ApiRequestOptions'; type Resolver = (options: ApiRequestOptions) => Promise; type Headers = Record; -type Config = { +export type OpenAPIConfig = { BASE: string; VERSION: string; WITH_CREDENTIALS: boolean; @@ -17,7 +17,7 @@ type Config = { ENCODE_PATH?: (path: string) => string; }; -export const OpenAPI: Config = { +export const OpenAPI: OpenAPIConfig = { BASE: '{{{server}}}', VERSION: '{{{version}}}', WITH_CREDENTIALS: false, diff --git a/src/templates/core/axios/getHeaders.hbs b/src/templates/core/axios/getHeaders.hbs index d99f29cf..8977a5f1 100644 --- a/src/templates/core/axios/getHeaders.hbs +++ b/src/templates/core/axios/getHeaders.hbs @@ -1,8 +1,8 @@ -async function getHeaders(options: ApiRequestOptions, formData?: FormData): Promise> { - const token = await resolve(options, OpenAPI.TOKEN); - const username = await resolve(options, OpenAPI.USERNAME); - const password = await resolve(options, OpenAPI.PASSWORD); - const additionalHeaders = await resolve(options, OpenAPI.HEADERS); +const getHeaders = async (config: OpenAPIConfig, options: ApiRequestOptions, formData?: FormData): Promise> => { + const token = await resolve(options, config.TOKEN); + const username = await resolve(options, config.USERNAME); + const password = await resolve(options, config.PASSWORD); + const additionalHeaders = await resolve(options, config.HEADERS); const formHeaders = typeof formData?.getHeaders === 'function' && formData?.getHeaders() || {} const headers = Object.entries({ @@ -27,4 +27,4 @@ async function getHeaders(options: ApiRequestOptions, formData?: FormData): Prom } return headers; -} +}; diff --git a/src/templates/core/axios/getRequestBody.hbs b/src/templates/core/axios/getRequestBody.hbs index 01199074..0e17c414 100644 --- a/src/templates/core/axios/getRequestBody.hbs +++ b/src/templates/core/axios/getRequestBody.hbs @@ -1,6 +1,6 @@ -function getRequestBody(options: ApiRequestOptions): any { +const getRequestBody = (options: ApiRequestOptions): any => { if (options.body) { return options.body; } return; -} +}; diff --git a/src/templates/core/axios/getResponseBody.hbs b/src/templates/core/axios/getResponseBody.hbs index fba92dfa..8f2ff06b 100644 --- a/src/templates/core/axios/getResponseBody.hbs +++ b/src/templates/core/axios/getResponseBody.hbs @@ -1,6 +1,6 @@ -function getResponseBody(response: AxiosResponse): any { +const getResponseBody = (response: AxiosResponse): any => { if (response.status !== 204) { return response.data; } return; -} +}; diff --git a/src/templates/core/axios/getResponseHeader.hbs b/src/templates/core/axios/getResponseHeader.hbs index 033a35bf..7463f744 100644 --- a/src/templates/core/axios/getResponseHeader.hbs +++ b/src/templates/core/axios/getResponseHeader.hbs @@ -1,4 +1,4 @@ -function getResponseHeader(response: AxiosResponse, responseHeader?: string): string | undefined { +const getResponseHeader = (response: AxiosResponse, responseHeader?: string): string | undefined => { if (responseHeader) { const content = response.headers[responseHeader]; if (isString(content)) { @@ -6,4 +6,4 @@ function getResponseHeader(response: AxiosResponse, responseHeader?: string } } return; -} +}; diff --git a/src/templates/core/axios/request.hbs b/src/templates/core/axios/request.hbs index 78a272a4..12157e8e 100644 --- a/src/templates/core/axios/request.hbs +++ b/src/templates/core/axios/request.hbs @@ -8,7 +8,7 @@ import type { ApiRequestOptions } from './ApiRequestOptions'; import type { ApiResult } from './ApiResult'; import { CancelablePromise } from './CancelablePromise'; import type { OnCancel } from './CancelablePromise'; -import { OpenAPI } from './OpenAPI'; +import { OpenAPIConfig } from './OpenAPI'; {{>functions/isDefined}} @@ -60,20 +60,21 @@ import { OpenAPI } from './OpenAPI'; /** * Request using axios client + * @param config The OpenAPI configuration object * @param options The request options from the service * @returns CancelablePromise * @throws ApiError */ -export function request(options: ApiRequestOptions): CancelablePromise { +export const request = (config: OpenAPIConfig, options: ApiRequestOptions): CancelablePromise => { return new CancelablePromise(async (resolve, reject, onCancel) => { try { - const url = getUrl(options); + const url = getUrl(config, options); const formData = getFormData(options); const body = getRequestBody(options); - const headers = await getHeaders(options, formData); + const headers = await getHeaders(config, options, formData); if (!onCancel.isCancelled) { - const response = await sendRequest(options, url, formData, body, headers, onCancel); + const response = await sendRequest(config, options, url, formData, body, headers, onCancel); const responseBody = getResponseBody(response); const responseHeader = getResponseHeader(response, options.responseHeader); @@ -93,5 +94,5 @@ export function request(options: ApiRequestOptions): CancelablePromise { reject(error); } }); -} +}; diff --git a/src/templates/core/axios/sendRequest.hbs b/src/templates/core/axios/sendRequest.hbs index 66b75fe5..7813a9c2 100644 --- a/src/templates/core/axios/sendRequest.hbs +++ b/src/templates/core/axios/sendRequest.hbs @@ -1,11 +1,12 @@ -async function sendRequest( +const sendRequest = async ( + config: OpenAPIConfig, options: ApiRequestOptions, url: string, formData: FormData | undefined, body: any, headers: Record, onCancel: OnCancel -): Promise> { +): Promise> => { const source = axios.CancelToken.source(); const config: AxiosRequestConfig = { @@ -13,7 +14,7 @@ async function sendRequest( headers, data: body || formData, method: options.method, - withCredentials: OpenAPI.WITH_CREDENTIALS, + withCredentials: config.WITH_CREDENTIALS, cancelToken: source.token, }; @@ -28,4 +29,4 @@ async function sendRequest( } throw error; } -} +}; diff --git a/src/templates/core/fetch/getHeaders.hbs b/src/templates/core/fetch/getHeaders.hbs index 57142a68..009b3a84 100644 --- a/src/templates/core/fetch/getHeaders.hbs +++ b/src/templates/core/fetch/getHeaders.hbs @@ -1,8 +1,8 @@ -async function getHeaders(options: ApiRequestOptions): Promise { - const token = await resolve(options, OpenAPI.TOKEN); - const username = await resolve(options, OpenAPI.USERNAME); - const password = await resolve(options, OpenAPI.PASSWORD); - const additionalHeaders = await resolve(options, OpenAPI.HEADERS); +const getHeaders = async (config: OpenAPIConfig, options: ApiRequestOptions): Promise => { + const token = await resolve(options, config.TOKEN); + const username = await resolve(options, config.USERNAME); + const password = await resolve(options, config.PASSWORD); + const additionalHeaders = await resolve(options, config.HEADERS); const defaultHeaders = Object.entries({ Accept: 'application/json', @@ -39,4 +39,4 @@ async function getHeaders(options: ApiRequestOptions): Promise { } return headers; -} +}; diff --git a/src/templates/core/fetch/getRequestBody.hbs b/src/templates/core/fetch/getRequestBody.hbs index 72bb863d..4d4780c4 100644 --- a/src/templates/core/fetch/getRequestBody.hbs +++ b/src/templates/core/fetch/getRequestBody.hbs @@ -1,4 +1,4 @@ -function getRequestBody(options: ApiRequestOptions): BodyInit | undefined { +const getRequestBody = (options: ApiRequestOptions): BodyInit | undefined => { if (options.body) { if (options.mediaType?.includes('/json')) { return JSON.stringify(options.body) @@ -9,4 +9,4 @@ function getRequestBody(options: ApiRequestOptions): BodyInit | undefined { } } return; -} +}; diff --git a/src/templates/core/fetch/getResponseBody.hbs b/src/templates/core/fetch/getResponseBody.hbs index 31c4473f..98ae33e2 100644 --- a/src/templates/core/fetch/getResponseBody.hbs +++ b/src/templates/core/fetch/getResponseBody.hbs @@ -1,4 +1,4 @@ -async function getResponseBody(response: Response): Promise { +const getResponseBody = async (response: Response): Promise => { if (response.status !== 204) { try { const contentType = response.headers.get('Content-Type'); @@ -15,4 +15,4 @@ async function getResponseBody(response: Response): Promise { } } return; -} +}; diff --git a/src/templates/core/fetch/getResponseHeader.hbs b/src/templates/core/fetch/getResponseHeader.hbs index 834ca2c7..0a63760f 100644 --- a/src/templates/core/fetch/getResponseHeader.hbs +++ b/src/templates/core/fetch/getResponseHeader.hbs @@ -1,4 +1,4 @@ -function getResponseHeader(response: Response, responseHeader?: string): string | undefined { +const getResponseHeader = (response: Response, responseHeader?: string): string | undefined => { if (responseHeader) { const content = response.headers.get(responseHeader); if (isString(content)) { @@ -6,4 +6,4 @@ function getResponseHeader(response: Response, responseHeader?: string): string } } return; -} +}; diff --git a/src/templates/core/fetch/request.hbs b/src/templates/core/fetch/request.hbs index 4fda6558..d89b7888 100644 --- a/src/templates/core/fetch/request.hbs +++ b/src/templates/core/fetch/request.hbs @@ -5,7 +5,7 @@ import type { ApiRequestOptions } from './ApiRequestOptions'; import type { ApiResult } from './ApiResult'; import { CancelablePromise } from './CancelablePromise'; import type { OnCancel } from './CancelablePromise'; -import { OpenAPI } from './OpenAPI'; +import { OpenAPIConfig } from './OpenAPI'; {{>functions/isDefined}} @@ -57,20 +57,21 @@ import { OpenAPI } from './OpenAPI'; /** * Request using fetch client + * @param config The OpenAPI configuration object * @param options The request options from the service * @returns CancelablePromise * @throws ApiError */ -export function request(options: ApiRequestOptions): CancelablePromise { +export const request = (config: OpenAPIConfig, options: ApiRequestOptions): CancelablePromise => { return new CancelablePromise(async (resolve, reject, onCancel) => { try { - const url = getUrl(options); + const url = getUrl(config, options); const formData = getFormData(options); const body = getRequestBody(options); - const headers = await getHeaders(options); + const headers = await getHeaders(config, options); if (!onCancel.isCancelled) { - const response = await sendRequest(options, url, formData, body, headers, onCancel); + const response = await sendRequest(config, options, url, formData, body, headers, onCancel); const responseBody = await getResponseBody(response); const responseHeader = getResponseHeader(response, options.responseHeader); @@ -90,4 +91,4 @@ export function request(options: ApiRequestOptions): CancelablePromise { reject(error); } }); -} +}; diff --git a/src/templates/core/fetch/sendRequest.hbs b/src/templates/core/fetch/sendRequest.hbs index 1c74ca1c..fa10a698 100644 --- a/src/templates/core/fetch/sendRequest.hbs +++ b/src/templates/core/fetch/sendRequest.hbs @@ -1,11 +1,12 @@ -async function sendRequest( +export const sendRequest = async ( + config: OpenAPIConfig, options: ApiRequestOptions, url: string, formData: FormData | undefined, body: BodyInit | undefined, headers: Headers, onCancel: OnCancel -): Promise { +): Promise => { const controller = new AbortController(); const request: RequestInit = { @@ -15,11 +16,11 @@ async function sendRequest( signal: controller.signal, }; - if (OpenAPI.WITH_CREDENTIALS) { - request.credentials = OpenAPI.CREDENTIALS; + if (config.WITH_CREDENTIALS) { + request.credentials = config.CREDENTIALS; } onCancel(() => controller.abort()); return await fetch(url, request); -} +}; diff --git a/src/templates/core/functions/base64.hbs b/src/templates/core/functions/base64.hbs index cb3dc8d4..be275b85 100644 --- a/src/templates/core/functions/base64.hbs +++ b/src/templates/core/functions/base64.hbs @@ -1,8 +1,8 @@ -function base64(str: string): string { +const base64 = (str: string): string => { try { return btoa(str); } catch (err) { // @ts-ignore return Buffer.from(str).toString('base64'); } -} +}; diff --git a/src/templates/core/functions/catchErrors.hbs b/src/templates/core/functions/catchErrors.hbs index c52163e1..8bc916fb 100644 --- a/src/templates/core/functions/catchErrors.hbs +++ b/src/templates/core/functions/catchErrors.hbs @@ -1,4 +1,4 @@ -function catchErrors(options: ApiRequestOptions, result: ApiResult): void { +const catchErrors = (options: ApiRequestOptions, result: ApiResult): void => { const errors: Record = { 400: 'Bad Request', 401: 'Unauthorized', @@ -18,4 +18,4 @@ function catchErrors(options: ApiRequestOptions, result: ApiResult): void { if (!result.ok) { throw new ApiError(result, 'Generic Error'); } -} +}; diff --git a/src/templates/core/functions/getFormData.hbs b/src/templates/core/functions/getFormData.hbs index 17f949dc..0e6309a3 100644 --- a/src/templates/core/functions/getFormData.hbs +++ b/src/templates/core/functions/getFormData.hbs @@ -1,4 +1,4 @@ -function getFormData(options: ApiRequestOptions): FormData | undefined { +const getFormData = (options: ApiRequestOptions): FormData | undefined => { if (options.formData) { const formData = new FormData(); @@ -23,4 +23,4 @@ function getFormData(options: ApiRequestOptions): FormData | undefined { return formData; } return; -} +}; diff --git a/src/templates/core/functions/getQueryString.hbs b/src/templates/core/functions/getQueryString.hbs index dccac76f..686d9bf5 100644 --- a/src/templates/core/functions/getQueryString.hbs +++ b/src/templates/core/functions/getQueryString.hbs @@ -1,4 +1,4 @@ -function getQueryString(params: Record): string { +const getQueryString = (params: Record): string => { const searchParams = new URLSearchParams(); const process = (key: string, value: any) => { @@ -27,4 +27,4 @@ function getQueryString(params: Record): string { } return ''; -} +}; diff --git a/src/templates/core/functions/getUrl.hbs b/src/templates/core/functions/getUrl.hbs index 96957a5d..7c309ca2 100644 --- a/src/templates/core/functions/getUrl.hbs +++ b/src/templates/core/functions/getUrl.hbs @@ -1,9 +1,9 @@ -function getUrl(options: ApiRequestOptions): string { - const path = OpenAPI.ENCODE_PATH ? OpenAPI.ENCODE_PATH(options.path) : options.path; - const url = `${OpenAPI.BASE}${path}`; +const getUrl = (config: OpenAPIConfig, options: ApiRequestOptions): string => { + const path = config.ENCODE_PATH ? config.ENCODE_PATH(options.path) : options.path; + const url = `${config.BASE}${path}`; if (options.query) { return `${url}${getQueryString(options.query)}`; } return url; -} +}; diff --git a/src/templates/core/functions/isBlob.hbs b/src/templates/core/functions/isBlob.hbs index e5a7b396..caf44ddd 100644 --- a/src/templates/core/functions/isBlob.hbs +++ b/src/templates/core/functions/isBlob.hbs @@ -1,4 +1,4 @@ -function isBlob(value: any): value is Blob { +const isBlob = (value: any): value is Blob => { return ( typeof value === 'object' && typeof value.type === 'string' && @@ -9,4 +9,4 @@ function isBlob(value: any): value is Blob { /^(Blob|File)$/.test(value.constructor.name) && /^(Blob|File)$/.test(value[Symbol.toStringTag]) ); -} +}; diff --git a/src/templates/core/functions/isDefined.hbs b/src/templates/core/functions/isDefined.hbs index afe3c25b..ef6d0fc7 100644 --- a/src/templates/core/functions/isDefined.hbs +++ b/src/templates/core/functions/isDefined.hbs @@ -1,3 +1,3 @@ -function isDefined(value: T | null | undefined): value is Exclude { +const isDefined = (value: T | null | undefined): value is Exclude => { return value !== undefined && value !== null; -} +}; diff --git a/src/templates/core/functions/isFormData.hbs b/src/templates/core/functions/isFormData.hbs index 4691d2de..8bcbed6b 100644 --- a/src/templates/core/functions/isFormData.hbs +++ b/src/templates/core/functions/isFormData.hbs @@ -1,3 +1,3 @@ -function isFormData(value: any): value is FormData { +const isFormData = (value: any): value is FormData => { return value instanceof FormData; -} +}; diff --git a/src/templates/core/functions/isString.hbs b/src/templates/core/functions/isString.hbs index c3934e59..b9888d56 100644 --- a/src/templates/core/functions/isString.hbs +++ b/src/templates/core/functions/isString.hbs @@ -1,3 +1,3 @@ -function isString(value: any): value is string { +const isString = (value: any): value is string => { return typeof value === 'string'; -} +}; diff --git a/src/templates/core/functions/isStringWithValue.hbs b/src/templates/core/functions/isStringWithValue.hbs index e0ba8965..b1659067 100644 --- a/src/templates/core/functions/isStringWithValue.hbs +++ b/src/templates/core/functions/isStringWithValue.hbs @@ -1,3 +1,3 @@ -function isStringWithValue(value: any): value is string { +const isStringWithValue = (value: any): value is string => { return isString(value) && value !== ''; -} +}; diff --git a/src/templates/core/functions/isSuccess.hbs b/src/templates/core/functions/isSuccess.hbs index 4821f94d..318af124 100644 --- a/src/templates/core/functions/isSuccess.hbs +++ b/src/templates/core/functions/isSuccess.hbs @@ -1,3 +1,3 @@ -function isSuccess(status: number): boolean { +const isSuccess = (status: number): boolean => { return status >= 200 && status < 300; -} +}; diff --git a/src/templates/core/functions/resolve.hbs b/src/templates/core/functions/resolve.hbs index a4ff30b7..40dbed81 100644 --- a/src/templates/core/functions/resolve.hbs +++ b/src/templates/core/functions/resolve.hbs @@ -1,8 +1,8 @@ type Resolver = (options: ApiRequestOptions) => Promise; -async function resolve(options: ApiRequestOptions, resolver?: T | Resolver): Promise { +const resolve = async (options: ApiRequestOptions, resolver?: T | Resolver): Promise => { if (typeof resolver === 'function') { return (resolver as Resolver)(options); } return resolver; -} +}; diff --git a/src/templates/core/node/getHeaders.hbs b/src/templates/core/node/getHeaders.hbs index 0d880a3d..10f61278 100644 --- a/src/templates/core/node/getHeaders.hbs +++ b/src/templates/core/node/getHeaders.hbs @@ -1,8 +1,8 @@ -async function getHeaders(options: ApiRequestOptions): Promise { - const token = await resolve(options, OpenAPI.TOKEN); - const username = await resolve(options, OpenAPI.USERNAME); - const password = await resolve(options, OpenAPI.PASSWORD); - const additionalHeaders = await resolve(options, OpenAPI.HEADERS); +const getHeaders = async (config: OpenAPIConfig, options: ApiRequestOptions): Promise => { + const token = await resolve(options, config.TOKEN); + const username = await resolve(options, config.USERNAME); + const password = await resolve(options, config.PASSWORD); + const additionalHeaders = await resolve(options, config.HEADERS); const defaultHeaders = Object.entries({ Accept: 'application/json', @@ -38,4 +38,4 @@ async function getHeaders(options: ApiRequestOptions): Promise { } } return headers; -} +}; diff --git a/src/templates/core/node/getRequestBody.hbs b/src/templates/core/node/getRequestBody.hbs index 7661a404..7cc68fb8 100644 --- a/src/templates/core/node/getRequestBody.hbs +++ b/src/templates/core/node/getRequestBody.hbs @@ -1,4 +1,4 @@ -function getRequestBody(options: ApiRequestOptions): BodyInit | undefined { +const getRequestBody = (options: ApiRequestOptions): BodyInit | undefined => { if (options.body) { if (options.mediaType?.includes('/json')) { return JSON.stringify(options.body) @@ -9,4 +9,4 @@ function getRequestBody(options: ApiRequestOptions): BodyInit | undefined { } } return; -} +}; diff --git a/src/templates/core/node/getResponseBody.hbs b/src/templates/core/node/getResponseBody.hbs index 31c4473f..98ae33e2 100644 --- a/src/templates/core/node/getResponseBody.hbs +++ b/src/templates/core/node/getResponseBody.hbs @@ -1,4 +1,4 @@ -async function getResponseBody(response: Response): Promise { +const getResponseBody = async (response: Response): Promise => { if (response.status !== 204) { try { const contentType = response.headers.get('Content-Type'); @@ -15,4 +15,4 @@ async function getResponseBody(response: Response): Promise { } } return; -} +}; diff --git a/src/templates/core/node/getResponseHeader.hbs b/src/templates/core/node/getResponseHeader.hbs index 834ca2c7..0a63760f 100644 --- a/src/templates/core/node/getResponseHeader.hbs +++ b/src/templates/core/node/getResponseHeader.hbs @@ -1,4 +1,4 @@ -function getResponseHeader(response: Response, responseHeader?: string): string | undefined { +const getResponseHeader = (response: Response, responseHeader?: string): string | undefined => { if (responseHeader) { const content = response.headers.get(responseHeader); if (isString(content)) { @@ -6,4 +6,4 @@ function getResponseHeader(response: Response, responseHeader?: string): string } } return; -} +}; diff --git a/src/templates/core/node/request.hbs b/src/templates/core/node/request.hbs index 5a57e65e..d8c738b5 100644 --- a/src/templates/core/node/request.hbs +++ b/src/templates/core/node/request.hbs @@ -9,7 +9,7 @@ import type { ApiRequestOptions } from './ApiRequestOptions'; import type { ApiResult } from './ApiResult'; import { CancelablePromise } from './CancelablePromise'; import type { OnCancel } from './CancelablePromise'; -import { OpenAPI } from './OpenAPI'; +import { OpenAPIConfig } from './OpenAPI'; {{>functions/isDefined}} @@ -61,17 +61,18 @@ import { OpenAPI } from './OpenAPI'; /** * Request using node-fetch client + * @param config The OpenAPI configuration object * @param options The request options from the service * @returns CancelablePromise * @throws ApiError */ -export function request(options: ApiRequestOptions): CancelablePromise { +export const request = (config: OpenAPIConfig, options: ApiRequestOptions): CancelablePromise => { return new CancelablePromise(async (resolve, reject, onCancel) => { try { - const url = getUrl(options); + const url = getUrl(config, options); const formData = getFormData(options); const body = getRequestBody(options); - const headers = await getHeaders(options); + const headers = await getHeaders(config, options); if (!onCancel.isCancelled) { const response = await sendRequest(options, url, formData, body, headers, onCancel); @@ -94,4 +95,4 @@ export function request(options: ApiRequestOptions): CancelablePromise { reject(error); } }); -} +}; diff --git a/src/templates/core/node/sendRequest.hbs b/src/templates/core/node/sendRequest.hbs index 2067d2f0..1160ad66 100644 --- a/src/templates/core/node/sendRequest.hbs +++ b/src/templates/core/node/sendRequest.hbs @@ -1,11 +1,11 @@ -async function sendRequest( +export const sendRequest = async ( options: ApiRequestOptions, url: string, formData: FormData | undefined, body: BodyInit | undefined, headers: Headers, onCancel: OnCancel -): Promise { +): Promise => { const controller = new AbortController(); const request: RequestInit = { @@ -18,4 +18,4 @@ async function sendRequest( onCancel(() => controller.abort()); return await fetch(url, request); -} +}; diff --git a/src/templates/core/xhr/getHeaders.hbs b/src/templates/core/xhr/getHeaders.hbs index cbb43e57..16a611bc 100644 --- a/src/templates/core/xhr/getHeaders.hbs +++ b/src/templates/core/xhr/getHeaders.hbs @@ -1,8 +1,8 @@ -async function getHeaders(options: ApiRequestOptions): Promise { - const token = await resolve(options, OpenAPI.TOKEN); - const username = await resolve(options, OpenAPI.USERNAME); - const password = await resolve(options, OpenAPI.PASSWORD); - const additionalHeaders = await resolve(options, OpenAPI.HEADERS); +const getHeaders = async (config: OpenAPIConfig, options: ApiRequestOptions): Promise => { + const token = await resolve(options, config.TOKEN); + const username = await resolve(options, config.USERNAME); + const password = await resolve(options, config.PASSWORD); + const additionalHeaders = await resolve(options, config.HEADERS); const defaultHeaders = Object.entries({ Accept: 'application/json', @@ -38,4 +38,4 @@ async function getHeaders(options: ApiRequestOptions): Promise { } } return headers; -} +}; diff --git a/src/templates/core/xhr/getRequestBody.hbs b/src/templates/core/xhr/getRequestBody.hbs index 3e0de31b..c0b4a534 100644 --- a/src/templates/core/xhr/getRequestBody.hbs +++ b/src/templates/core/xhr/getRequestBody.hbs @@ -1,4 +1,4 @@ -function getRequestBody(options: ApiRequestOptions): any { +const getRequestBody = (options: ApiRequestOptions): any => { if (options.body) { if (options.mediaType?.includes('/json')) { return JSON.stringify(options.body) @@ -10,4 +10,4 @@ function getRequestBody(options: ApiRequestOptions): any { } return; -} +}; diff --git a/src/templates/core/xhr/getResponseBody.hbs b/src/templates/core/xhr/getResponseBody.hbs index 47c21d85..96da1f9f 100644 --- a/src/templates/core/xhr/getResponseBody.hbs +++ b/src/templates/core/xhr/getResponseBody.hbs @@ -1,4 +1,4 @@ -function getResponseBody(xhr: XMLHttpRequest): any { +const getResponseBody = (xhr: XMLHttpRequest): any => { if (xhr.status !== 204) { try { const contentType = xhr.getResponseHeader('Content-Type'); @@ -15,4 +15,4 @@ function getResponseBody(xhr: XMLHttpRequest): any { } } return; -} +}; diff --git a/src/templates/core/xhr/getResponseHeader.hbs b/src/templates/core/xhr/getResponseHeader.hbs index 9a1bf0b7..d99e4c8c 100644 --- a/src/templates/core/xhr/getResponseHeader.hbs +++ b/src/templates/core/xhr/getResponseHeader.hbs @@ -1,4 +1,4 @@ -function getResponseHeader(xhr: XMLHttpRequest, responseHeader?: string): string | undefined { +const getResponseHeader = (xhr: XMLHttpRequest, responseHeader?: string): string | undefined => { if (responseHeader) { const content = xhr.getResponseHeader(responseHeader); if (isString(content)) { @@ -6,4 +6,4 @@ function getResponseHeader(xhr: XMLHttpRequest, responseHeader?: string): string } } return; -} +}; diff --git a/src/templates/core/xhr/request.hbs b/src/templates/core/xhr/request.hbs index 3e589d51..40aac34e 100644 --- a/src/templates/core/xhr/request.hbs +++ b/src/templates/core/xhr/request.hbs @@ -5,7 +5,7 @@ import type { ApiRequestOptions } from './ApiRequestOptions'; import type { ApiResult } from './ApiResult'; import { CancelablePromise } from './CancelablePromise'; import type { OnCancel } from './CancelablePromise'; -import { OpenAPI } from './OpenAPI'; +import { OpenAPIConfig } from './OpenAPI'; {{>functions/isDefined}} @@ -60,20 +60,21 @@ import { OpenAPI } from './OpenAPI'; /** * Request using XHR client + * @param config The OpenAPI configuration object * @param options The request options from the service * @returns CancelablePromise * @throws ApiError */ -export function request(options: ApiRequestOptions): CancelablePromise { +export const request = (config: OpenAPIConfig, options: ApiRequestOptions): CancelablePromise => { return new CancelablePromise(async (resolve, reject, onCancel) => { try { - const url = getUrl(options); + const url = getUrl(config, options); const formData = getFormData(options); const body = getRequestBody(options); - const headers = await getHeaders(options); + const headers = await getHeaders(config, options); if (!onCancel.isCancelled) { - const response = await sendRequest(options, url, formData, body, headers, onCancel); + const response = await sendRequest(config, options, url, formData, body, headers, onCancel); const responseBody = getResponseBody(response); const responseHeader = getResponseHeader(response, options.responseHeader); @@ -93,4 +94,4 @@ export function request(options: ApiRequestOptions): CancelablePromise { reject(error); } }); -} +}; diff --git a/src/templates/core/xhr/sendRequest.hbs b/src/templates/core/xhr/sendRequest.hbs index 4badc36e..d51f6e3c 100644 --- a/src/templates/core/xhr/sendRequest.hbs +++ b/src/templates/core/xhr/sendRequest.hbs @@ -1,14 +1,15 @@ -async function sendRequest( +export const sendRequest = async ( + config: OpenAPIConfig, options: ApiRequestOptions, url: string, formData: FormData | undefined, body: any, headers: Headers, onCancel: OnCancel -): Promise { +): Promise => { const xhr = new XMLHttpRequest(); xhr.open(options.method, url, true); - xhr.withCredentials = OpenAPI.WITH_CREDENTIALS; + xhr.withCredentials = config.WITH_CREDENTIALS; headers.forEach((value, key) => { xhr.setRequestHeader(key, value); @@ -22,4 +23,4 @@ async function sendRequest( onCancel(() => xhr.abort()); }); -} +}; diff --git a/src/templates/exportService.hbs b/src/templates/exportService.hbs index 7af37dd4..13becbfa 100644 --- a/src/templates/exportService.hbs +++ b/src/templates/exportService.hbs @@ -37,7 +37,7 @@ export class {{{name}}}{{{@root.postfix}}} { * @throws ApiError */ public static {{{name}}}({{>parameters}}): CancelablePromise<{{>result}}> { - return __request({ + return __request(OpenAPI, { method: '{{{method}}}', path: `{{{path}}}`, {{#if parametersCookie}} From ae3314979797fe86d4870d2be33e597661cb5c8e Mon Sep 17 00:00:00 2001 From: Ferdi Koomen Date: Tue, 25 Jan 2022 11:15:56 +0100 Subject: [PATCH 09/19] - Tested seperation of OpenAPI object, some small fixes --- src/templates/core/axios/request.hbs | 2 +- src/templates/core/axios/sendRequest.hbs | 4 ++-- src/templates/core/fetch/request.hbs | 2 +- src/templates/core/node/request.hbs | 2 +- src/templates/core/xhr/request.hbs | 2 +- src/templates/index.hbs | 1 + 6 files changed, 7 insertions(+), 6 deletions(-) diff --git a/src/templates/core/axios/request.hbs b/src/templates/core/axios/request.hbs index 12157e8e..755555bf 100644 --- a/src/templates/core/axios/request.hbs +++ b/src/templates/core/axios/request.hbs @@ -8,7 +8,7 @@ import type { ApiRequestOptions } from './ApiRequestOptions'; import type { ApiResult } from './ApiResult'; import { CancelablePromise } from './CancelablePromise'; import type { OnCancel } from './CancelablePromise'; -import { OpenAPIConfig } from './OpenAPI'; +import type { OpenAPIConfig } from './OpenAPI'; {{>functions/isDefined}} diff --git a/src/templates/core/axios/sendRequest.hbs b/src/templates/core/axios/sendRequest.hbs index 7813a9c2..f5c08e40 100644 --- a/src/templates/core/axios/sendRequest.hbs +++ b/src/templates/core/axios/sendRequest.hbs @@ -9,7 +9,7 @@ const sendRequest = async ( ): Promise> => { const source = axios.CancelToken.source(); - const config: AxiosRequestConfig = { + const requestConfig: AxiosRequestConfig = { url, headers, data: body || formData, @@ -21,7 +21,7 @@ const sendRequest = async ( onCancel(() => source.cancel('The user aborted a request.')); try { - return await axios.request(config); + return await axios.request(requestConfig); } catch (error) { const axiosError = error as AxiosError; if (axiosError.response) { diff --git a/src/templates/core/fetch/request.hbs b/src/templates/core/fetch/request.hbs index d89b7888..6116daed 100644 --- a/src/templates/core/fetch/request.hbs +++ b/src/templates/core/fetch/request.hbs @@ -5,7 +5,7 @@ import type { ApiRequestOptions } from './ApiRequestOptions'; import type { ApiResult } from './ApiResult'; import { CancelablePromise } from './CancelablePromise'; import type { OnCancel } from './CancelablePromise'; -import { OpenAPIConfig } from './OpenAPI'; +import type { OpenAPIConfig } from './OpenAPI'; {{>functions/isDefined}} diff --git a/src/templates/core/node/request.hbs b/src/templates/core/node/request.hbs index d8c738b5..367254d5 100644 --- a/src/templates/core/node/request.hbs +++ b/src/templates/core/node/request.hbs @@ -9,7 +9,7 @@ import type { ApiRequestOptions } from './ApiRequestOptions'; import type { ApiResult } from './ApiResult'; import { CancelablePromise } from './CancelablePromise'; import type { OnCancel } from './CancelablePromise'; -import { OpenAPIConfig } from './OpenAPI'; +import type { OpenAPIConfig } from './OpenAPI'; {{>functions/isDefined}} diff --git a/src/templates/core/xhr/request.hbs b/src/templates/core/xhr/request.hbs index 40aac34e..d9d32225 100644 --- a/src/templates/core/xhr/request.hbs +++ b/src/templates/core/xhr/request.hbs @@ -5,7 +5,7 @@ import type { ApiRequestOptions } from './ApiRequestOptions'; import type { ApiResult } from './ApiResult'; import { CancelablePromise } from './CancelablePromise'; import type { OnCancel } from './CancelablePromise'; -import { OpenAPIConfig } from './OpenAPI'; +import type { OpenAPIConfig } from './OpenAPI'; {{>functions/isDefined}} diff --git a/src/templates/index.hbs b/src/templates/index.hbs index 97355941..86a25715 100644 --- a/src/templates/index.hbs +++ b/src/templates/index.hbs @@ -4,6 +4,7 @@ export { ApiError } from './core/ApiError'; export { CancelablePromise, CancelError } from './core/CancelablePromise'; export { OpenAPI } from './core/OpenAPI'; +export type { OpenAPIConfig } from './core/OpenAPI'; {{/if}} {{#if @root.exportModels}} {{#if models}} From d0900cee8c7d6500ce60af3ca7f62bd9532df92d Mon Sep 17 00:00:00 2001 From: Ferdi Koomen Date: Tue, 25 Jan 2022 11:52:07 +0100 Subject: [PATCH 10/19] - Added client and HttpRequest files --- src/templates/client.hbs | 39 ++++++++++++++++++++++++ src/templates/core/BaseHttpRequest.hbs | 17 +++++++++++ src/templates/core/HttpRequest.hbs | 22 +++++++++++++ src/templates/core/axios/request.hbs | 4 +-- src/templates/core/axios/sendRequest.hbs | 2 +- src/templates/core/fetch/request.hbs | 4 +-- src/templates/core/fetch/sendRequest.hbs | 2 +- src/templates/core/node/request.hbs | 4 +-- src/templates/core/node/sendRequest.hbs | 2 +- src/templates/core/xhr/request.hbs | 4 +-- src/templates/core/xhr/sendRequest.hbs | 2 +- 11 files changed, 90 insertions(+), 12 deletions(-) create mode 100644 src/templates/client.hbs create mode 100644 src/templates/core/BaseHttpRequest.hbs create mode 100644 src/templates/core/HttpRequest.hbs diff --git a/src/templates/client.hbs b/src/templates/client.hbs new file mode 100644 index 00000000..51afc61a --- /dev/null +++ b/src/templates/client.hbs @@ -0,0 +1,39 @@ +{{>header}} + +import type { BaseHttpRequest } from './core/BaseHttpRequest'; +import type { OpenAPIConfig } from './core/OpenAPI'; +import { {{{httpRequest}}} } from './core/{{{httpRequest}}}'; +{{#if services}} +{{#each services}} +import { {{{name}}} } from './services/{{{name}}}'; +{{/each}} +{{/if}} + +type HttpRequestConstructor = new (config: OpenAPIConfig) => BaseHttpRequest; + +export class {{{clientName}}} { + +{{#each services}} + readonly {{{name}}}: {{{name}}}; +{{/each}} + + readonly request: BaseHttpRequest; + + constructor(config?: OpenAPIConfig, HttpRequest: HttpRequestConstructor = {{{httpRequest}}}) { + this.request = new HttpRequest({ + BASE: config?.BASE ?? '{{{server}}}', + VERSION: config?.VERSION ?? '{{{version}}}', + WITH_CREDENTIALS: config?.WITH_CREDENTIALS ?? false, + CREDENTIALS: config?.CREDENTIALS ?? 'include', + TOKEN: config?.TOKEN, + USERNAME: config?.USERNAME, + PASSWORD: config?.PASSWORD, + HEADERS: config?.HEADERS, + ENCODE_PATH: config?.ENCODE_PATH, + }); + + {{#each services}} + this.{{{name}}} = new {{{name}}}(this.request); + {{/each}} + } +} diff --git a/src/templates/core/BaseHttpRequest.hbs b/src/templates/core/BaseHttpRequest.hbs new file mode 100644 index 00000000..6a70629a --- /dev/null +++ b/src/templates/core/BaseHttpRequest.hbs @@ -0,0 +1,17 @@ +{{>header}} + +import type { ApiRequestOptions } from './ApiRequestOptions'; +import type { CancelablePromise } from './CancelablePromise'; +import type { OpenAPIConfig } from './OpenAPI'; + +export class BaseHttpRequest { + protected readonly config: OpenAPIConfig; + + constructor(config: OpenAPIConfig) { + this.config = config; + } + + public request(options: ApiRequestOptions): CancelablePromise { + throw new Error('Not Implemented'); + } +} diff --git a/src/templates/core/HttpRequest.hbs b/src/templates/core/HttpRequest.hbs new file mode 100644 index 00000000..ed97a39b --- /dev/null +++ b/src/templates/core/HttpRequest.hbs @@ -0,0 +1,22 @@ +{{>header}} + +import type { BaseHttpRequest } from './BaseHttpRequest'; +import type { OpenAPIConfig } from './OpenAPI'; +import { request as __request } from './request'; + +export class {{HttpRequest}} extends BaseHttpRequest { + + constructor(config: OpenAPIConfig) { + super(config); + } + + /** + * Request method + * @param options The request options from the service + * @returns CancelablePromise + * @throws ApiError + */ + public request(options: ApiRequestOptions): CancelablePromise { + return __request(this.config, options); + } +} diff --git a/src/templates/core/axios/request.hbs b/src/templates/core/axios/request.hbs index 755555bf..6f7765a0 100644 --- a/src/templates/core/axios/request.hbs +++ b/src/templates/core/axios/request.hbs @@ -59,7 +59,7 @@ import type { OpenAPIConfig } from './OpenAPI'; /** - * Request using axios client + * Request method * @param config The OpenAPI configuration object * @param options The request options from the service * @returns CancelablePromise @@ -83,7 +83,7 @@ export const request = (config: OpenAPIConfig, options: ApiRequestOptions): C ok: isSuccess(response.status), status: response.status, statusText: response.statusText, - body: responseHeader || responseBody, + body: responseHeader ?? responseBody, }; catchErrors(options, result); diff --git a/src/templates/core/axios/sendRequest.hbs b/src/templates/core/axios/sendRequest.hbs index f5c08e40..41af3b46 100644 --- a/src/templates/core/axios/sendRequest.hbs +++ b/src/templates/core/axios/sendRequest.hbs @@ -12,7 +12,7 @@ const sendRequest = async ( const requestConfig: AxiosRequestConfig = { url, headers, - data: body || formData, + data: body ?? formData, method: options.method, withCredentials: config.WITH_CREDENTIALS, cancelToken: source.token, diff --git a/src/templates/core/fetch/request.hbs b/src/templates/core/fetch/request.hbs index 6116daed..5815f6e4 100644 --- a/src/templates/core/fetch/request.hbs +++ b/src/templates/core/fetch/request.hbs @@ -56,7 +56,7 @@ import type { OpenAPIConfig } from './OpenAPI'; /** - * Request using fetch client + * Request method * @param config The OpenAPI configuration object * @param options The request options from the service * @returns CancelablePromise @@ -80,7 +80,7 @@ export const request = (config: OpenAPIConfig, options: ApiRequestOptions): C ok: response.ok, status: response.status, statusText: response.statusText, - body: responseHeader || responseBody, + body: responseHeader ?? responseBody, }; catchErrors(options, result); diff --git a/src/templates/core/fetch/sendRequest.hbs b/src/templates/core/fetch/sendRequest.hbs index fa10a698..d0a0c7c7 100644 --- a/src/templates/core/fetch/sendRequest.hbs +++ b/src/templates/core/fetch/sendRequest.hbs @@ -11,7 +11,7 @@ export const sendRequest = async ( const request: RequestInit = { headers, - body: body || formData, + body: body ?? formData, method: options.method, signal: controller.signal, }; diff --git a/src/templates/core/node/request.hbs b/src/templates/core/node/request.hbs index 367254d5..fdd33a26 100644 --- a/src/templates/core/node/request.hbs +++ b/src/templates/core/node/request.hbs @@ -60,7 +60,7 @@ import type { OpenAPIConfig } from './OpenAPI'; /** - * Request using node-fetch client + * Request method * @param config The OpenAPI configuration object * @param options The request options from the service * @returns CancelablePromise @@ -84,7 +84,7 @@ export const request = (config: OpenAPIConfig, options: ApiRequestOptions): C ok: response.ok, status: response.status, statusText: response.statusText, - body: responseHeader || responseBody, + body: responseHeader ?? responseBody, }; catchErrors(options, result); diff --git a/src/templates/core/node/sendRequest.hbs b/src/templates/core/node/sendRequest.hbs index 1160ad66..dd6ac3df 100644 --- a/src/templates/core/node/sendRequest.hbs +++ b/src/templates/core/node/sendRequest.hbs @@ -11,7 +11,7 @@ export const sendRequest = async ( const request: RequestInit = { headers, method: options.method, - body: body || formData, + body: body ?? formData, signal: controller.signal, }; diff --git a/src/templates/core/xhr/request.hbs b/src/templates/core/xhr/request.hbs index d9d32225..b5f91d4b 100644 --- a/src/templates/core/xhr/request.hbs +++ b/src/templates/core/xhr/request.hbs @@ -59,7 +59,7 @@ import type { OpenAPIConfig } from './OpenAPI'; /** - * Request using XHR client + * Request method * @param config The OpenAPI configuration object * @param options The request options from the service * @returns CancelablePromise @@ -83,7 +83,7 @@ export const request = (config: OpenAPIConfig, options: ApiRequestOptions): C ok: isSuccess(response.status), status: response.status, statusText: response.statusText, - body: responseHeader || responseBody, + body: responseHeader ?? responseBody, }; catchErrors(options, result); diff --git a/src/templates/core/xhr/sendRequest.hbs b/src/templates/core/xhr/sendRequest.hbs index d51f6e3c..ea2f8da5 100644 --- a/src/templates/core/xhr/sendRequest.hbs +++ b/src/templates/core/xhr/sendRequest.hbs @@ -19,7 +19,7 @@ export const sendRequest = async ( xhr.onload = () => resolve(xhr); xhr.onabort = () => reject(new Error('Request aborted')); xhr.onerror = () => reject(new Error('Network error')); - xhr.send(body || formData); + xhr.send(body ?? formData); onCancel(() => xhr.abort()); }); From 7b4352c48f1f390f3427acbb8366ccc00393bdf4 Mon Sep 17 00:00:00 2001 From: Ferdi Koomen Date: Tue, 25 Jan 2022 12:15:37 +0100 Subject: [PATCH 11/19] - Added write client class methods --- src/index.ts | 4 +++ src/templates/client.hbs | 8 ++--- src/templates/core/HttpRequest.hbs | 12 +++---- src/utils/registerHandlebarTemplates.ts | 9 +++++ src/utils/writeClient.spec.ts | 6 +++- src/utils/writeClient.ts | 9 +++++ src/utils/writeClientClass.spec.ts | 45 +++++++++++++++++++++++++ src/utils/writeClientClass.ts | 44 ++++++++++++++++++++++++ src/utils/writeClientCore.spec.ts | 3 ++ src/utils/writeClientIndex.spec.ts | 3 ++ src/utils/writeClientIndex.ts | 29 ++++++++-------- src/utils/writeClientModels.spec.ts | 3 ++ src/utils/writeClientSchemas.spec.ts | 3 ++ src/utils/writeClientServices.spec.ts | 3 ++ 14 files changed, 155 insertions(+), 26 deletions(-) create mode 100644 src/utils/writeClientClass.spec.ts create mode 100644 src/utils/writeClientClass.ts diff --git a/src/index.ts b/src/index.ts index 2949881a..fc733540 100644 --- a/src/index.ts +++ b/src/index.ts @@ -36,6 +36,7 @@ export type Options = { * @param input The relative location of the OpenAPI spec * @param output The relative location of the output directory * @param httpClient The selected httpClient (fetch, xhr, node or axios) + * @param clientName Custom client class name * @param useOptions Use options or arguments functions * @param useUnionTypes Use union types instead of enums * @param exportCore: Generate core client classes @@ -51,6 +52,7 @@ export async function generate({ input, output, httpClient = HttpClient.FETCH, + clientName, useOptions = false, useUnionTypes = false, exportCore = true, @@ -88,6 +90,7 @@ export async function generate({ exportSchemas, indent, postfix, + clientName, request ); break; @@ -110,6 +113,7 @@ export async function generate({ exportSchemas, indent, postfix, + clientName, request ); break; diff --git a/src/templates/client.hbs b/src/templates/client.hbs index 51afc61a..aea06c0e 100644 --- a/src/templates/client.hbs +++ b/src/templates/client.hbs @@ -5,7 +5,7 @@ import type { OpenAPIConfig } from './core/OpenAPI'; import { {{{httpRequest}}} } from './core/{{{httpRequest}}}'; {{#if services}} {{#each services}} -import { {{{name}}} } from './services/{{{name}}}'; +import { {{{name}}}{{{@root.postfix}}} } from './services/{{{name}}}{{{@root.postfix}}}'; {{/each}} {{/if}} @@ -14,10 +14,10 @@ type HttpRequestConstructor = new (config: OpenAPIConfig) => BaseHttpRequest; export class {{{clientName}}} { {{#each services}} - readonly {{{name}}}: {{{name}}}; + public readonly {{{name}}}: {{{name}}}{{{@root.postfix}}}; {{/each}} - readonly request: BaseHttpRequest; + public readonly request: BaseHttpRequest; constructor(config?: OpenAPIConfig, HttpRequest: HttpRequestConstructor = {{{httpRequest}}}) { this.request = new HttpRequest({ @@ -33,7 +33,7 @@ export class {{{clientName}}} { }); {{#each services}} - this.{{{name}}} = new {{{name}}}(this.request); + this.{{{name}}} = new {{{name}}}{{{@root.postfix}}}(this.request); {{/each}} } } diff --git a/src/templates/core/HttpRequest.hbs b/src/templates/core/HttpRequest.hbs index ed97a39b..01804e38 100644 --- a/src/templates/core/HttpRequest.hbs +++ b/src/templates/core/HttpRequest.hbs @@ -6,9 +6,9 @@ import { request as __request } from './request'; export class {{HttpRequest}} extends BaseHttpRequest { - constructor(config: OpenAPIConfig) { - super(config); - } + constructor(config: OpenAPIConfig) { + super(config); + } /** * Request method @@ -16,7 +16,7 @@ export class {{HttpRequest}} extends BaseHttpRequest { * @returns CancelablePromise * @throws ApiError */ - public request(options: ApiRequestOptions): CancelablePromise { - return __request(this.config, options); - } + public request(options: ApiRequestOptions): CancelablePromise { + return __request(this.config, options); + } } diff --git a/src/utils/registerHandlebarTemplates.ts b/src/utils/registerHandlebarTemplates.ts index 72569938..db4ec97c 100644 --- a/src/utils/registerHandlebarTemplates.ts +++ b/src/utils/registerHandlebarTemplates.ts @@ -1,6 +1,7 @@ import Handlebars from 'handlebars/runtime'; import { HttpClient } from '../HttpClient'; +import templateClient from '../templates/client.hbs'; import templateCoreApiError from '../templates/core/ApiError.hbs'; import templateCoreApiRequestOptions from '../templates/core/ApiRequestOptions.hbs'; import templateCoreApiResult from '../templates/core/ApiResult.hbs'; @@ -10,6 +11,7 @@ import axiosGetResponseBody from '../templates/core/axios/getResponseBody.hbs'; import axiosGetResponseHeader from '../templates/core/axios/getResponseHeader.hbs'; import axiosRequest from '../templates/core/axios/request.hbs'; import axiosSendRequest from '../templates/core/axios/sendRequest.hbs'; +import templateCoreBaseHttpRequest from '../templates/core/BaseHttpRequest.hbs'; import templateCancelablePromise from '../templates/core/CancelablePromise.hbs'; import fetchGetHeaders from '../templates/core/fetch/getHeaders.hbs'; import fetchGetRequestBody from '../templates/core/fetch/getRequestBody.hbs'; @@ -29,6 +31,7 @@ import functionIsString from '../templates/core/functions/isString.hbs'; import functionIsStringWithValue from '../templates/core/functions/isStringWithValue.hbs'; import functionIsSuccess from '../templates/core/functions/isSuccess.hbs'; import functionResolve from '../templates/core/functions/resolve.hbs'; +import templateCoreHttpRequest from '../templates/core/HttpRequest.hbs'; import nodeGetHeaders from '../templates/core/node/getHeaders.hbs'; import nodeGetRequestBody from '../templates/core/node/getRequestBody.hbs'; import nodeGetResponseBody from '../templates/core/node/getResponseBody.hbs'; @@ -78,6 +81,7 @@ import { registerHandlebarHelpers } from './registerHandlebarHelpers'; export interface Templates { index: Handlebars.TemplateDelegate; + client: Handlebars.TemplateDelegate; exports: { model: Handlebars.TemplateDelegate; schema: Handlebars.TemplateDelegate; @@ -90,6 +94,8 @@ export interface Templates { apiResult: Handlebars.TemplateDelegate; cancelablePromise: Handlebars.TemplateDelegate; request: Handlebars.TemplateDelegate; + baseHttpRequest: Handlebars.TemplateDelegate; + httpRequest: Handlebars.TemplateDelegate; }; } @@ -107,6 +113,7 @@ export function registerHandlebarTemplates(root: { // Main templates (entry points for the files we write to disk) const templates: Templates = { index: Handlebars.template(templateIndex), + client: Handlebars.template(templateClient), exports: { model: Handlebars.template(templateExportModel), schema: Handlebars.template(templateExportSchema), @@ -119,6 +126,8 @@ export function registerHandlebarTemplates(root: { apiResult: Handlebars.template(templateCoreApiResult), cancelablePromise: Handlebars.template(templateCancelablePromise), request: Handlebars.template(templateCoreRequest), + httpRequest: Handlebars.template(templateCoreBaseHttpRequest), + baseHttpRequest: Handlebars.template(templateCoreHttpRequest), }, }; diff --git a/src/utils/writeClient.spec.ts b/src/utils/writeClient.spec.ts index 5c472bea..bc38b4b6 100644 --- a/src/utils/writeClient.spec.ts +++ b/src/utils/writeClient.spec.ts @@ -18,6 +18,7 @@ describe('writeClient', () => { const templates: Templates = { index: () => 'index', + client: () => 'client', exports: { model: () => 'model', schema: () => 'schema', @@ -30,6 +31,8 @@ describe('writeClient', () => { apiResult: () => 'apiResult', cancelablePromise: () => 'cancelablePromise', request: () => 'request', + baseHttpRequest: () => 'baseHttpRequest', + httpRequest: () => 'httpRequest', }, }; @@ -45,7 +48,8 @@ describe('writeClient', () => { true, true, Indent.SPACE_4, - '' + 'Service', + 'AppClient' ); expect(rmdir).toBeCalled(); diff --git a/src/utils/writeClient.ts b/src/utils/writeClient.ts index 9f09ecd9..65571b63 100644 --- a/src/utils/writeClient.ts +++ b/src/utils/writeClient.ts @@ -4,8 +4,10 @@ import type { Client } from '../client/interfaces/Client'; import { HttpClient } from '../HttpClient'; import { Indent } from '../Indent'; import { mkdir, rmdir } from './fileSystem'; +import { isDefined } from './isDefined'; import { isSubDirectory } from './isSubdirectory'; import { Templates } from './registerHandlebarTemplates'; +import { writeClientClass } from './writeClientClass'; import { writeClientCore } from './writeClientCore'; import { writeClientIndex } from './writeClientIndex'; import { writeClientModels } from './writeClientModels'; @@ -27,6 +29,7 @@ import { writeClientServices } from './writeClientServices'; * @param exportSchemas: Generate schemas * @param indent: Indentation options (4, 2 or tab) * @param postfix: Service name postfix + * @param clientName: Custom client class name * @param request: Path to custom request file */ export async function writeClient( @@ -42,6 +45,7 @@ export async function writeClient( exportSchemas: boolean, indent: Indent, postfix: string, + clientName?: string, request?: string ): Promise { const outputPath = resolve(process.cwd(), output); @@ -87,6 +91,11 @@ export async function writeClient( await writeClientModels(client.models, templates, outputPathModels, httpClient, useUnionTypes, indent); } + if (isDefined(clientName)) { + await mkdir(outputPath); + await writeClientClass(client, templates, outputPath, httpClient, clientName, indent, postfix); + } + if (exportCore || exportServices || exportSchemas || exportModels) { await mkdir(outputPath); await writeClientIndex( diff --git a/src/utils/writeClientClass.spec.ts b/src/utils/writeClientClass.spec.ts new file mode 100644 index 00000000..871e2052 --- /dev/null +++ b/src/utils/writeClientClass.spec.ts @@ -0,0 +1,45 @@ +import type { Client } from '../client/interfaces/Client'; +import { HttpClient } from '../HttpClient'; +import { Indent } from '../Indent'; +import { mkdir, rmdir, writeFile } from './fileSystem'; +import { Templates } from './registerHandlebarTemplates'; +import { writeClientClass } from './writeClientClass'; + +jest.mock('./fileSystem'); + +describe('writeClientClass', () => { + it('should write to filesystem', async () => { + const client: Client = { + server: 'http://localhost:8080', + version: 'v1', + models: [], + services: [], + }; + + const templates: Templates = { + index: () => 'index', + client: () => 'client', + exports: { + model: () => 'model', + schema: () => 'schema', + service: () => 'service', + }, + core: { + settings: () => 'settings', + apiError: () => 'apiError', + apiRequestOptions: () => 'apiRequestOptions', + apiResult: () => 'apiResult', + cancelablePromise: () => 'cancelablePromise', + request: () => 'request', + baseHttpRequest: () => 'baseHttpRequest', + httpRequest: () => 'httpRequest', + }, + }; + + await writeClientClass(client, templates, './dist', HttpClient.FETCH, 'AppClient', Indent.SPACE_4, ''); + + expect(rmdir).toBeCalled(); + expect(mkdir).toBeCalled(); + expect(writeFile).toBeCalled(); + }); +}); diff --git a/src/utils/writeClientClass.ts b/src/utils/writeClientClass.ts new file mode 100644 index 00000000..ff0ef816 --- /dev/null +++ b/src/utils/writeClientClass.ts @@ -0,0 +1,44 @@ +import { resolve } from 'path'; + +import type { Client } from '../client/interfaces/Client'; +import { HttpClient } from '../HttpClient'; +import { Indent } from '../Indent'; +import { writeFile } from './fileSystem'; +import { formatCode as f } from './formatCode'; +import { formatIndentation as i } from './formatIndentation'; +import { Templates } from './registerHandlebarTemplates'; +import { sortModelsByName } from './sortModelsByName'; +import { sortServicesByName } from './sortServicesByName'; +/** + * Generate the OpenAPI client index file using the Handlebar template and write it to disk. + * The index file just contains all the exports you need to use the client as a standalone + * library. But yuo can also import individual models and services directly. + * @param client Client object, containing, models, schemas and services + * @param templates The loaded handlebar templates + * @param outputPath Directory to write the generated files to + * @param httpClient The selected httpClient (fetch, xhr, node or axios) + * @param clientName Custom client class name + * @param indent: Indentation options (4, 2 or tab) + * @param postfix: Service name postfix + */ +export async function writeClientClass( + client: Client, + templates: Templates, + outputPath: string, + httpClient: HttpClient, + clientName: string, + indent: Indent, + postfix: string +): Promise { + const templateResult = templates.client({ + clientName, + postfix, + server: client.server, + version: client.version, + models: sortModelsByName(client.models), + services: sortServicesByName(client.services), + httpRequest: 'XhrBaseRequest', + }); + + await writeFile(resolve(outputPath, 'client.ts'), i(f(templateResult), indent)); +} diff --git a/src/utils/writeClientCore.spec.ts b/src/utils/writeClientCore.spec.ts index b96780ad..b9222227 100644 --- a/src/utils/writeClientCore.spec.ts +++ b/src/utils/writeClientCore.spec.ts @@ -18,6 +18,7 @@ describe('writeClientCore', () => { const templates: Templates = { index: () => 'index', + client: () => 'client', exports: { model: () => 'model', schema: () => 'schema', @@ -30,6 +31,8 @@ describe('writeClientCore', () => { apiResult: () => 'apiResult', cancelablePromise: () => 'cancelablePromise', request: () => 'request', + baseHttpRequest: () => 'baseHttpRequest', + httpRequest: () => 'httpRequest', }, }; diff --git a/src/utils/writeClientIndex.spec.ts b/src/utils/writeClientIndex.spec.ts index a5d243b1..ffc365bd 100644 --- a/src/utils/writeClientIndex.spec.ts +++ b/src/utils/writeClientIndex.spec.ts @@ -16,6 +16,7 @@ describe('writeClientIndex', () => { const templates: Templates = { index: () => 'index', + client: () => 'client', exports: { model: () => 'model', schema: () => 'schema', @@ -28,6 +29,8 @@ describe('writeClientIndex', () => { apiResult: () => 'apiResult', cancelablePromise: () => 'cancelablePromise', request: () => 'request', + baseHttpRequest: () => 'baseHttpRequest', + httpRequest: () => 'httpRequest', }, }; diff --git a/src/utils/writeClientIndex.ts b/src/utils/writeClientIndex.ts index 8336471e..6fe74fa2 100644 --- a/src/utils/writeClientIndex.ts +++ b/src/utils/writeClientIndex.ts @@ -31,19 +31,18 @@ export async function writeClientIndex( exportSchemas: boolean, postfix: string ): Promise { - await writeFile( - resolve(outputPath, 'index.ts'), - templates.index({ - exportCore, - exportServices, - exportModels, - exportSchemas, - useUnionTypes, - postfix, - server: client.server, - version: client.version, - models: sortModelsByName(client.models), - services: sortServicesByName(client.services), - }) - ); + const templateResult = templates.index({ + exportCore, + exportServices, + exportModels, + exportSchemas, + useUnionTypes, + postfix, + server: client.server, + version: client.version, + models: sortModelsByName(client.models), + services: sortServicesByName(client.services), + }); + + await writeFile(resolve(outputPath, 'index.ts'), templateResult); } diff --git a/src/utils/writeClientModels.spec.ts b/src/utils/writeClientModels.spec.ts index 359849dc..61e2255b 100644 --- a/src/utils/writeClientModels.spec.ts +++ b/src/utils/writeClientModels.spec.ts @@ -31,6 +31,7 @@ describe('writeClientModels', () => { const templates: Templates = { index: () => 'index', + client: () => 'client', exports: { model: () => 'model', schema: () => 'schema', @@ -43,6 +44,8 @@ describe('writeClientModels', () => { apiResult: () => 'apiResult', cancelablePromise: () => 'cancelablePromise', request: () => 'request', + baseHttpRequest: () => 'baseHttpRequest', + httpRequest: () => 'httpRequest', }, }; diff --git a/src/utils/writeClientSchemas.spec.ts b/src/utils/writeClientSchemas.spec.ts index 4c1f34ce..1f917223 100644 --- a/src/utils/writeClientSchemas.spec.ts +++ b/src/utils/writeClientSchemas.spec.ts @@ -31,6 +31,7 @@ describe('writeClientSchemas', () => { const templates: Templates = { index: () => 'index', + client: () => 'client', exports: { model: () => 'model', schema: () => 'schema', @@ -43,6 +44,8 @@ describe('writeClientSchemas', () => { apiResult: () => 'apiResult', cancelablePromise: () => 'cancelablePromise', request: () => 'request', + baseHttpRequest: () => 'baseHttpRequest', + httpRequest: () => 'httpRequest', }, }; diff --git a/src/utils/writeClientServices.spec.ts b/src/utils/writeClientServices.spec.ts index 1f185db8..387ea208 100644 --- a/src/utils/writeClientServices.spec.ts +++ b/src/utils/writeClientServices.spec.ts @@ -19,6 +19,7 @@ describe('writeClientServices', () => { const templates: Templates = { index: () => 'index', + client: () => 'client', exports: { model: () => 'model', schema: () => 'schema', @@ -31,6 +32,8 @@ describe('writeClientServices', () => { apiResult: () => 'apiResult', cancelablePromise: () => 'cancelablePromise', request: () => 'request', + baseHttpRequest: () => 'baseHttpRequest', + httpRequest: () => 'httpRequest', }, }; From c6c9d2b879a9f9769a62a0e899b55415ee88b008 Mon Sep 17 00:00:00 2001 From: Ferdi Koomen Date: Tue, 25 Jan 2022 12:31:24 +0100 Subject: [PATCH 12/19] - Added output of httpRequest files --- src/templates/core/HttpRequest.hbs | 6 ++++-- src/utils/registerHandlebarTemplates.ts | 4 ++-- src/utils/writeClient.ts | 2 +- src/utils/writeClientClass.ts | 2 +- src/utils/writeClientCore.ts | 12 +++++++++++- 5 files changed, 19 insertions(+), 7 deletions(-) diff --git a/src/templates/core/HttpRequest.hbs b/src/templates/core/HttpRequest.hbs index 01804e38..3a3a3308 100644 --- a/src/templates/core/HttpRequest.hbs +++ b/src/templates/core/HttpRequest.hbs @@ -1,10 +1,12 @@ {{>header}} -import type { BaseHttpRequest } from './BaseHttpRequest'; +import type { ApiRequestOptions } from './ApiRequestOptions'; +import { BaseHttpRequest } from './BaseHttpRequest'; +import type { CancelablePromise } from './CancelablePromise'; import type { OpenAPIConfig } from './OpenAPI'; import { request as __request } from './request'; -export class {{HttpRequest}} extends BaseHttpRequest { +export class {{httpRequest}} extends BaseHttpRequest { constructor(config: OpenAPIConfig) { super(config); diff --git a/src/utils/registerHandlebarTemplates.ts b/src/utils/registerHandlebarTemplates.ts index db4ec97c..a64a6f61 100644 --- a/src/utils/registerHandlebarTemplates.ts +++ b/src/utils/registerHandlebarTemplates.ts @@ -126,8 +126,8 @@ export function registerHandlebarTemplates(root: { apiResult: Handlebars.template(templateCoreApiResult), cancelablePromise: Handlebars.template(templateCancelablePromise), request: Handlebars.template(templateCoreRequest), - httpRequest: Handlebars.template(templateCoreBaseHttpRequest), - baseHttpRequest: Handlebars.template(templateCoreHttpRequest), + baseHttpRequest: Handlebars.template(templateCoreBaseHttpRequest), + httpRequest: Handlebars.template(templateCoreHttpRequest), }, }; diff --git a/src/utils/writeClient.ts b/src/utils/writeClient.ts index 65571b63..a00d0048 100644 --- a/src/utils/writeClient.ts +++ b/src/utils/writeClient.ts @@ -61,7 +61,7 @@ export async function writeClient( if (exportCore) { await rmdir(outputPathCore); await mkdir(outputPathCore); - await writeClientCore(client, templates, outputPathCore, httpClient, indent, request); + await writeClientCore(client, templates, outputPathCore, httpClient, indent, clientName, request); } if (exportServices) { diff --git a/src/utils/writeClientClass.ts b/src/utils/writeClientClass.ts index ff0ef816..e0a7cb49 100644 --- a/src/utils/writeClientClass.ts +++ b/src/utils/writeClientClass.ts @@ -37,7 +37,7 @@ export async function writeClientClass( version: client.version, models: sortModelsByName(client.models), services: sortServicesByName(client.services), - httpRequest: 'XhrBaseRequest', + httpRequest: 'XHRHttpRequest', }); await writeFile(resolve(outputPath, 'client.ts'), i(f(templateResult), indent)); diff --git a/src/utils/writeClientCore.ts b/src/utils/writeClientCore.ts index fe498f6b..87d9846b 100644 --- a/src/utils/writeClientCore.ts +++ b/src/utils/writeClientCore.ts @@ -3,9 +3,11 @@ import { resolve } from 'path'; import type { Client } from '../client/interfaces/Client'; import { HttpClient } from '../HttpClient'; import { Indent } from '../Indent'; -import { copyFile, exists, writeFile } from './fileSystem'; +import { copyFile, exists, mkdir, writeFile } from './fileSystem'; import { formatIndentation as i } from './formatIndentation'; +import { isDefined } from './isDefined'; import { Templates } from './registerHandlebarTemplates'; +import { writeClientClass } from './writeClientClass'; /** * Generate OpenAPI core files, this includes the basic boilerplate code to handle requests. @@ -22,12 +24,15 @@ export async function writeClientCore( outputPath: string, httpClient: HttpClient, indent: Indent, + clientName?: string, request?: string ): Promise { const context = { httpClient, + clientName, server: client.server, version: client.version, + httpRequest: 'XHRHttpRequest', }; await writeFile(resolve(outputPath, 'OpenAPI.ts'), i(templates.core.settings(context), indent)); @@ -37,6 +42,11 @@ export async function writeClientCore( await writeFile(resolve(outputPath, 'CancelablePromise.ts'), i(templates.core.cancelablePromise(context), indent)); await writeFile(resolve(outputPath, 'request.ts'), i(templates.core.request(context), indent)); + if (isDefined(clientName)) { + await writeFile(resolve(outputPath, 'BaseHttpRequest.ts'), i(templates.core.baseHttpRequest(context), indent)); + await writeFile(resolve(outputPath, 'XHRHttpRequest.ts'), i(templates.core.httpRequest(context), indent)); + } + if (request) { const requestFile = resolve(process.cwd(), request); const requestFileExists = await exists(requestFile); From 280d196f99b9635a22ac6af4d73c2d024544689f Mon Sep 17 00:00:00 2001 From: Ferdi Koomen Date: Tue, 25 Jan 2022 13:22:21 +0100 Subject: [PATCH 13/19] - Moved to const definitions for functions --- rollup.config.js | 1 + src/index.ts | 6 +++--- src/openApi/v2/index.ts | 4 ++-- src/openApi/v2/parser/escapeName.ts | 4 ++-- src/openApi/v2/parser/extendEnum.ts | 4 ++-- src/openApi/v2/parser/getEnum.ts | 4 ++-- src/openApi/v2/parser/getEnumFromDescription.ts | 4 ++-- src/openApi/v2/parser/getMappedType.ts | 4 ++-- src/openApi/v2/parser/getModel.ts | 6 +++--- src/openApi/v2/parser/getModelComposition.ts | 6 +++--- src/openApi/v2/parser/getModelProperties.ts | 4 ++-- src/openApi/v2/parser/getModelTemplate.ts | 4 ++-- src/openApi/v2/parser/getModels.ts | 4 ++-- src/openApi/v2/parser/getOperation.ts | 9 ++++----- src/openApi/v2/parser/getOperationErrors.ts | 4 ++-- src/openApi/v2/parser/getOperationName.ts | 4 ++-- src/openApi/v2/parser/getOperationParameter.ts | 4 ++-- .../v2/parser/getOperationParameterDefault.ts | 6 +++--- src/openApi/v2/parser/getOperationParameterName.ts | 4 ++-- src/openApi/v2/parser/getOperationParameters.ts | 4 ++-- src/openApi/v2/parser/getOperationPath.ts | 4 ++-- src/openApi/v2/parser/getOperationResponse.ts | 6 +++--- src/openApi/v2/parser/getOperationResponseCode.ts | 4 ++-- .../v2/parser/getOperationResponseHeader.ts | 4 ++-- src/openApi/v2/parser/getOperationResponses.ts | 4 ++-- src/openApi/v2/parser/getOperationResults.ts | 8 ++++---- src/openApi/v2/parser/getRef.ts | 4 ++-- .../parser/getRequiredPropertiesFromComposition.ts | 6 +++--- src/openApi/v2/parser/getServer.ts | 4 ++-- src/openApi/v2/parser/getServiceName.ts | 4 ++-- src/openApi/v2/parser/getServiceVersion.ts | 4 ++-- src/openApi/v2/parser/getServices.ts | 6 +++--- src/openApi/v2/parser/getType.ts | 8 ++++---- src/openApi/v2/parser/sortByRequired.ts | 4 ++-- src/openApi/v2/parser/stripNamespace.ts | 4 ++-- src/openApi/v3/index.ts | 4 ++-- src/openApi/v3/parser/escapeName.ts | 4 ++-- src/openApi/v3/parser/extendEnum.ts | 4 ++-- src/openApi/v3/parser/getContent.ts | 4 ++-- src/openApi/v3/parser/getEnum.ts | 4 ++-- src/openApi/v3/parser/getEnumFromDescription.ts | 4 ++-- src/openApi/v3/parser/getMappedType.ts | 4 ++-- src/openApi/v3/parser/getModel.ts | 6 +++--- src/openApi/v3/parser/getModelComposition.ts | 6 +++--- src/openApi/v3/parser/getModelDefault.ts | 4 ++-- src/openApi/v3/parser/getModelProperties.ts | 6 +++--- src/openApi/v3/parser/getModelTemplate.ts | 4 ++-- src/openApi/v3/parser/getModels.ts | 4 ++-- src/openApi/v3/parser/getOperation.ts | 9 ++++----- src/openApi/v3/parser/getOperationErrors.ts | 4 ++-- src/openApi/v3/parser/getOperationName.ts | 4 ++-- src/openApi/v3/parser/getOperationParameter.ts | 4 ++-- src/openApi/v3/parser/getOperationParameterName.ts | 4 ++-- src/openApi/v3/parser/getOperationParameters.ts | 4 ++-- src/openApi/v3/parser/getOperationPath.ts | 4 ++-- src/openApi/v3/parser/getOperationRequestBody.ts | 4 ++-- src/openApi/v3/parser/getOperationResponse.ts | 6 +++--- src/openApi/v3/parser/getOperationResponseCode.ts | 4 ++-- .../v3/parser/getOperationResponseHeader.ts | 4 ++-- src/openApi/v3/parser/getOperationResponses.ts | 4 ++-- src/openApi/v3/parser/getOperationResults.ts | 8 ++++---- src/openApi/v3/parser/getRef.ts | 4 ++-- .../parser/getRequiredPropertiesFromComposition.ts | 6 +++--- src/openApi/v3/parser/getServer.ts | 4 ++-- src/openApi/v3/parser/getServiceName.ts | 4 ++-- src/openApi/v3/parser/getServiceVersion.ts | 4 ++-- src/openApi/v3/parser/getServices.ts | 6 +++--- src/openApi/v3/parser/getType.ts | 8 ++++---- src/openApi/v3/parser/sortByRequired.ts | 4 ++-- src/openApi/v3/parser/stripNamespace.ts | 4 ++-- src/templates/__mocks__/index.ts | 2 +- src/templates/client.hbs | 4 ++-- src/utils/discriminator.ts | 12 ++++++------ src/utils/flatMap.ts | 6 +++--- src/utils/formatCode.ts | 4 ++-- src/utils/formatIndentation.ts | 4 ++-- src/utils/getModelNames.ts | 4 ++-- src/utils/getOpenApiSpec.ts | 4 ++-- src/utils/getOpenApiVersion.ts | 4 ++-- src/utils/getPattern.ts | 4 ++-- src/utils/getServiceNames.ts | 4 ++-- src/utils/isDefined.ts | 4 ++-- src/utils/isEqual.ts | 4 ++-- src/utils/isString.ts | 4 ++-- src/utils/isSubdirectory.ts | 4 ++-- src/utils/postProcessClient.ts | 4 ++-- src/utils/postProcessModel.ts | 4 ++-- src/utils/postProcessModelEnum.ts | 4 ++-- src/utils/postProcessModelEnums.ts | 4 ++-- src/utils/postProcessModelImports.ts | 4 ++-- src/utils/postProcessService.ts | 4 ++-- src/utils/postProcessServiceImports.ts | 4 ++-- src/utils/postProcessServiceOperations.ts | 4 ++-- src/utils/readSpec.ts | 4 ++-- src/utils/readSpecFromDisk.ts | 4 ++-- src/utils/readSpecFromHttp.ts | 4 ++-- src/utils/readSpecFromHttps.ts | 4 ++-- src/utils/registerHandlebarHelpers.spec.ts | 1 + src/utils/registerHandlebarHelpers.ts | 11 ++++++++--- src/utils/registerHandlebarTemplates.ts | 6 +++--- src/utils/sort.ts | 4 ++-- src/utils/sortModelsByName.ts | 4 ++-- src/utils/sortServicesByName.ts | 4 ++-- src/utils/unique.ts | 4 ++-- src/utils/writeClient.ts | 6 +++--- src/utils/writeClientClass.ts | 6 +++--- src/utils/writeClientCore.ts | 9 ++++----- src/utils/writeClientIndex.ts | 6 +++--- src/utils/writeClientModels.ts | 6 +++--- src/utils/writeClientSchemas.ts | 6 +++--- src/utils/writeClientServices.ts | 6 +++--- test/custom/request.ts | 8 ++++---- test/spec/v2.json | 6 ++++++ test/spec/v3.json | 14 ++++++++++++-- 114 files changed, 286 insertions(+), 266 deletions(-) diff --git a/rollup.config.js b/rollup.config.js index 59e8d39e..6f085f8d 100644 --- a/rollup.config.js +++ b/rollup.config.js @@ -36,6 +36,7 @@ const handlebarsPlugin = () => ({ enumerator: true, escapeComment: true, escapeDescription: true, + camelCase: true, }, }); return `export default ${templateSpec};`; diff --git a/src/index.ts b/src/index.ts index fc733540..eef0c2dc 100644 --- a/src/index.ts +++ b/src/index.ts @@ -48,7 +48,7 @@ export type Options = { * @param request: Path to custom request file * @param write Write the files to disk (true or false) */ -export async function generate({ +export const generate = async ({ input, output, httpClient = HttpClient.FETCH, @@ -63,7 +63,7 @@ export async function generate({ postfix = 'Service', request, write = true, -}: Options): Promise { +}: Options): Promise => { const openApi = isString(input) ? await getOpenApiSpec(input) : input; const openApiVersion = getOpenApiVersion(openApi); const templates = registerHandlebarTemplates({ @@ -119,7 +119,7 @@ export async function generate({ break; } } -} +}; export default { HttpClient, diff --git a/src/openApi/v2/index.ts b/src/openApi/v2/index.ts index 30bd05cc..9dbdadb3 100644 --- a/src/openApi/v2/index.ts +++ b/src/openApi/v2/index.ts @@ -10,11 +10,11 @@ import { getServiceVersion } from './parser/getServiceVersion'; * all the models, services and schema's we should output. * @param openApi The OpenAPI spec that we have loaded from disk. */ -export function parse(openApi: OpenApi): Client { +export const parse = (openApi: OpenApi): Client => { const version = getServiceVersion(openApi.info.version); const server = getServer(openApi); const models = getModels(openApi); const services = getServices(openApi); return { version, server, models, services }; -} +}; diff --git a/src/openApi/v2/parser/escapeName.ts b/src/openApi/v2/parser/escapeName.ts index 0a26cb65..6b23d934 100644 --- a/src/openApi/v2/parser/escapeName.ts +++ b/src/openApi/v2/parser/escapeName.ts @@ -1,4 +1,4 @@ -export function escapeName(value: string): string { +export const escapeName = (value: string): string => { if (value) { const validName = /^[a-zA-Z_$][\w$]+$/g.test(value); if (!validName) { @@ -6,4 +6,4 @@ export function escapeName(value: string): string { } } return value; -} +}; diff --git a/src/openApi/v2/parser/extendEnum.ts b/src/openApi/v2/parser/extendEnum.ts index 81e85fdf..0a5ebeb1 100644 --- a/src/openApi/v2/parser/extendEnum.ts +++ b/src/openApi/v2/parser/extendEnum.ts @@ -7,7 +7,7 @@ import type { WithEnumExtension } from '../interfaces/Extensions/WithEnumExtensi * @param enumerators * @param definition */ -export function extendEnum(enumerators: Enum[], definition: WithEnumExtension): Enum[] { +export const extendEnum = (enumerators: Enum[], definition: WithEnumExtension): Enum[] => { const names = definition['x-enum-varnames']; const descriptions = definition['x-enum-descriptions']; @@ -17,4 +17,4 @@ export function extendEnum(enumerators: Enum[], definition: WithEnumExtension): value: enumerator.value, type: enumerator.type, })); -} +}; diff --git a/src/openApi/v2/parser/getEnum.ts b/src/openApi/v2/parser/getEnum.ts index 5558db68..c684b466 100644 --- a/src/openApi/v2/parser/getEnum.ts +++ b/src/openApi/v2/parser/getEnum.ts @@ -1,7 +1,7 @@ import type { Enum } from '../../../client/interfaces/Enum'; import { isDefined } from '../../../utils/isDefined'; -export function getEnum(values?: (string | number)[]): Enum[] { +export const getEnum = (values?: (string | number)[]): Enum[] => { if (Array.isArray(values)) { return values .filter((value, index, arr) => { @@ -30,4 +30,4 @@ export function getEnum(values?: (string | number)[]): Enum[] { }); } return []; -} +}; diff --git a/src/openApi/v2/parser/getEnumFromDescription.ts b/src/openApi/v2/parser/getEnumFromDescription.ts index d1154e6e..0f49cf40 100644 --- a/src/openApi/v2/parser/getEnumFromDescription.ts +++ b/src/openApi/v2/parser/getEnumFromDescription.ts @@ -3,7 +3,7 @@ import type { Enum } from '../../../client/interfaces/Enum'; /** * @deprecated */ -export function getEnumFromDescription(description: string): Enum[] { +export const getEnumFromDescription = (description: string): Enum[] => { // Check if we can find this special format string: // None=0,Something=1,AnotherThing=2 if (/^(\w+=[0-9]+)/g.test(description)) { @@ -36,4 +36,4 @@ export function getEnumFromDescription(description: string): Enum[] { } return []; -} +}; diff --git a/src/openApi/v2/parser/getMappedType.ts b/src/openApi/v2/parser/getMappedType.ts index e44434e2..a7c32fd8 100644 --- a/src/openApi/v2/parser/getMappedType.ts +++ b/src/openApi/v2/parser/getMappedType.ts @@ -24,9 +24,9 @@ const TYPE_MAPPINGS = new Map([ /** * Get mapped type for given type to any basic Typescript/Javascript type. */ -export function getMappedType(type: string, format?: string): string | undefined { +export const getMappedType = (type: string, format?: string): string | undefined => { if (format === 'binary') { return 'binary'; } return TYPE_MAPPINGS.get(type); -} +}; diff --git a/src/openApi/v2/parser/getModel.ts b/src/openApi/v2/parser/getModel.ts index d5683f07..8ac1bc11 100644 --- a/src/openApi/v2/parser/getModel.ts +++ b/src/openApi/v2/parser/getModel.ts @@ -9,12 +9,12 @@ import { getModelComposition } from './getModelComposition'; import { getModelProperties } from './getModelProperties'; import { getType } from './getType'; -export function getModel( +export const getModel = ( openApi: OpenApi, definition: OpenApiSchema, isDefinition: boolean = false, name: string = '' -): Model { +): Model => { const model: Model = { name, export: 'interface', @@ -162,4 +162,4 @@ export function getModel( } return model; -} +}; diff --git a/src/openApi/v2/parser/getModelComposition.ts b/src/openApi/v2/parser/getModelComposition.ts index 468dbe26..6b5e4c30 100644 --- a/src/openApi/v2/parser/getModelComposition.ts +++ b/src/openApi/v2/parser/getModelComposition.ts @@ -9,13 +9,13 @@ import { getRequiredPropertiesFromComposition } from './getRequiredPropertiesFro // Fix for circular dependency export type GetModelFn = typeof getModel; -export function getModelComposition( +export const getModelComposition = ( openApi: OpenApi, definition: OpenApiSchema, definitions: OpenApiSchema[], type: 'one-of' | 'any-of' | 'all-of', getModel: GetModelFn -): ModelComposition { +): ModelComposition => { const composition: ModelComposition = { type, imports: [], @@ -87,4 +87,4 @@ export function getModelComposition( } return composition; -} +}; diff --git a/src/openApi/v2/parser/getModelProperties.ts b/src/openApi/v2/parser/getModelProperties.ts index fcb07fc9..7560be76 100644 --- a/src/openApi/v2/parser/getModelProperties.ts +++ b/src/openApi/v2/parser/getModelProperties.ts @@ -9,7 +9,7 @@ import { getType } from './getType'; // Fix for circular dependency export type GetModelFn = typeof getModel; -export function getModelProperties(openApi: OpenApi, definition: OpenApiSchema, getModel: GetModelFn): Model[] { +export const getModelProperties = (openApi: OpenApi, definition: OpenApiSchema, getModel: GetModelFn): Model[] => { const models: Model[] = []; for (const propertyName in definition.properties) { if (definition.properties.hasOwnProperty(propertyName)) { @@ -85,4 +85,4 @@ export function getModelProperties(openApi: OpenApi, definition: OpenApiSchema, } } return models; -} +}; diff --git a/src/openApi/v2/parser/getModelTemplate.ts b/src/openApi/v2/parser/getModelTemplate.ts index 26902ea0..b2aa0b33 100644 --- a/src/openApi/v2/parser/getModelTemplate.ts +++ b/src/openApi/v2/parser/getModelTemplate.ts @@ -6,6 +6,6 @@ import type { Type } from '../../../client/interfaces/Type'; * @param modelClass The parsed model class type. * @returns The model template type ( or empty). */ -export function getModelTemplate(modelClass: Type): string { +export const getModelTemplate = (modelClass: Type): string => { return modelClass.template ? '' : ''; -} +}; diff --git a/src/openApi/v2/parser/getModels.ts b/src/openApi/v2/parser/getModels.ts index b22e5c12..d9febc06 100644 --- a/src/openApi/v2/parser/getModels.ts +++ b/src/openApi/v2/parser/getModels.ts @@ -3,7 +3,7 @@ import type { OpenApi } from '../interfaces/OpenApi'; import { getModel } from './getModel'; import { getType } from './getType'; -export function getModels(openApi: OpenApi): Model[] { +export const getModels = (openApi: OpenApi): Model[] => { const models: Model[] = []; for (const definitionName in openApi.definitions) { if (openApi.definitions.hasOwnProperty(definitionName)) { @@ -14,4 +14,4 @@ export function getModels(openApi: OpenApi): Model[] { } } return models; -} +}; diff --git a/src/openApi/v2/parser/getOperation.ts b/src/openApi/v2/parser/getOperation.ts index f70e7f21..e344c7f9 100644 --- a/src/openApi/v2/parser/getOperation.ts +++ b/src/openApi/v2/parser/getOperation.ts @@ -12,17 +12,16 @@ import { getOperationResults } from './getOperationResults'; import { getServiceName } from './getServiceName'; import { sortByRequired } from './sortByRequired'; -export function getOperation( +export const getOperation = ( openApi: OpenApi, url: string, method: string, tag: string, op: OpenApiOperation, pathParams: OperationParameters -): Operation { +): Operation => { const serviceName = getServiceName(tag); - const operationNameFallback = `${method}${serviceName}`; - const operationName = getOperationName(op.operationId || operationNameFallback); + const operationName = getOperationName(op.operationId || `${method}`); const operationPath = getOperationPath(url); // Create a new operation object for this method. @@ -76,4 +75,4 @@ export function getOperation( operation.parameters = operation.parameters.sort(sortByRequired); return operation; -} +}; diff --git a/src/openApi/v2/parser/getOperationErrors.ts b/src/openApi/v2/parser/getOperationErrors.ts index 3e0ed0b9..ef4c12e5 100644 --- a/src/openApi/v2/parser/getOperationErrors.ts +++ b/src/openApi/v2/parser/getOperationErrors.ts @@ -5,7 +5,7 @@ import type { OperationResponse } from '../../../client/interfaces/OperationResp * * @param operationResponses */ -export function getOperationErrors(operationResponses: OperationResponse[]): OperationError[] { +export const getOperationErrors = (operationResponses: OperationResponse[]): OperationError[] => { return operationResponses .filter(operationResponse => { return operationResponse.code >= 300 && operationResponse.description; @@ -14,4 +14,4 @@ export function getOperationErrors(operationResponses: OperationResponse[]): Ope code: response.code, description: response.description!, })); -} +}; diff --git a/src/openApi/v2/parser/getOperationName.ts b/src/openApi/v2/parser/getOperationName.ts index 9a993d8d..663a758d 100644 --- a/src/openApi/v2/parser/getOperationName.ts +++ b/src/openApi/v2/parser/getOperationName.ts @@ -5,10 +5,10 @@ import camelCase from 'camelcase'; * This converts the input string to camelCase, so the method name follows * the most popular Javascript and Typescript writing style. */ -export function getOperationName(value: string): string { +export const getOperationName = (value: string): string => { const clean = value .replace(/^[^a-zA-Z]+/g, '') .replace(/[^\w\-]+/g, '-') .trim(); return camelCase(clean); -} +}; diff --git a/src/openApi/v2/parser/getOperationParameter.ts b/src/openApi/v2/parser/getOperationParameter.ts index 7bfb136d..31fdab6a 100644 --- a/src/openApi/v2/parser/getOperationParameter.ts +++ b/src/openApi/v2/parser/getOperationParameter.ts @@ -12,7 +12,7 @@ import { getOperationParameterName } from './getOperationParameterName'; import { getRef } from './getRef'; import { getType } from './getType'; -export function getOperationParameter(openApi: OpenApi, parameter: OpenApiParameter): OperationParameter { +export const getOperationParameter = (openApi: OpenApi, parameter: OpenApiParameter): OperationParameter => { const operationParameter: OperationParameter = { in: parameter.in, prop: parameter.name, @@ -147,4 +147,4 @@ export function getOperationParameter(openApi: OpenApi, parameter: OpenApiParame } return operationParameter; -} +}; diff --git a/src/openApi/v2/parser/getOperationParameterDefault.ts b/src/openApi/v2/parser/getOperationParameterDefault.ts index c7f97e14..87ace2b9 100644 --- a/src/openApi/v2/parser/getOperationParameterDefault.ts +++ b/src/openApi/v2/parser/getOperationParameterDefault.ts @@ -1,10 +1,10 @@ import type { OperationParameter } from '../../../client/interfaces/OperationParameter'; import type { OpenApiParameter } from '../interfaces/OpenApiParameter'; -export function getOperationParameterDefault( +export const getOperationParameterDefault = ( parameter: OpenApiParameter, operationParameter: OperationParameter -): string | undefined { +): string | undefined => { if (parameter.default === undefined) { return; } @@ -39,4 +39,4 @@ export function getOperationParameterDefault( } return; -} +}; diff --git a/src/openApi/v2/parser/getOperationParameterName.ts b/src/openApi/v2/parser/getOperationParameterName.ts index 0954d736..de9b154b 100644 --- a/src/openApi/v2/parser/getOperationParameterName.ts +++ b/src/openApi/v2/parser/getOperationParameterName.ts @@ -7,10 +7,10 @@ const reservedWords = * Replaces any invalid characters from a parameter name. * For example: 'filter.someProperty' becomes 'filterSomeProperty'. */ -export function getOperationParameterName(value: string): string { +export const getOperationParameterName = (value: string): string => { const clean = value .replace(/^[^a-zA-Z]+/g, '') .replace(/[^\w\-]+/g, '-') .trim(); return camelCase(clean).replace(reservedWords, '_$1'); -} +}; diff --git a/src/openApi/v2/parser/getOperationParameters.ts b/src/openApi/v2/parser/getOperationParameters.ts index 6bba9bc4..f265d1cc 100644 --- a/src/openApi/v2/parser/getOperationParameters.ts +++ b/src/openApi/v2/parser/getOperationParameters.ts @@ -4,7 +4,7 @@ import type { OpenApiParameter } from '../interfaces/OpenApiParameter'; import { getOperationParameter } from './getOperationParameter'; import { getRef } from './getRef'; -export function getOperationParameters(openApi: OpenApi, parameters: OpenApiParameter[]): OperationParameters { +export const getOperationParameters = (openApi: OpenApi, parameters: OpenApiParameter[]): OperationParameters => { const operationParameters: OperationParameters = { imports: [], parameters: [], @@ -58,4 +58,4 @@ export function getOperationParameters(openApi: OpenApi, parameters: OpenApiPara } }); return operationParameters; -} +}; diff --git a/src/openApi/v2/parser/getOperationPath.ts b/src/openApi/v2/parser/getOperationPath.ts index 7d2a07cf..17594a2c 100644 --- a/src/openApi/v2/parser/getOperationPath.ts +++ b/src/openApi/v2/parser/getOperationPath.ts @@ -7,10 +7,10 @@ import { getOperationParameterName } from './getOperationParameterName'; * Plus we return the correct parameter names to replace in the URL. * @param path */ -export function getOperationPath(path: string): string { +export const getOperationPath = (path: string): string => { return path .replace(/\{(.*?)\}/g, (_, w: string) => { return `\${${getOperationParameterName(w)}}`; }) .replace('${apiVersion}', '${OpenAPI.VERSION}'); -} +}; diff --git a/src/openApi/v2/parser/getOperationResponse.ts b/src/openApi/v2/parser/getOperationResponse.ts index c7611915..8f6c3ca5 100644 --- a/src/openApi/v2/parser/getOperationResponse.ts +++ b/src/openApi/v2/parser/getOperationResponse.ts @@ -7,11 +7,11 @@ import { getModel } from './getModel'; import { getRef } from './getRef'; import { getType } from './getType'; -export function getOperationResponse( +export const getOperationResponse = ( openApi: OpenApi, response: OpenApiResponse, responseCode: number -): OperationResponse { +): OperationResponse => { const operationResponse: OperationResponse = { in: 'response', name: '', @@ -96,4 +96,4 @@ export function getOperationResponse( } return operationResponse; -} +}; diff --git a/src/openApi/v2/parser/getOperationResponseCode.ts b/src/openApi/v2/parser/getOperationResponseCode.ts index c5609938..f34c99b7 100644 --- a/src/openApi/v2/parser/getOperationResponseCode.ts +++ b/src/openApi/v2/parser/getOperationResponseCode.ts @@ -1,4 +1,4 @@ -export function getOperationResponseCode(value: string | 'default'): number | null { +export const getOperationResponseCode = (value: string | 'default'): number | null => { // You can specify a "default" response, this is treated as HTTP code 200 if (value === 'default') { return 200; @@ -13,4 +13,4 @@ export function getOperationResponseCode(value: string | 'default'): number | nu } return null; -} +}; diff --git a/src/openApi/v2/parser/getOperationResponseHeader.ts b/src/openApi/v2/parser/getOperationResponseHeader.ts index 79659ae2..09a81091 100644 --- a/src/openApi/v2/parser/getOperationResponseHeader.ts +++ b/src/openApi/v2/parser/getOperationResponseHeader.ts @@ -1,6 +1,6 @@ import type { OperationResponse } from '../../../client/interfaces/OperationResponse'; -export function getOperationResponseHeader(operationResponses: OperationResponse[]): string | null { +export const getOperationResponseHeader = (operationResponses: OperationResponse[]): string | null => { const header = operationResponses.find(operationResponses => { return operationResponses.in === 'header'; }); @@ -8,4 +8,4 @@ export function getOperationResponseHeader(operationResponses: OperationResponse return header.name; } return null; -} +}; diff --git a/src/openApi/v2/parser/getOperationResponses.ts b/src/openApi/v2/parser/getOperationResponses.ts index 2ed23f14..ed628e85 100644 --- a/src/openApi/v2/parser/getOperationResponses.ts +++ b/src/openApi/v2/parser/getOperationResponses.ts @@ -6,7 +6,7 @@ import { getOperationResponse } from './getOperationResponse'; import { getOperationResponseCode } from './getOperationResponseCode'; import { getRef } from './getRef'; -export function getOperationResponses(openApi: OpenApi, responses: OpenApiResponses): OperationResponse[] { +export const getOperationResponses = (openApi: OpenApi, responses: OpenApiResponses): OperationResponse[] => { const operationResponses: OperationResponse[] = []; // Iterate over each response code and get the @@ -28,4 +28,4 @@ export function getOperationResponses(openApi: OpenApi, responses: OpenApiRespon return operationResponses.sort((a, b): number => { return a.code < b.code ? -1 : a.code > b.code ? 1 : 0; }); -} +}; diff --git a/src/openApi/v2/parser/getOperationResults.ts b/src/openApi/v2/parser/getOperationResults.ts index 5d4ad2d0..9d8111fe 100644 --- a/src/openApi/v2/parser/getOperationResults.ts +++ b/src/openApi/v2/parser/getOperationResults.ts @@ -1,15 +1,15 @@ import type { Model } from '../../../client/interfaces/Model'; import type { OperationResponse } from '../../../client/interfaces/OperationResponse'; -function areEqual(a: Model, b: Model): boolean { +const areEqual = (a: Model, b: Model): boolean => { const equal = a.type === b.type && a.base === b.base && a.template === b.template; if (equal && a.link && b.link) { return areEqual(a.link, b.link); } return equal; -} +}; -export function getOperationResults(operationResponses: OperationResponse[]): OperationResponse[] { +export const getOperationResults = (operationResponses: OperationResponse[]): OperationResponse[] => { const operationResults: OperationResponse[] = []; // Filter out success response codes, but skip "204 No Content" @@ -49,4 +49,4 @@ export function getOperationResults(operationResponses: OperationResponse[]): Op }) === index ); }); -} +}; diff --git a/src/openApi/v2/parser/getRef.ts b/src/openApi/v2/parser/getRef.ts index 6e67d208..f92dfcf6 100644 --- a/src/openApi/v2/parser/getRef.ts +++ b/src/openApi/v2/parser/getRef.ts @@ -4,7 +4,7 @@ import type { OpenApiReference } from '../interfaces/OpenApiReference'; const ESCAPED_REF_SLASH = /~1/g; const ESCAPED_REF_TILDE = /~0/g; -export function getRef(openApi: OpenApi, item: T & OpenApiReference): T { +export const getRef = (openApi: OpenApi, item: T & OpenApiReference): T => { if (item.$ref) { // Fetch the paths to the definitions, this converts: // "#/definitions/Form" to ["definitions", "Form"] @@ -29,4 +29,4 @@ export function getRef(openApi: OpenApi, item: T & OpenApiReference): T { return result as T; } return item as T; -} +}; diff --git a/src/openApi/v2/parser/getRequiredPropertiesFromComposition.ts b/src/openApi/v2/parser/getRequiredPropertiesFromComposition.ts index 0794d616..0b1f1859 100644 --- a/src/openApi/v2/parser/getRequiredPropertiesFromComposition.ts +++ b/src/openApi/v2/parser/getRequiredPropertiesFromComposition.ts @@ -7,12 +7,12 @@ import { getRef } from './getRef'; // Fix for circular dependency export type GetModelFn = typeof getModel; -export function getRequiredPropertiesFromComposition( +export const getRequiredPropertiesFromComposition = ( openApi: OpenApi, required: string[], definitions: OpenApiSchema[], getModel: GetModelFn -): Model[] { +): Model[] => { return definitions .reduce((properties, definition) => { if (definition.$ref) { @@ -30,4 +30,4 @@ export function getRequiredPropertiesFromComposition( isRequired: true, }; }); -} +}; diff --git a/src/openApi/v2/parser/getServer.ts b/src/openApi/v2/parser/getServer.ts index 642fe34d..0b191388 100644 --- a/src/openApi/v2/parser/getServer.ts +++ b/src/openApi/v2/parser/getServer.ts @@ -4,10 +4,10 @@ import type { OpenApi } from '../interfaces/OpenApi'; * Get the base server url. * @param openApi */ -export function getServer(openApi: OpenApi): string { +export const getServer = (openApi: OpenApi): string => { const scheme = openApi.schemes?.[0] || 'http'; const host = openApi.host; const basePath = openApi.basePath || ''; const url = host ? `${scheme}://${host}${basePath}` : basePath; return url.replace(/\/$/g, ''); -} +}; diff --git a/src/openApi/v2/parser/getServiceName.ts b/src/openApi/v2/parser/getServiceName.ts index 14a003b1..b5b1718f 100644 --- a/src/openApi/v2/parser/getServiceName.ts +++ b/src/openApi/v2/parser/getServiceName.ts @@ -4,10 +4,10 @@ import camelCase from 'camelcase'; * Convert the input value to a correct service name. This converts * the input string to PascalCase. */ -export function getServiceName(value: string): string { +export const getServiceName = (value: string): string => { const clean = value .replace(/^[^a-zA-Z]+/g, '') .replace(/[^\w\-]+/g, '-') .trim(); return camelCase(clean, { pascalCase: true }); -} +}; diff --git a/src/openApi/v2/parser/getServiceVersion.ts b/src/openApi/v2/parser/getServiceVersion.ts index 7d860d6d..9c7a8a04 100644 --- a/src/openApi/v2/parser/getServiceVersion.ts +++ b/src/openApi/v2/parser/getServiceVersion.ts @@ -3,6 +3,6 @@ * This basically removes any "v" prefix from the version string. * @param version */ -export function getServiceVersion(version = '1.0'): string { +export const getServiceVersion = (version = '1.0'): string => { return String(version).replace(/^v/gi, ''); -} +}; diff --git a/src/openApi/v2/parser/getServices.ts b/src/openApi/v2/parser/getServices.ts index e52f8496..d8fe411b 100644 --- a/src/openApi/v2/parser/getServices.ts +++ b/src/openApi/v2/parser/getServices.ts @@ -7,7 +7,7 @@ import { getOperationParameters } from './getOperationParameters'; /** * Get the OpenAPI services */ -export function getServices(openApi: OpenApi): Service[] { +export const getServices = (openApi: OpenApi): Service[] => { const services = new Map(); for (const url in openApi.paths) { if (openApi.paths.hasOwnProperty(url)) { @@ -28,7 +28,7 @@ export function getServices(openApi: OpenApi): Service[] { case 'patch': // Each method contains an OpenAPI operation, we parse the operation const op = path[method]!; - const tags = op.tags?.length ? op.tags.filter(unique) : ['']; + const tags = op.tags?.length ? op.tags.filter(unique) : ['Default']; tags.forEach(tag => { const operation = getOperation(openApi, url, method, tag, op, pathParams); @@ -52,4 +52,4 @@ export function getServices(openApi: OpenApi): Service[] { } } return Array.from(services.values()); -} +}; diff --git a/src/openApi/v2/parser/getType.ts b/src/openApi/v2/parser/getType.ts index 49905623..6caa1e01 100644 --- a/src/openApi/v2/parser/getType.ts +++ b/src/openApi/v2/parser/getType.ts @@ -2,16 +2,16 @@ import type { Type } from '../../../client/interfaces/Type'; import { getMappedType } from './getMappedType'; import { stripNamespace } from './stripNamespace'; -function encode(value: string): string { +const encode = (value: string): string => { return value.replace(/^[^a-zA-Z_$]+/g, '').replace(/[^\w$]+/g, '_'); -} +}; /** * Parse any string value into a type object. * @param type String value like "integer" or "Link[Model]". * @param format String value like "binary" or "date". */ -export function getType(type: string = 'any', format?: string): Type { +export const getType = (type: string = 'any', format?: string): Type => { const result: Type = { type: 'any', base: 'any', @@ -64,4 +64,4 @@ export function getType(type: string = 'any', format?: string): Type { } return result; -} +}; diff --git a/src/openApi/v2/parser/sortByRequired.ts b/src/openApi/v2/parser/sortByRequired.ts index d9533264..6519bb17 100644 --- a/src/openApi/v2/parser/sortByRequired.ts +++ b/src/openApi/v2/parser/sortByRequired.ts @@ -1,9 +1,9 @@ import type { OperationParameter } from '../../../client/interfaces/OperationParameter'; -export function sortByRequired(a: OperationParameter, b: OperationParameter): number { +export const sortByRequired = (a: OperationParameter, b: OperationParameter): number => { const aNeedsValue = a.isRequired && a.default === undefined; const bNeedsValue = b.isRequired && b.default === undefined; if (aNeedsValue && !bNeedsValue) return -1; if (bNeedsValue && !aNeedsValue) return 1; return 0; -} +}; diff --git a/src/openApi/v2/parser/stripNamespace.ts b/src/openApi/v2/parser/stripNamespace.ts index fa124be9..ff543b3c 100644 --- a/src/openApi/v2/parser/stripNamespace.ts +++ b/src/openApi/v2/parser/stripNamespace.ts @@ -2,11 +2,11 @@ * Strip (OpenAPI) namespaces fom values. * @param value */ -export function stripNamespace(value: string): string { +export const stripNamespace = (value: string): string => { return value .trim() .replace(/^#\/definitions\//, '') .replace(/^#\/parameters\//, '') .replace(/^#\/responses\//, '') .replace(/^#\/securityDefinitions\//, ''); -} +}; diff --git a/src/openApi/v3/index.ts b/src/openApi/v3/index.ts index 30bd05cc..9dbdadb3 100644 --- a/src/openApi/v3/index.ts +++ b/src/openApi/v3/index.ts @@ -10,11 +10,11 @@ import { getServiceVersion } from './parser/getServiceVersion'; * all the models, services and schema's we should output. * @param openApi The OpenAPI spec that we have loaded from disk. */ -export function parse(openApi: OpenApi): Client { +export const parse = (openApi: OpenApi): Client => { const version = getServiceVersion(openApi.info.version); const server = getServer(openApi); const models = getModels(openApi); const services = getServices(openApi); return { version, server, models, services }; -} +}; diff --git a/src/openApi/v3/parser/escapeName.ts b/src/openApi/v3/parser/escapeName.ts index 0a26cb65..6b23d934 100644 --- a/src/openApi/v3/parser/escapeName.ts +++ b/src/openApi/v3/parser/escapeName.ts @@ -1,4 +1,4 @@ -export function escapeName(value: string): string { +export const escapeName = (value: string): string => { if (value) { const validName = /^[a-zA-Z_$][\w$]+$/g.test(value); if (!validName) { @@ -6,4 +6,4 @@ export function escapeName(value: string): string { } } return value; -} +}; diff --git a/src/openApi/v3/parser/extendEnum.ts b/src/openApi/v3/parser/extendEnum.ts index 81e85fdf..0a5ebeb1 100644 --- a/src/openApi/v3/parser/extendEnum.ts +++ b/src/openApi/v3/parser/extendEnum.ts @@ -7,7 +7,7 @@ import type { WithEnumExtension } from '../interfaces/Extensions/WithEnumExtensi * @param enumerators * @param definition */ -export function extendEnum(enumerators: Enum[], definition: WithEnumExtension): Enum[] { +export const extendEnum = (enumerators: Enum[], definition: WithEnumExtension): Enum[] => { const names = definition['x-enum-varnames']; const descriptions = definition['x-enum-descriptions']; @@ -17,4 +17,4 @@ export function extendEnum(enumerators: Enum[], definition: WithEnumExtension): value: enumerator.value, type: enumerator.type, })); -} +}; diff --git a/src/openApi/v3/parser/getContent.ts b/src/openApi/v3/parser/getContent.ts index 84f5cc11..97662581 100644 --- a/src/openApi/v3/parser/getContent.ts +++ b/src/openApi/v3/parser/getContent.ts @@ -21,7 +21,7 @@ const BASIC_MEDIA_TYPES = [ 'multipart/batch', ]; -export function getContent(openApi: OpenApi, content: Dictionary): Content | null { +export const getContent = (openApi: OpenApi, content: Dictionary): Content | null => { const basicMediaTypeWithSchema = Object.keys(content) .filter(mediaType => { const cleanMediaType = mediaType.split(';')[0].trim(); @@ -43,4 +43,4 @@ export function getContent(openApi: OpenApi, content: Dictionary { if (Array.isArray(values)) { return values .filter((value, index, arr) => { @@ -30,4 +30,4 @@ export function getEnum(values?: (string | number)[]): Enum[] { }); } return []; -} +}; diff --git a/src/openApi/v3/parser/getEnumFromDescription.ts b/src/openApi/v3/parser/getEnumFromDescription.ts index d1154e6e..0f49cf40 100644 --- a/src/openApi/v3/parser/getEnumFromDescription.ts +++ b/src/openApi/v3/parser/getEnumFromDescription.ts @@ -3,7 +3,7 @@ import type { Enum } from '../../../client/interfaces/Enum'; /** * @deprecated */ -export function getEnumFromDescription(description: string): Enum[] { +export const getEnumFromDescription = (description: string): Enum[] => { // Check if we can find this special format string: // None=0,Something=1,AnotherThing=2 if (/^(\w+=[0-9]+)/g.test(description)) { @@ -36,4 +36,4 @@ export function getEnumFromDescription(description: string): Enum[] { } return []; -} +}; diff --git a/src/openApi/v3/parser/getMappedType.ts b/src/openApi/v3/parser/getMappedType.ts index e44434e2..a7c32fd8 100644 --- a/src/openApi/v3/parser/getMappedType.ts +++ b/src/openApi/v3/parser/getMappedType.ts @@ -24,9 +24,9 @@ const TYPE_MAPPINGS = new Map([ /** * Get mapped type for given type to any basic Typescript/Javascript type. */ -export function getMappedType(type: string, format?: string): string | undefined { +export const getMappedType = (type: string, format?: string): string | undefined => { if (format === 'binary') { return 'binary'; } return TYPE_MAPPINGS.get(type); -} +}; diff --git a/src/openApi/v3/parser/getModel.ts b/src/openApi/v3/parser/getModel.ts index a44ebb0d..4b006830 100644 --- a/src/openApi/v3/parser/getModel.ts +++ b/src/openApi/v3/parser/getModel.ts @@ -10,12 +10,12 @@ import { getModelDefault } from './getModelDefault'; import { getModelProperties } from './getModelProperties'; import { getType } from './getType'; -export function getModel( +export const getModel = ( openApi: OpenApi, definition: OpenApiSchema, isDefinition: boolean = false, name: string = '' -): Model { +): Model => { const model: Model = { name, export: 'interface', @@ -191,4 +191,4 @@ export function getModel( } return model; -} +}; diff --git a/src/openApi/v3/parser/getModelComposition.ts b/src/openApi/v3/parser/getModelComposition.ts index 468dbe26..6b5e4c30 100644 --- a/src/openApi/v3/parser/getModelComposition.ts +++ b/src/openApi/v3/parser/getModelComposition.ts @@ -9,13 +9,13 @@ import { getRequiredPropertiesFromComposition } from './getRequiredPropertiesFro // Fix for circular dependency export type GetModelFn = typeof getModel; -export function getModelComposition( +export const getModelComposition = ( openApi: OpenApi, definition: OpenApiSchema, definitions: OpenApiSchema[], type: 'one-of' | 'any-of' | 'all-of', getModel: GetModelFn -): ModelComposition { +): ModelComposition => { const composition: ModelComposition = { type, imports: [], @@ -87,4 +87,4 @@ export function getModelComposition( } return composition; -} +}; diff --git a/src/openApi/v3/parser/getModelDefault.ts b/src/openApi/v3/parser/getModelDefault.ts index e56594e6..3182d7ac 100644 --- a/src/openApi/v3/parser/getModelDefault.ts +++ b/src/openApi/v3/parser/getModelDefault.ts @@ -1,7 +1,7 @@ import type { Model } from '../../../client/interfaces/Model'; import type { OpenApiSchema } from '../interfaces/OpenApiSchema'; -export function getModelDefault(definition: OpenApiSchema, model?: Model): string | undefined { +export const getModelDefault = (definition: OpenApiSchema, model?: Model): string | undefined => { if (definition.default === undefined) { return; } @@ -36,4 +36,4 @@ export function getModelDefault(definition: OpenApiSchema, model?: Model): strin } return; -} +}; diff --git a/src/openApi/v3/parser/getModelProperties.ts b/src/openApi/v3/parser/getModelProperties.ts index 9c9833da..1c2cbff0 100644 --- a/src/openApi/v3/parser/getModelProperties.ts +++ b/src/openApi/v3/parser/getModelProperties.ts @@ -10,12 +10,12 @@ import { getType } from './getType'; // Fix for circular dependency export type GetModelFn = typeof getModel; -export function getModelProperties( +export const getModelProperties = ( openApi: OpenApi, definition: OpenApiSchema, getModel: GetModelFn, parent?: Model -): Model[] { +): Model[] => { const models: Model[] = []; const discriminator = findOneOfParentDiscriminator(openApi, parent); for (const propertyName in definition.properties) { @@ -104,4 +104,4 @@ export function getModelProperties( } return models; -} +}; diff --git a/src/openApi/v3/parser/getModelTemplate.ts b/src/openApi/v3/parser/getModelTemplate.ts index 26902ea0..b2aa0b33 100644 --- a/src/openApi/v3/parser/getModelTemplate.ts +++ b/src/openApi/v3/parser/getModelTemplate.ts @@ -6,6 +6,6 @@ import type { Type } from '../../../client/interfaces/Type'; * @param modelClass The parsed model class type. * @returns The model template type ( or empty). */ -export function getModelTemplate(modelClass: Type): string { +export const getModelTemplate = (modelClass: Type): string => { return modelClass.template ? '' : ''; -} +}; diff --git a/src/openApi/v3/parser/getModels.ts b/src/openApi/v3/parser/getModels.ts index 6294597d..3ca6393e 100644 --- a/src/openApi/v3/parser/getModels.ts +++ b/src/openApi/v3/parser/getModels.ts @@ -3,7 +3,7 @@ import type { OpenApi } from '../interfaces/OpenApi'; import { getModel } from './getModel'; import { getType } from './getType'; -export function getModels(openApi: OpenApi): Model[] { +export const getModels = (openApi: OpenApi): Model[] => { const models: Model[] = []; if (openApi.components) { for (const definitionName in openApi.components.schemas) { @@ -16,4 +16,4 @@ export function getModels(openApi: OpenApi): Model[] { } } return models; -} +}; diff --git a/src/openApi/v3/parser/getOperation.ts b/src/openApi/v3/parser/getOperation.ts index de452712..027d9f13 100644 --- a/src/openApi/v3/parser/getOperation.ts +++ b/src/openApi/v3/parser/getOperation.ts @@ -15,17 +15,16 @@ import { getRef } from './getRef'; import { getServiceName } from './getServiceName'; import { sortByRequired } from './sortByRequired'; -export function getOperation( +export const getOperation = ( openApi: OpenApi, url: string, method: string, tag: string, op: OpenApiOperation, pathParams: OperationParameters -): Operation { +): Operation => { const serviceName = getServiceName(tag); - const operationNameFallback = `${method}${serviceName}`; - const operationName = getOperationName(op.operationId || operationNameFallback); + const operationName = getOperationName(op.operationId || `${method}`); const operationPath = getOperationPath(url); // Create a new operation object for this method. @@ -87,4 +86,4 @@ export function getOperation( operation.parameters = operation.parameters.sort(sortByRequired); return operation; -} +}; diff --git a/src/openApi/v3/parser/getOperationErrors.ts b/src/openApi/v3/parser/getOperationErrors.ts index 9703f91b..e7624adb 100644 --- a/src/openApi/v3/parser/getOperationErrors.ts +++ b/src/openApi/v3/parser/getOperationErrors.ts @@ -1,7 +1,7 @@ import type { OperationError } from '../../../client/interfaces/OperationError'; import type { OperationResponse } from '../../../client/interfaces/OperationResponse'; -export function getOperationErrors(operationResponses: OperationResponse[]): OperationError[] { +export const getOperationErrors = (operationResponses: OperationResponse[]): OperationError[] => { return operationResponses .filter(operationResponse => { return operationResponse.code >= 300 && operationResponse.description; @@ -10,4 +10,4 @@ export function getOperationErrors(operationResponses: OperationResponse[]): Ope code: response.code, description: response.description!, })); -} +}; diff --git a/src/openApi/v3/parser/getOperationName.ts b/src/openApi/v3/parser/getOperationName.ts index 9a993d8d..663a758d 100644 --- a/src/openApi/v3/parser/getOperationName.ts +++ b/src/openApi/v3/parser/getOperationName.ts @@ -5,10 +5,10 @@ import camelCase from 'camelcase'; * This converts the input string to camelCase, so the method name follows * the most popular Javascript and Typescript writing style. */ -export function getOperationName(value: string): string { +export const getOperationName = (value: string): string => { const clean = value .replace(/^[^a-zA-Z]+/g, '') .replace(/[^\w\-]+/g, '-') .trim(); return camelCase(clean); -} +}; diff --git a/src/openApi/v3/parser/getOperationParameter.ts b/src/openApi/v3/parser/getOperationParameter.ts index 89ef5f35..90b8a8e7 100644 --- a/src/openApi/v3/parser/getOperationParameter.ts +++ b/src/openApi/v3/parser/getOperationParameter.ts @@ -9,7 +9,7 @@ import { getOperationParameterName } from './getOperationParameterName'; import { getRef } from './getRef'; import { getType } from './getType'; -export function getOperationParameter(openApi: OpenApi, parameter: OpenApiParameter): OperationParameter { +export const getOperationParameter = (openApi: OpenApi, parameter: OpenApiParameter): OperationParameter => { const operationParameter: OperationParameter = { in: parameter.in, prop: parameter.name, @@ -89,4 +89,4 @@ export function getOperationParameter(openApi: OpenApi, parameter: OpenApiParame } return operationParameter; -} +}; diff --git a/src/openApi/v3/parser/getOperationParameterName.ts b/src/openApi/v3/parser/getOperationParameterName.ts index 0954d736..de9b154b 100644 --- a/src/openApi/v3/parser/getOperationParameterName.ts +++ b/src/openApi/v3/parser/getOperationParameterName.ts @@ -7,10 +7,10 @@ const reservedWords = * Replaces any invalid characters from a parameter name. * For example: 'filter.someProperty' becomes 'filterSomeProperty'. */ -export function getOperationParameterName(value: string): string { +export const getOperationParameterName = (value: string): string => { const clean = value .replace(/^[^a-zA-Z]+/g, '') .replace(/[^\w\-]+/g, '-') .trim(); return camelCase(clean).replace(reservedWords, '_$1'); -} +}; diff --git a/src/openApi/v3/parser/getOperationParameters.ts b/src/openApi/v3/parser/getOperationParameters.ts index f4cc7503..051b4a0a 100644 --- a/src/openApi/v3/parser/getOperationParameters.ts +++ b/src/openApi/v3/parser/getOperationParameters.ts @@ -4,7 +4,7 @@ import type { OpenApiParameter } from '../interfaces/OpenApiParameter'; import { getOperationParameter } from './getOperationParameter'; import { getRef } from './getRef'; -export function getOperationParameters(openApi: OpenApi, parameters: OpenApiParameter[]): OperationParameters { +export const getOperationParameters = (openApi: OpenApi, parameters: OpenApiParameter[]): OperationParameters => { const operationParameters: OperationParameters = { imports: [], parameters: [], @@ -58,4 +58,4 @@ export function getOperationParameters(openApi: OpenApi, parameters: OpenApiPara } }); return operationParameters; -} +}; diff --git a/src/openApi/v3/parser/getOperationPath.ts b/src/openApi/v3/parser/getOperationPath.ts index 7d2a07cf..17594a2c 100644 --- a/src/openApi/v3/parser/getOperationPath.ts +++ b/src/openApi/v3/parser/getOperationPath.ts @@ -7,10 +7,10 @@ import { getOperationParameterName } from './getOperationParameterName'; * Plus we return the correct parameter names to replace in the URL. * @param path */ -export function getOperationPath(path: string): string { +export const getOperationPath = (path: string): string => { return path .replace(/\{(.*?)\}/g, (_, w: string) => { return `\${${getOperationParameterName(w)}}`; }) .replace('${apiVersion}', '${OpenAPI.VERSION}'); -} +}; diff --git a/src/openApi/v3/parser/getOperationRequestBody.ts b/src/openApi/v3/parser/getOperationRequestBody.ts index be0b8eeb..9f9cca24 100644 --- a/src/openApi/v3/parser/getOperationRequestBody.ts +++ b/src/openApi/v3/parser/getOperationRequestBody.ts @@ -6,7 +6,7 @@ import { getContent } from './getContent'; import { getModel } from './getModel'; import { getType } from './getType'; -export function getOperationRequestBody(openApi: OpenApi, body: OpenApiRequestBody): OperationParameter { +export const getOperationRequestBody = (openApi: OpenApi, body: OpenApiRequestBody): OperationParameter => { const requestBody: OperationParameter = { in: 'body', export: 'interface', @@ -83,4 +83,4 @@ export function getOperationRequestBody(openApi: OpenApi, body: OpenApiRequestBo } return requestBody; -} +}; diff --git a/src/openApi/v3/parser/getOperationResponse.ts b/src/openApi/v3/parser/getOperationResponse.ts index 8b91980e..dff19ec1 100644 --- a/src/openApi/v3/parser/getOperationResponse.ts +++ b/src/openApi/v3/parser/getOperationResponse.ts @@ -8,11 +8,11 @@ import { getModel } from './getModel'; import { getRef } from './getRef'; import { getType } from './getType'; -export function getOperationResponse( +export const getOperationResponse = ( openApi: OpenApi, response: OpenApiResponse, responseCode: number -): OperationResponse { +): OperationResponse => { const operationResponse: OperationResponse = { in: 'response', name: '', @@ -95,4 +95,4 @@ export function getOperationResponse( } return operationResponse; -} +}; diff --git a/src/openApi/v3/parser/getOperationResponseCode.ts b/src/openApi/v3/parser/getOperationResponseCode.ts index c5609938..f34c99b7 100644 --- a/src/openApi/v3/parser/getOperationResponseCode.ts +++ b/src/openApi/v3/parser/getOperationResponseCode.ts @@ -1,4 +1,4 @@ -export function getOperationResponseCode(value: string | 'default'): number | null { +export const getOperationResponseCode = (value: string | 'default'): number | null => { // You can specify a "default" response, this is treated as HTTP code 200 if (value === 'default') { return 200; @@ -13,4 +13,4 @@ export function getOperationResponseCode(value: string | 'default'): number | nu } return null; -} +}; diff --git a/src/openApi/v3/parser/getOperationResponseHeader.ts b/src/openApi/v3/parser/getOperationResponseHeader.ts index 79659ae2..09a81091 100644 --- a/src/openApi/v3/parser/getOperationResponseHeader.ts +++ b/src/openApi/v3/parser/getOperationResponseHeader.ts @@ -1,6 +1,6 @@ import type { OperationResponse } from '../../../client/interfaces/OperationResponse'; -export function getOperationResponseHeader(operationResponses: OperationResponse[]): string | null { +export const getOperationResponseHeader = (operationResponses: OperationResponse[]): string | null => { const header = operationResponses.find(operationResponses => { return operationResponses.in === 'header'; }); @@ -8,4 +8,4 @@ export function getOperationResponseHeader(operationResponses: OperationResponse return header.name; } return null; -} +}; diff --git a/src/openApi/v3/parser/getOperationResponses.ts b/src/openApi/v3/parser/getOperationResponses.ts index 2ed23f14..ed628e85 100644 --- a/src/openApi/v3/parser/getOperationResponses.ts +++ b/src/openApi/v3/parser/getOperationResponses.ts @@ -6,7 +6,7 @@ import { getOperationResponse } from './getOperationResponse'; import { getOperationResponseCode } from './getOperationResponseCode'; import { getRef } from './getRef'; -export function getOperationResponses(openApi: OpenApi, responses: OpenApiResponses): OperationResponse[] { +export const getOperationResponses = (openApi: OpenApi, responses: OpenApiResponses): OperationResponse[] => { const operationResponses: OperationResponse[] = []; // Iterate over each response code and get the @@ -28,4 +28,4 @@ export function getOperationResponses(openApi: OpenApi, responses: OpenApiRespon return operationResponses.sort((a, b): number => { return a.code < b.code ? -1 : a.code > b.code ? 1 : 0; }); -} +}; diff --git a/src/openApi/v3/parser/getOperationResults.ts b/src/openApi/v3/parser/getOperationResults.ts index 5d4ad2d0..9d8111fe 100644 --- a/src/openApi/v3/parser/getOperationResults.ts +++ b/src/openApi/v3/parser/getOperationResults.ts @@ -1,15 +1,15 @@ import type { Model } from '../../../client/interfaces/Model'; import type { OperationResponse } from '../../../client/interfaces/OperationResponse'; -function areEqual(a: Model, b: Model): boolean { +const areEqual = (a: Model, b: Model): boolean => { const equal = a.type === b.type && a.base === b.base && a.template === b.template; if (equal && a.link && b.link) { return areEqual(a.link, b.link); } return equal; -} +}; -export function getOperationResults(operationResponses: OperationResponse[]): OperationResponse[] { +export const getOperationResults = (operationResponses: OperationResponse[]): OperationResponse[] => { const operationResults: OperationResponse[] = []; // Filter out success response codes, but skip "204 No Content" @@ -49,4 +49,4 @@ export function getOperationResults(operationResponses: OperationResponse[]): Op }) === index ); }); -} +}; diff --git a/src/openApi/v3/parser/getRef.ts b/src/openApi/v3/parser/getRef.ts index d3737311..2c42690e 100644 --- a/src/openApi/v3/parser/getRef.ts +++ b/src/openApi/v3/parser/getRef.ts @@ -4,7 +4,7 @@ import type { OpenApiReference } from '../interfaces/OpenApiReference'; const ESCAPED_REF_SLASH = /~1/g; const ESCAPED_REF_TILDE = /~0/g; -export function getRef(openApi: OpenApi, item: T & OpenApiReference): T { +export const getRef = (openApi: OpenApi, item: T & OpenApiReference): T => { if (item.$ref) { // Fetch the paths to the definitions, this converts: // "#/components/schemas/Form" to ["components", "schemas", "Form"] @@ -29,4 +29,4 @@ export function getRef(openApi: OpenApi, item: T & OpenApiReference): T { return result as T; } return item as T; -} +}; diff --git a/src/openApi/v3/parser/getRequiredPropertiesFromComposition.ts b/src/openApi/v3/parser/getRequiredPropertiesFromComposition.ts index 0794d616..0b1f1859 100644 --- a/src/openApi/v3/parser/getRequiredPropertiesFromComposition.ts +++ b/src/openApi/v3/parser/getRequiredPropertiesFromComposition.ts @@ -7,12 +7,12 @@ import { getRef } from './getRef'; // Fix for circular dependency export type GetModelFn = typeof getModel; -export function getRequiredPropertiesFromComposition( +export const getRequiredPropertiesFromComposition = ( openApi: OpenApi, required: string[], definitions: OpenApiSchema[], getModel: GetModelFn -): Model[] { +): Model[] => { return definitions .reduce((properties, definition) => { if (definition.$ref) { @@ -30,4 +30,4 @@ export function getRequiredPropertiesFromComposition( isRequired: true, }; }); -} +}; diff --git a/src/openApi/v3/parser/getServer.ts b/src/openApi/v3/parser/getServer.ts index 57d5447b..dd60b1cf 100644 --- a/src/openApi/v3/parser/getServer.ts +++ b/src/openApi/v3/parser/getServer.ts @@ -1,6 +1,6 @@ import type { OpenApi } from '../interfaces/OpenApi'; -export function getServer(openApi: OpenApi): string { +export const getServer = (openApi: OpenApi): string => { const server = openApi.servers?.[0]; const variables = server?.variables || {}; let url = server?.url || ''; @@ -10,4 +10,4 @@ export function getServer(openApi: OpenApi): string { } } return url.replace(/\/$/g, ''); -} +}; diff --git a/src/openApi/v3/parser/getServiceName.ts b/src/openApi/v3/parser/getServiceName.ts index 14a003b1..b5b1718f 100644 --- a/src/openApi/v3/parser/getServiceName.ts +++ b/src/openApi/v3/parser/getServiceName.ts @@ -4,10 +4,10 @@ import camelCase from 'camelcase'; * Convert the input value to a correct service name. This converts * the input string to PascalCase. */ -export function getServiceName(value: string): string { +export const getServiceName = (value: string): string => { const clean = value .replace(/^[^a-zA-Z]+/g, '') .replace(/[^\w\-]+/g, '-') .trim(); return camelCase(clean, { pascalCase: true }); -} +}; diff --git a/src/openApi/v3/parser/getServiceVersion.ts b/src/openApi/v3/parser/getServiceVersion.ts index 7d860d6d..9c7a8a04 100644 --- a/src/openApi/v3/parser/getServiceVersion.ts +++ b/src/openApi/v3/parser/getServiceVersion.ts @@ -3,6 +3,6 @@ * This basically removes any "v" prefix from the version string. * @param version */ -export function getServiceVersion(version = '1.0'): string { +export const getServiceVersion = (version = '1.0'): string => { return String(version).replace(/^v/gi, ''); -} +}; diff --git a/src/openApi/v3/parser/getServices.ts b/src/openApi/v3/parser/getServices.ts index e52f8496..d8fe411b 100644 --- a/src/openApi/v3/parser/getServices.ts +++ b/src/openApi/v3/parser/getServices.ts @@ -7,7 +7,7 @@ import { getOperationParameters } from './getOperationParameters'; /** * Get the OpenAPI services */ -export function getServices(openApi: OpenApi): Service[] { +export const getServices = (openApi: OpenApi): Service[] => { const services = new Map(); for (const url in openApi.paths) { if (openApi.paths.hasOwnProperty(url)) { @@ -28,7 +28,7 @@ export function getServices(openApi: OpenApi): Service[] { case 'patch': // Each method contains an OpenAPI operation, we parse the operation const op = path[method]!; - const tags = op.tags?.length ? op.tags.filter(unique) : ['']; + const tags = op.tags?.length ? op.tags.filter(unique) : ['Default']; tags.forEach(tag => { const operation = getOperation(openApi, url, method, tag, op, pathParams); @@ -52,4 +52,4 @@ export function getServices(openApi: OpenApi): Service[] { } } return Array.from(services.values()); -} +}; diff --git a/src/openApi/v3/parser/getType.ts b/src/openApi/v3/parser/getType.ts index d62453db..e8ef4733 100644 --- a/src/openApi/v3/parser/getType.ts +++ b/src/openApi/v3/parser/getType.ts @@ -3,16 +3,16 @@ import { isDefined } from '../../../utils/isDefined'; import { getMappedType } from './getMappedType'; import { stripNamespace } from './stripNamespace'; -function encode(value: string): string { +const encode = (value: string): string => { return value.replace(/^[^a-zA-Z_$]+/g, '').replace(/[^\w$]+/g, '_'); -} +}; /** * Parse any string value into a type object. * @param type String or String[] value like "integer", "Link[Model]" or ["string", "null"]. * @param format String value like "binary" or "date". */ -export function getType(type: string | string[] = 'any', format?: string): Type { +export const getType = (type: string | string[] = 'any', format?: string): Type => { const result: Type = { type: 'any', base: 'any', @@ -79,4 +79,4 @@ export function getType(type: string | string[] = 'any', format?: string): Type } return result; -} +}; diff --git a/src/openApi/v3/parser/sortByRequired.ts b/src/openApi/v3/parser/sortByRequired.ts index d9533264..6519bb17 100644 --- a/src/openApi/v3/parser/sortByRequired.ts +++ b/src/openApi/v3/parser/sortByRequired.ts @@ -1,9 +1,9 @@ import type { OperationParameter } from '../../../client/interfaces/OperationParameter'; -export function sortByRequired(a: OperationParameter, b: OperationParameter): number { +export const sortByRequired = (a: OperationParameter, b: OperationParameter): number => { const aNeedsValue = a.isRequired && a.default === undefined; const bNeedsValue = b.isRequired && b.default === undefined; if (aNeedsValue && !bNeedsValue) return -1; if (bNeedsValue && !aNeedsValue) return 1; return 0; -} +}; diff --git a/src/openApi/v3/parser/stripNamespace.ts b/src/openApi/v3/parser/stripNamespace.ts index 6ff55b7a..76b9d02d 100644 --- a/src/openApi/v3/parser/stripNamespace.ts +++ b/src/openApi/v3/parser/stripNamespace.ts @@ -2,7 +2,7 @@ * Strip (OpenAPI) namespaces fom values. * @param value */ -export function stripNamespace(value: string): string { +export const stripNamespace = (value: string): string => { return value .trim() .replace(/^#\/components\/schemas\//, '') @@ -14,4 +14,4 @@ export function stripNamespace(value: string): string { .replace(/^#\/components\/securitySchemes\//, '') .replace(/^#\/components\/links\//, '') .replace(/^#\/components\/callbacks\//, ''); -} +}; diff --git a/src/templates/__mocks__/index.ts b/src/templates/__mocks__/index.ts index ba8c8cdb..7f78e06f 100644 --- a/src/templates/__mocks__/index.ts +++ b/src/templates/__mocks__/index.ts @@ -1,7 +1,7 @@ export default { compiler: [8, '>= 4.3.0'], useData: true, - main: function () { + main: () => { return ''; }, }; diff --git a/src/templates/client.hbs b/src/templates/client.hbs index aea06c0e..33cc0f1d 100644 --- a/src/templates/client.hbs +++ b/src/templates/client.hbs @@ -14,7 +14,7 @@ type HttpRequestConstructor = new (config: OpenAPIConfig) => BaseHttpRequest; export class {{{clientName}}} { {{#each services}} - public readonly {{{name}}}: {{{name}}}{{{@root.postfix}}}; + public readonly {{{camelCase name}}}: {{{name}}}{{{@root.postfix}}}; {{/each}} public readonly request: BaseHttpRequest; @@ -33,7 +33,7 @@ export class {{{clientName}}} { }); {{#each services}} - this.{{{name}}} = new {{{name}}}{{{@root.postfix}}}(this.request); + this.{{{camelCase name}}} = new {{{name}}}{{{@root.postfix}}}(this.request); {{/each}} } } diff --git a/src/utils/discriminator.ts b/src/utils/discriminator.ts index 1bbffa3e..3b45c4eb 100644 --- a/src/utils/discriminator.ts +++ b/src/utils/discriminator.ts @@ -4,15 +4,15 @@ import type { OpenApiDiscriminator } from '../openApi/v3/interfaces/OpenApiDiscr import { stripNamespace } from '../openApi/v3/parser/stripNamespace'; import type { Dictionary } from './types'; -function inverseDictionary(map: Dictionary): Dictionary { +const inverseDictionary = (map: Dictionary): Dictionary => { const m2: Dictionary = {}; for (const key in map) { m2[map[key]] = key; } return m2; -} +}; -export function findOneOfParentDiscriminator(openApi: OpenApi, parent?: Model): OpenApiDiscriminator | undefined { +export const findOneOfParentDiscriminator = (openApi: OpenApi, parent?: Model): OpenApiDiscriminator | undefined => { if (openApi.components && parent) { for (const definitionName in openApi.components.schemas) { if (openApi.components.schemas.hasOwnProperty(definitionName)) { @@ -28,9 +28,9 @@ export function findOneOfParentDiscriminator(openApi: OpenApi, parent?: Model): } } return; -} +}; -export function mapPropertyValue(discriminator: OpenApiDiscriminator, parent: Model): string { +export const mapPropertyValue = (discriminator: OpenApiDiscriminator, parent: Model): string => { if (discriminator.mapping) { const mapping = inverseDictionary(discriminator.mapping); const key = Object.keys(mapping).find(item => stripNamespace(item) == parent.name); @@ -39,4 +39,4 @@ export function mapPropertyValue(discriminator: OpenApiDiscriminator, parent: Mo } } return parent.name; -} +}; diff --git a/src/utils/flatMap.ts b/src/utils/flatMap.ts index 26fd4f28..7dbcb315 100644 --- a/src/utils/flatMap.ts +++ b/src/utils/flatMap.ts @@ -1,11 +1,11 @@ /** - * Calls a defined callback function on each element of an array. + * Calls a defined callback on each element of an array. * Then, flattens the result into a new array. */ -export function flatMap(array: T[], callback: (value: T, index: number, array: T[]) => U[]): U[] { +export const flatMap = (array: T[], callback: (value: T, index: number, array: T[]) => U[]): U[] => { const result: U[] = []; array.map(callback).forEach(arr => { result.push(...arr); }); return result; -} +}; diff --git a/src/utils/formatCode.ts b/src/utils/formatCode.ts index 17e45774..42cfd5cf 100644 --- a/src/utils/formatCode.ts +++ b/src/utils/formatCode.ts @@ -1,6 +1,6 @@ import { EOL } from 'os'; -export function formatCode(s: string): string { +export const formatCode = (s: string): string => { let indent: number = 0; let lines = s.split(EOL); lines = lines.map(line => { @@ -20,4 +20,4 @@ export function formatCode(s: string): string { return result; }); return lines.join(EOL); -} +}; diff --git a/src/utils/formatIndentation.ts b/src/utils/formatIndentation.ts index 903eec79..a2764d99 100644 --- a/src/utils/formatIndentation.ts +++ b/src/utils/formatIndentation.ts @@ -2,7 +2,7 @@ import { EOL } from 'os'; import { Indent } from '../Indent'; -export function formatIndentation(s: string, indent: Indent): string { +export const formatIndentation = (s: string, indent: Indent): string => { let lines = s.split(EOL); lines = lines.map(line => { switch (indent) { @@ -15,4 +15,4 @@ export function formatIndentation(s: string, indent: Indent): string { } }); return lines.join(EOL); -} +}; diff --git a/src/utils/getModelNames.ts b/src/utils/getModelNames.ts index 78cd58b1..26b76f71 100644 --- a/src/utils/getModelNames.ts +++ b/src/utils/getModelNames.ts @@ -1,6 +1,6 @@ import type { Model } from '../client/interfaces/Model'; import { sort } from './sort'; -export function getModelNames(models: Model[]): string[] { +export const getModelNames = (models: Model[]): string[] => { return models.map(model => model.name).sort(sort); -} +}; diff --git a/src/utils/getOpenApiSpec.ts b/src/utils/getOpenApiSpec.ts index 0d6407f0..9b52ccd2 100644 --- a/src/utils/getOpenApiSpec.ts +++ b/src/utils/getOpenApiSpec.ts @@ -6,6 +6,6 @@ import RefParser from 'json-schema-ref-parser'; * on parsing the file as JSON. * @param location: Path or url */ -export async function getOpenApiSpec(location: string): Promise { +export const getOpenApiSpec = async (location: string): Promise => { return await RefParser.bundle(location, location, {}); -} +}; diff --git a/src/utils/getOpenApiVersion.ts b/src/utils/getOpenApiVersion.ts index 8c88d497..9c7cc7e4 100644 --- a/src/utils/getOpenApiVersion.ts +++ b/src/utils/getOpenApiVersion.ts @@ -9,7 +9,7 @@ export enum OpenApiVersion { * an incompatible type. Or if the type is missing... * @param openApi The loaded spec (can be any object) */ -export function getOpenApiVersion(openApi: any): OpenApiVersion { +export const getOpenApiVersion = (openApi: any): OpenApiVersion => { const info: any = openApi.swagger || openApi.openapi; if (typeof info === 'string') { const c = info.charAt(0); @@ -19,4 +19,4 @@ export function getOpenApiVersion(openApi: any): OpenApiVersion { } } throw new Error(`Unsupported Open API version: "${String(info)}"`); -} +}; diff --git a/src/utils/getPattern.ts b/src/utils/getPattern.ts index a4f54bfa..58ee7853 100644 --- a/src/utils/getPattern.ts +++ b/src/utils/getPattern.ts @@ -5,6 +5,6 @@ * to make it a valid regexp string. * @param pattern */ -export function getPattern(pattern?: string): string | undefined { +export const getPattern = (pattern?: string): string | undefined => { return pattern?.replace(/\\/g, '\\\\'); -} +}; diff --git a/src/utils/getServiceNames.ts b/src/utils/getServiceNames.ts index 78f18469..913b746c 100644 --- a/src/utils/getServiceNames.ts +++ b/src/utils/getServiceNames.ts @@ -1,6 +1,6 @@ import type { Service } from '../client/interfaces/Service'; import { sort } from './sort'; -export function getServiceNames(services: Service[]): string[] { +export const getServiceNames = (services: Service[]): string[] => { return services.map(service => service.name).sort(sort); -} +}; diff --git a/src/utils/isDefined.ts b/src/utils/isDefined.ts index 7a9615b6..470b6f9d 100644 --- a/src/utils/isDefined.ts +++ b/src/utils/isDefined.ts @@ -2,6 +2,6 @@ * Check if a value is defined * @param value */ -export function isDefined(value: T | undefined | null | ''): value is Exclude { +export const isDefined = (value: T | undefined | null | ''): value is Exclude => { return value !== undefined && value !== null && value !== ''; -} +}; diff --git a/src/utils/isEqual.ts b/src/utils/isEqual.ts index d3fe474e..f0d1c2a3 100644 --- a/src/utils/isEqual.ts +++ b/src/utils/isEqual.ts @@ -1,4 +1,4 @@ -export function isEqual(a: any, b: any): boolean { +export const isEqual = (a: any, b: any): boolean => { if (a === b) { return true; } @@ -35,4 +35,4 @@ export function isEqual(a: any, b: any): boolean { } return a !== a && b !== b; -} +}; diff --git a/src/utils/isString.ts b/src/utils/isString.ts index 4f5dd374..581c602c 100644 --- a/src/utils/isString.ts +++ b/src/utils/isString.ts @@ -1,3 +1,3 @@ -export function isString(val: any): val is string { +export const isString = (val: any): val is string => { return typeof val === 'string'; -} +}; diff --git a/src/utils/isSubdirectory.ts b/src/utils/isSubdirectory.ts index 5a403fe8..761eb89d 100644 --- a/src/utils/isSubdirectory.ts +++ b/src/utils/isSubdirectory.ts @@ -1,5 +1,5 @@ import { relative } from 'path'; -export function isSubDirectory(parent: string, child: string) { +export const isSubDirectory = (parent: string, child: string) => { return relative(child, parent).startsWith('..'); -} +}; diff --git a/src/utils/postProcessClient.ts b/src/utils/postProcessClient.ts index 9e0e00dd..0033923d 100644 --- a/src/utils/postProcessClient.ts +++ b/src/utils/postProcessClient.ts @@ -6,10 +6,10 @@ import { postProcessService } from './postProcessService'; * Post process client * @param client Client object with all the models, services, etc. */ -export function postProcessClient(client: Client): Client { +export const postProcessClient = (client: Client): Client => { return { ...client, models: client.models.map(model => postProcessModel(model)), services: client.services.map(service => postProcessService(service)), }; -} +}; diff --git a/src/utils/postProcessModel.ts b/src/utils/postProcessModel.ts index c2e06622..3c8e3f01 100644 --- a/src/utils/postProcessModel.ts +++ b/src/utils/postProcessModel.ts @@ -8,11 +8,11 @@ import { postProcessModelImports } from './postProcessModelImports'; * This will cleanup any double imports or enum values. * @param model */ -export function postProcessModel(model: Model): Model { +export const postProcessModel = (model: Model): Model => { return { ...model, imports: postProcessModelImports(model), enums: postProcessModelEnums(model), enum: postProcessModelEnum(model), }; -} +}; diff --git a/src/utils/postProcessModelEnum.ts b/src/utils/postProcessModelEnum.ts index c2655726..f442b369 100644 --- a/src/utils/postProcessModelEnum.ts +++ b/src/utils/postProcessModelEnum.ts @@ -5,8 +5,8 @@ import type { Model } from '../client/interfaces/Model'; * Set unique enum values for the model * @param model */ -export function postProcessModelEnum(model: Model): Enum[] { +export const postProcessModelEnum = (model: Model): Enum[] => { return model.enum.filter((property, index, arr) => { return arr.findIndex(item => item.name === property.name) === index; }); -} +}; diff --git a/src/utils/postProcessModelEnums.ts b/src/utils/postProcessModelEnums.ts index e220e213..2f06127a 100644 --- a/src/utils/postProcessModelEnums.ts +++ b/src/utils/postProcessModelEnums.ts @@ -4,8 +4,8 @@ import type { Model } from '../client/interfaces/Model'; * Set unique enum values for the model * @param model The model that is post-processed */ -export function postProcessModelEnums(model: Model): Model[] { +export const postProcessModelEnums = (model: Model): Model[] => { return model.enums.filter((property, index, arr) => { return arr.findIndex(item => item.name === property.name) === index; }); -} +}; diff --git a/src/utils/postProcessModelImports.ts b/src/utils/postProcessModelImports.ts index 949dd7b3..00c0d453 100644 --- a/src/utils/postProcessModelImports.ts +++ b/src/utils/postProcessModelImports.ts @@ -6,9 +6,9 @@ import { unique } from './unique'; * Set unique imports, sorted by name * @param model The model that is post-processed */ -export function postProcessModelImports(model: Model): string[] { +export const postProcessModelImports = (model: Model): string[] => { return model.imports .filter(unique) .sort(sort) .filter(name => model.name !== name); -} +}; diff --git a/src/utils/postProcessService.ts b/src/utils/postProcessService.ts index d604dcdd..2851f4a6 100644 --- a/src/utils/postProcessService.ts +++ b/src/utils/postProcessService.ts @@ -2,7 +2,7 @@ import type { Service } from '../client/interfaces/Service'; import { postProcessServiceImports } from './postProcessServiceImports'; import { postProcessServiceOperations } from './postProcessServiceOperations'; -export function postProcessService(service: Service): Service { +export const postProcessService = (service: Service): Service => { const clone = { ...service }; clone.operations = postProcessServiceOperations(clone); clone.operations.forEach(operation => { @@ -10,4 +10,4 @@ export function postProcessService(service: Service): Service { }); clone.imports = postProcessServiceImports(clone); return clone; -} +}; diff --git a/src/utils/postProcessServiceImports.ts b/src/utils/postProcessServiceImports.ts index 50598a41..b47cfe79 100644 --- a/src/utils/postProcessServiceImports.ts +++ b/src/utils/postProcessServiceImports.ts @@ -6,6 +6,6 @@ import { unique } from './unique'; * Set unique imports, sorted by name * @param service */ -export function postProcessServiceImports(service: Service): string[] { +export const postProcessServiceImports = (service: Service): string[] => { return service.imports.filter(unique).sort(sort); -} +}; diff --git a/src/utils/postProcessServiceOperations.ts b/src/utils/postProcessServiceOperations.ts index 62faad72..5b88a5b2 100644 --- a/src/utils/postProcessServiceOperations.ts +++ b/src/utils/postProcessServiceOperations.ts @@ -2,7 +2,7 @@ import type { Operation } from '../client/interfaces/Operation'; import type { Service } from '../client/interfaces/Service'; import { flatMap } from './flatMap'; -export function postProcessServiceOperations(service: Service): Operation[] { +export const postProcessServiceOperations = (service: Service): Operation[] => { const names = new Map(); return service.operations.map(operation => { @@ -23,4 +23,4 @@ export function postProcessServiceOperations(service: Service): Operation[] { return clone; }); -} +}; diff --git a/src/utils/readSpec.ts b/src/utils/readSpec.ts index ade19525..016bf929 100644 --- a/src/utils/readSpec.ts +++ b/src/utils/readSpec.ts @@ -2,7 +2,7 @@ import { readSpecFromDisk } from './readSpecFromDisk'; import { readSpecFromHttp } from './readSpecFromHttp'; import { readSpecFromHttps } from './readSpecFromHttps'; -export async function readSpec(input: string): Promise { +export const readSpec = async (input: string): Promise => { if (input.startsWith('https://')) { return await readSpecFromHttps(input); } @@ -10,4 +10,4 @@ export async function readSpec(input: string): Promise { return await readSpecFromHttp(input); } return await readSpecFromDisk(input); -} +}; diff --git a/src/utils/readSpecFromDisk.ts b/src/utils/readSpecFromDisk.ts index 0c37c37e..7a5b7667 100644 --- a/src/utils/readSpecFromDisk.ts +++ b/src/utils/readSpecFromDisk.ts @@ -6,7 +6,7 @@ import { exists, readFile } from './fileSystem'; * Check if given file exists and try to read the content as string. * @param input */ -export async function readSpecFromDisk(input: string): Promise { +export const readSpecFromDisk = async (input: string): Promise => { const filePath = resolve(process.cwd(), input); const fileExists = await exists(filePath); if (fileExists) { @@ -18,4 +18,4 @@ export async function readSpecFromDisk(input: string): Promise { } } throw new Error(`Could not find OpenApi spec: "${filePath}"`); -} +}; diff --git a/src/utils/readSpecFromHttp.ts b/src/utils/readSpecFromHttp.ts index 3131dd9c..e4cc828a 100644 --- a/src/utils/readSpecFromHttp.ts +++ b/src/utils/readSpecFromHttp.ts @@ -4,7 +4,7 @@ import { get } from 'http'; * Download the spec file from a HTTP resource * @param url */ -export async function readSpecFromHttp(url: string): Promise { +export const readSpecFromHttp = async (url: string): Promise => { return new Promise((resolve, reject) => { get(url, response => { let body = ''; @@ -19,4 +19,4 @@ export async function readSpecFromHttp(url: string): Promise { }); }); }); -} +}; diff --git a/src/utils/readSpecFromHttps.ts b/src/utils/readSpecFromHttps.ts index 5d9f12bd..52cdc57d 100644 --- a/src/utils/readSpecFromHttps.ts +++ b/src/utils/readSpecFromHttps.ts @@ -4,7 +4,7 @@ import { get } from 'https'; * Download the spec file from a HTTPS resource * @param url */ -export async function readSpecFromHttps(url: string): Promise { +export const readSpecFromHttps = async (url: string): Promise => { return new Promise((resolve, reject) => { get(url, response => { let body = ''; @@ -19,4 +19,4 @@ export async function readSpecFromHttps(url: string): Promise { }); }); }); -} +}; diff --git a/src/utils/registerHandlebarHelpers.spec.ts b/src/utils/registerHandlebarHelpers.spec.ts index adc4200b..f71ca000 100644 --- a/src/utils/registerHandlebarHelpers.spec.ts +++ b/src/utils/registerHandlebarHelpers.spec.ts @@ -19,5 +19,6 @@ describe('registerHandlebarHelpers', () => { expect(helpers).toContain('enumerator'); expect(helpers).toContain('escapeComment'); expect(helpers).toContain('escapeDescription'); + expect(helpers).toContain('camelCase'); }); }); diff --git a/src/utils/registerHandlebarHelpers.ts b/src/utils/registerHandlebarHelpers.ts index a1ac4454..f03ab5f0 100644 --- a/src/utils/registerHandlebarHelpers.ts +++ b/src/utils/registerHandlebarHelpers.ts @@ -1,3 +1,4 @@ +import camelCase from 'camelcase'; import Handlebars from 'handlebars/runtime'; import { EOL } from 'os'; @@ -6,11 +7,11 @@ import { Model } from '../client/interfaces/Model'; import { HttpClient } from '../HttpClient'; import { unique } from './unique'; -export function registerHandlebarHelpers(root: { +export const registerHandlebarHelpers = (root: { httpClient: HttpClient; useOptions: boolean; useUnionTypes: boolean; -}): void { +}): void => { Handlebars.registerHelper( 'equals', function (this: any, a: string, b: string, options: Handlebars.HelperOptions): string { @@ -91,4 +92,8 @@ export function registerHandlebarHelpers(root: { Handlebars.registerHelper('escapeDescription', function (value: string): string { return value.replace(/\\/g, '\\\\').replace(/`/g, '\\`').replace(/\${/g, '\\${'); }); -} + + Handlebars.registerHelper('camelCase', function (value: string): string { + return camelCase(value); + }); +}; diff --git a/src/utils/registerHandlebarTemplates.ts b/src/utils/registerHandlebarTemplates.ts index a64a6f61..ee2a3086 100644 --- a/src/utils/registerHandlebarTemplates.ts +++ b/src/utils/registerHandlebarTemplates.ts @@ -103,11 +103,11 @@ export interface Templates { * Read all the Handlebar templates that we need and return on wrapper object * so we can easily access the templates in out generator / write functions. */ -export function registerHandlebarTemplates(root: { +export const registerHandlebarTemplates = (root: { httpClient: HttpClient; useOptions: boolean; useUnionTypes: boolean; -}): Templates { +}): Templates => { registerHandlebarHelpers(root); // Main templates (entry points for the files we write to disk) @@ -207,4 +207,4 @@ export function registerHandlebarTemplates(root: { Handlebars.registerPartial('axios/request', Handlebars.template(axiosRequest)); return templates; -} +}; diff --git a/src/utils/sort.ts b/src/utils/sort.ts index 9d41d840..1d76998f 100644 --- a/src/utils/sort.ts +++ b/src/utils/sort.ts @@ -1,5 +1,5 @@ -export function sort(a: string, b: string): number { +export const sort = (a: string, b: string): number => { const nameA = a.toLowerCase(); const nameB = b.toLowerCase(); return nameA.localeCompare(nameB, 'en'); -} +}; diff --git a/src/utils/sortModelsByName.ts b/src/utils/sortModelsByName.ts index c4d272e1..33fae399 100644 --- a/src/utils/sortModelsByName.ts +++ b/src/utils/sortModelsByName.ts @@ -1,9 +1,9 @@ import type { Model } from '../client/interfaces/Model'; -export function sortModelsByName(models: Model[]): Model[] { +export const sortModelsByName = (models: Model[]): Model[] => { return models.sort((a, b) => { const nameA = a.name.toLowerCase(); const nameB = b.name.toLowerCase(); return nameA.localeCompare(nameB, 'en'); }); -} +}; diff --git a/src/utils/sortServicesByName.ts b/src/utils/sortServicesByName.ts index 9ff4d871..4bbef126 100644 --- a/src/utils/sortServicesByName.ts +++ b/src/utils/sortServicesByName.ts @@ -1,9 +1,9 @@ import type { Service } from '../client/interfaces/Service'; -export function sortServicesByName(services: Service[]): Service[] { +export const sortServicesByName = (services: Service[]): Service[] => { return services.sort((a, b) => { const nameA = a.name.toLowerCase(); const nameB = b.name.toLowerCase(); return nameA.localeCompare(nameB, 'en'); }); -} +}; diff --git a/src/utils/unique.ts b/src/utils/unique.ts index 02ca1378..65c0f7c7 100644 --- a/src/utils/unique.ts +++ b/src/utils/unique.ts @@ -1,3 +1,3 @@ -export function unique(val: T, index: number, arr: T[]): boolean { +export const unique = (val: T, index: number, arr: T[]): boolean => { return arr.indexOf(val) === index; -} +}; diff --git a/src/utils/writeClient.ts b/src/utils/writeClient.ts index a00d0048..4a1feaab 100644 --- a/src/utils/writeClient.ts +++ b/src/utils/writeClient.ts @@ -32,7 +32,7 @@ import { writeClientServices } from './writeClientServices'; * @param clientName: Custom client class name * @param request: Path to custom request file */ -export async function writeClient( +export const writeClient = async ( client: Client, templates: Templates, output: string, @@ -47,7 +47,7 @@ export async function writeClient( postfix: string, clientName?: string, request?: string -): Promise { +): Promise => { const outputPath = resolve(process.cwd(), output); const outputPathCore = resolve(outputPath, 'core'); const outputPathModels = resolve(outputPath, 'models'); @@ -110,4 +110,4 @@ export async function writeClient( postfix ); } -} +}; diff --git a/src/utils/writeClientClass.ts b/src/utils/writeClientClass.ts index e0a7cb49..2b06d7d6 100644 --- a/src/utils/writeClientClass.ts +++ b/src/utils/writeClientClass.ts @@ -21,7 +21,7 @@ import { sortServicesByName } from './sortServicesByName'; * @param indent: Indentation options (4, 2 or tab) * @param postfix: Service name postfix */ -export async function writeClientClass( +export const writeClientClass = async ( client: Client, templates: Templates, outputPath: string, @@ -29,7 +29,7 @@ export async function writeClientClass( clientName: string, indent: Indent, postfix: string -): Promise { +): Promise => { const templateResult = templates.client({ clientName, postfix, @@ -41,4 +41,4 @@ export async function writeClientClass( }); await writeFile(resolve(outputPath, 'client.ts'), i(f(templateResult), indent)); -} +}; diff --git a/src/utils/writeClientCore.ts b/src/utils/writeClientCore.ts index 87d9846b..2e641e1a 100644 --- a/src/utils/writeClientCore.ts +++ b/src/utils/writeClientCore.ts @@ -3,11 +3,10 @@ import { resolve } from 'path'; import type { Client } from '../client/interfaces/Client'; import { HttpClient } from '../HttpClient'; import { Indent } from '../Indent'; -import { copyFile, exists, mkdir, writeFile } from './fileSystem'; +import { copyFile, exists, writeFile } from './fileSystem'; import { formatIndentation as i } from './formatIndentation'; import { isDefined } from './isDefined'; import { Templates } from './registerHandlebarTemplates'; -import { writeClientClass } from './writeClientClass'; /** * Generate OpenAPI core files, this includes the basic boilerplate code to handle requests. @@ -18,7 +17,7 @@ import { writeClientClass } from './writeClientClass'; * @param indent: Indentation options (4, 2 or tab) * @param request: Path to custom request file */ -export async function writeClientCore( +export const writeClientCore = async ( client: Client, templates: Templates, outputPath: string, @@ -26,7 +25,7 @@ export async function writeClientCore( indent: Indent, clientName?: string, request?: string -): Promise { +): Promise => { const context = { httpClient, clientName, @@ -55,4 +54,4 @@ export async function writeClientCore( } await copyFile(requestFile, resolve(outputPath, 'request.ts')); } -} +}; diff --git a/src/utils/writeClientIndex.ts b/src/utils/writeClientIndex.ts index 6fe74fa2..eb13cbb1 100644 --- a/src/utils/writeClientIndex.ts +++ b/src/utils/writeClientIndex.ts @@ -20,7 +20,7 @@ import { sortServicesByName } from './sortServicesByName'; * @param exportSchemas: Generate schemas * @param postfix: Service name postfix */ -export async function writeClientIndex( +export const writeClientIndex = async ( client: Client, templates: Templates, outputPath: string, @@ -30,7 +30,7 @@ export async function writeClientIndex( exportModels: boolean, exportSchemas: boolean, postfix: string -): Promise { +): Promise => { const templateResult = templates.index({ exportCore, exportServices, @@ -45,4 +45,4 @@ export async function writeClientIndex( }); await writeFile(resolve(outputPath, 'index.ts'), templateResult); -} +}; diff --git a/src/utils/writeClientModels.ts b/src/utils/writeClientModels.ts index 7c58bd85..8ea5fc22 100644 --- a/src/utils/writeClientModels.ts +++ b/src/utils/writeClientModels.ts @@ -17,14 +17,14 @@ import { Templates } from './registerHandlebarTemplates'; * @param useUnionTypes Use union types instead of enums * @param indent: Indentation options (4, 2 or tab) */ -export async function writeClientModels( +export const writeClientModels = async ( models: Model[], templates: Templates, outputPath: string, httpClient: HttpClient, useUnionTypes: boolean, indent: Indent -): Promise { +): Promise => { for (const model of models) { const file = resolve(outputPath, `${model.name}.ts`); const templateResult = templates.exports.model({ @@ -34,4 +34,4 @@ export async function writeClientModels( }); await writeFile(file, i(f(templateResult), indent)); } -} +}; diff --git a/src/utils/writeClientSchemas.ts b/src/utils/writeClientSchemas.ts index 74fdc0c9..18727198 100644 --- a/src/utils/writeClientSchemas.ts +++ b/src/utils/writeClientSchemas.ts @@ -17,14 +17,14 @@ import { Templates } from './registerHandlebarTemplates'; * @param useUnionTypes Use union types instead of enums * @param indent: Indentation options (4, 2 or tab) */ -export async function writeClientSchemas( +export const writeClientSchemas = async ( models: Model[], templates: Templates, outputPath: string, httpClient: HttpClient, useUnionTypes: boolean, indent: Indent -): Promise { +): Promise => { for (const model of models) { const file = resolve(outputPath, `$${model.name}.ts`); const templateResult = templates.exports.schema({ @@ -34,4 +34,4 @@ export async function writeClientSchemas( }); await writeFile(file, i(f(templateResult), indent)); } -} +}; diff --git a/src/utils/writeClientServices.ts b/src/utils/writeClientServices.ts index f094f69b..7bf47652 100644 --- a/src/utils/writeClientServices.ts +++ b/src/utils/writeClientServices.ts @@ -21,7 +21,7 @@ const VERSION_TEMPLATE_STRING = 'OpenAPI.VERSION'; * @param indent: Indentation options (4, 2 or tab) * @param postfix: Service name postfix */ -export async function writeClientServices( +export const writeClientServices = async ( services: Service[], templates: Templates, outputPath: string, @@ -30,7 +30,7 @@ export async function writeClientServices( useOptions: boolean, indent: Indent, postfix: string -): Promise { +): Promise => { for (const service of services) { const file = resolve(outputPath, `${service.name}${postfix}.ts`); const useVersion = service.operations.some(operation => operation.path.includes(VERSION_TEMPLATE_STRING)); @@ -44,4 +44,4 @@ export async function writeClientServices( }); await writeFile(file, i(f(templateResult), indent)); } -} +}; diff --git a/test/custom/request.ts b/test/custom/request.ts index 277a8fa4..522f85cf 100644 --- a/test/custom/request.ts +++ b/test/custom/request.ts @@ -1,10 +1,10 @@ import type { ApiRequestOptions } from './ApiRequestOptions'; import { CancelablePromise } from './CancelablePromise'; -import { OpenAPI } from './OpenAPI'; +import type { OpenAPIConfig } from './OpenAPI'; -export function request(options: ApiRequestOptions): CancelablePromise { +export const request = (config: OpenAPIConfig, options: ApiRequestOptions): CancelablePromise => { return new CancelablePromise((resolve, reject, onCancel) => { - const url = `${OpenAPI.BASE}${options.path}`; + const url = `${config.BASE}${options.path}`; try { // Do your request... @@ -28,4 +28,4 @@ export function request(options: ApiRequestOptions): CancelablePromise { reject(e); } }); -} +}; diff --git a/test/spec/v2.json b/test/spec/v2.json index bf13a84e..8171551f 100644 --- a/test/spec/v2.json +++ b/test/spec/v2.json @@ -10,6 +10,12 @@ "http" ], "paths": { + "/api/v{api-version}/no-tag": { + "tags": [], + "get": { + "operationId": "ServiceWithEmptyTag" + } + }, "/api/v{api-version}/simple": { "get": { "tags": [ diff --git a/test/spec/v3.json b/test/spec/v3.json index 2d816d70..dcfd011e 100644 --- a/test/spec/v3.json +++ b/test/spec/v3.json @@ -10,6 +10,12 @@ } ], "paths": { + "/api/v{api-version}/no-tag": { + "tags": [], + "get": { + "operationId": "ServiceWithEmptyTag" + } + }, "/api/v{api-version}/simple": { "get": { "tags": [ @@ -1886,7 +1892,9 @@ "ModelCircle": { "description": "Circle", "type": "object", - "required": ["kind"], + "required": [ + "kind" + ], "properties": { "kind": { "type": "string" @@ -1899,7 +1907,9 @@ "ModelSquare": { "description": "Square", "type": "object", - "required": ["kind"], + "required": [ + "kind" + ], "properties": { "kind": { "type": "string" From 83a0692b1010999abc4c1fd7df694f25f1adaa32 Mon Sep 17 00:00:00 2001 From: Ferdi Koomen Date: Tue, 25 Jan 2022 13:22:59 +0100 Subject: [PATCH 14/19] - Adding util to get HttpRequestName --- src/utils/getHttpRequestName.ts | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 src/utils/getHttpRequestName.ts diff --git a/src/utils/getHttpRequestName.ts b/src/utils/getHttpRequestName.ts new file mode 100644 index 00000000..e25d2380 --- /dev/null +++ b/src/utils/getHttpRequestName.ts @@ -0,0 +1,3 @@ +export const getHttpRequestName = (): string => { + return ''; +}; From e1268b197a3924a58cbacea3c3c9e781400ab304 Mon Sep 17 00:00:00 2001 From: Ferdi Koomen Date: Tue, 25 Jan 2022 13:34:23 +0100 Subject: [PATCH 15/19] - Working HttpClient exporter --- src/templates/client.hbs | 3 ++- src/utils/getHttpRequestName.ts | 19 +++++++++++++++++-- src/utils/registerHandlebarHelpers.ts | 6 +++--- src/utils/writeClient.spec.ts | 2 +- src/utils/writeClient.ts | 6 +++--- src/utils/writeClientClass.spec.ts | 2 +- src/utils/writeClientClass.ts | 10 ++++++---- src/utils/writeClientCore.spec.ts | 2 +- src/utils/writeClientCore.ts | 12 +++++++----- src/utils/writeClientIndex.spec.ts | 2 +- src/utils/writeClientModels.spec.ts | 2 +- src/utils/writeClientModels.ts | 6 +++--- src/utils/writeClientSchemas.spec.ts | 2 +- src/utils/writeClientSchemas.ts | 6 +++--- src/utils/writeClientServices.spec.ts | 2 +- src/utils/writeClientServices.ts | 6 +++--- 16 files changed, 54 insertions(+), 34 deletions(-) diff --git a/src/templates/client.hbs b/src/templates/client.hbs index 33cc0f1d..4f643fb2 100644 --- a/src/templates/client.hbs +++ b/src/templates/client.hbs @@ -3,6 +3,7 @@ import type { BaseHttpRequest } from './core/BaseHttpRequest'; import type { OpenAPIConfig } from './core/OpenAPI'; import { {{{httpRequest}}} } from './core/{{{httpRequest}}}'; + {{#if services}} {{#each services}} import { {{{name}}}{{{@root.postfix}}} } from './services/{{{name}}}{{{@root.postfix}}}'; @@ -17,7 +18,7 @@ export class {{{clientName}}} { public readonly {{{camelCase name}}}: {{{name}}}{{{@root.postfix}}}; {{/each}} - public readonly request: BaseHttpRequest; + private readonly request: BaseHttpRequest; constructor(config?: OpenAPIConfig, HttpRequest: HttpRequestConstructor = {{{httpRequest}}}) { this.request = new HttpRequest({ diff --git a/src/utils/getHttpRequestName.ts b/src/utils/getHttpRequestName.ts index e25d2380..b6906209 100644 --- a/src/utils/getHttpRequestName.ts +++ b/src/utils/getHttpRequestName.ts @@ -1,3 +1,18 @@ -export const getHttpRequestName = (): string => { - return ''; +import { HttpClient } from '../HttpClient'; + +/** + * Generate the HttpRequest filename based on the selected client + * @param httpClient The selected httpClient (fetch, xhr, node or axios) + */ +export const getHttpRequestName = (httpClient: HttpClient): string => { + switch (httpClient) { + case HttpClient.FETCH: + return 'FetchHttpRequest'; + case HttpClient.XHR: + return 'XHRHttpRequest'; + case HttpClient.NODE: + return 'NodeHttpRequest'; + case HttpClient.AXIOS: + return 'AxiosHttpRequest'; + } }; diff --git a/src/utils/registerHandlebarHelpers.ts b/src/utils/registerHandlebarHelpers.ts index f03ab5f0..58b2ad18 100644 --- a/src/utils/registerHandlebarHelpers.ts +++ b/src/utils/registerHandlebarHelpers.ts @@ -2,9 +2,9 @@ import camelCase from 'camelcase'; import Handlebars from 'handlebars/runtime'; import { EOL } from 'os'; -import { Enum } from '../client/interfaces/Enum'; -import { Model } from '../client/interfaces/Model'; -import { HttpClient } from '../HttpClient'; +import type { Enum } from '../client/interfaces/Enum'; +import type { Model } from '../client/interfaces/Model'; +import type { HttpClient } from '../HttpClient'; import { unique } from './unique'; export const registerHandlebarHelpers = (root: { diff --git a/src/utils/writeClient.spec.ts b/src/utils/writeClient.spec.ts index bc38b4b6..3c06a95a 100644 --- a/src/utils/writeClient.spec.ts +++ b/src/utils/writeClient.spec.ts @@ -2,7 +2,7 @@ import type { Client } from '../client/interfaces/Client'; import { HttpClient } from '../HttpClient'; import { Indent } from '../Indent'; import { mkdir, rmdir, writeFile } from './fileSystem'; -import { Templates } from './registerHandlebarTemplates'; +import type { Templates } from './registerHandlebarTemplates'; import { writeClient } from './writeClient'; jest.mock('./fileSystem'); diff --git a/src/utils/writeClient.ts b/src/utils/writeClient.ts index 4a1feaab..e77828db 100644 --- a/src/utils/writeClient.ts +++ b/src/utils/writeClient.ts @@ -1,12 +1,12 @@ import { resolve } from 'path'; import type { Client } from '../client/interfaces/Client'; -import { HttpClient } from '../HttpClient'; -import { Indent } from '../Indent'; +import type { HttpClient } from '../HttpClient'; +import type { Indent } from '../Indent'; import { mkdir, rmdir } from './fileSystem'; import { isDefined } from './isDefined'; import { isSubDirectory } from './isSubdirectory'; -import { Templates } from './registerHandlebarTemplates'; +import type { Templates } from './registerHandlebarTemplates'; import { writeClientClass } from './writeClientClass'; import { writeClientCore } from './writeClientCore'; import { writeClientIndex } from './writeClientIndex'; diff --git a/src/utils/writeClientClass.spec.ts b/src/utils/writeClientClass.spec.ts index 871e2052..3aa6d29c 100644 --- a/src/utils/writeClientClass.spec.ts +++ b/src/utils/writeClientClass.spec.ts @@ -2,7 +2,7 @@ import type { Client } from '../client/interfaces/Client'; import { HttpClient } from '../HttpClient'; import { Indent } from '../Indent'; import { mkdir, rmdir, writeFile } from './fileSystem'; -import { Templates } from './registerHandlebarTemplates'; +import type { Templates } from './registerHandlebarTemplates'; import { writeClientClass } from './writeClientClass'; jest.mock('./fileSystem'); diff --git a/src/utils/writeClientClass.ts b/src/utils/writeClientClass.ts index 2b06d7d6..be0702c8 100644 --- a/src/utils/writeClientClass.ts +++ b/src/utils/writeClientClass.ts @@ -1,14 +1,16 @@ import { resolve } from 'path'; import type { Client } from '../client/interfaces/Client'; -import { HttpClient } from '../HttpClient'; -import { Indent } from '../Indent'; +import type { HttpClient } from '../HttpClient'; +import type { Indent } from '../Indent'; import { writeFile } from './fileSystem'; import { formatCode as f } from './formatCode'; import { formatIndentation as i } from './formatIndentation'; -import { Templates } from './registerHandlebarTemplates'; +import { getHttpRequestName } from './getHttpRequestName'; +import type { Templates } from './registerHandlebarTemplates'; import { sortModelsByName } from './sortModelsByName'; import { sortServicesByName } from './sortServicesByName'; + /** * Generate the OpenAPI client index file using the Handlebar template and write it to disk. * The index file just contains all the exports you need to use the client as a standalone @@ -37,7 +39,7 @@ export const writeClientClass = async ( version: client.version, models: sortModelsByName(client.models), services: sortServicesByName(client.services), - httpRequest: 'XHRHttpRequest', + httpRequest: getHttpRequestName(httpClient), }); await writeFile(resolve(outputPath, 'client.ts'), i(f(templateResult), indent)); diff --git a/src/utils/writeClientCore.spec.ts b/src/utils/writeClientCore.spec.ts index b9222227..cb2cc292 100644 --- a/src/utils/writeClientCore.spec.ts +++ b/src/utils/writeClientCore.spec.ts @@ -2,7 +2,7 @@ import type { Client } from '../client/interfaces/Client'; import { HttpClient } from '../HttpClient'; import { Indent } from '../Indent'; import { writeFile } from './fileSystem'; -import { Templates } from './registerHandlebarTemplates'; +import type { Templates } from './registerHandlebarTemplates'; import { writeClientCore } from './writeClientCore'; jest.mock('./fileSystem'); diff --git a/src/utils/writeClientCore.ts b/src/utils/writeClientCore.ts index 2e641e1a..3be78d9e 100644 --- a/src/utils/writeClientCore.ts +++ b/src/utils/writeClientCore.ts @@ -1,12 +1,13 @@ import { resolve } from 'path'; import type { Client } from '../client/interfaces/Client'; -import { HttpClient } from '../HttpClient'; -import { Indent } from '../Indent'; +import type { HttpClient } from '../HttpClient'; +import type { Indent } from '../Indent'; import { copyFile, exists, writeFile } from './fileSystem'; import { formatIndentation as i } from './formatIndentation'; +import { getHttpRequestName } from './getHttpRequestName'; import { isDefined } from './isDefined'; -import { Templates } from './registerHandlebarTemplates'; +import type { Templates } from './registerHandlebarTemplates'; /** * Generate OpenAPI core files, this includes the basic boilerplate code to handle requests. @@ -26,12 +27,13 @@ export const writeClientCore = async ( clientName?: string, request?: string ): Promise => { + const httpRequest = getHttpRequestName(httpClient); const context = { httpClient, clientName, + httpRequest, server: client.server, version: client.version, - httpRequest: 'XHRHttpRequest', }; await writeFile(resolve(outputPath, 'OpenAPI.ts'), i(templates.core.settings(context), indent)); @@ -43,7 +45,7 @@ export const writeClientCore = async ( if (isDefined(clientName)) { await writeFile(resolve(outputPath, 'BaseHttpRequest.ts'), i(templates.core.baseHttpRequest(context), indent)); - await writeFile(resolve(outputPath, 'XHRHttpRequest.ts'), i(templates.core.httpRequest(context), indent)); + await writeFile(resolve(outputPath, `${httpRequest}.ts`), i(templates.core.httpRequest(context), indent)); } if (request) { diff --git a/src/utils/writeClientIndex.spec.ts b/src/utils/writeClientIndex.spec.ts index ffc365bd..6284dfd2 100644 --- a/src/utils/writeClientIndex.spec.ts +++ b/src/utils/writeClientIndex.spec.ts @@ -1,6 +1,6 @@ import type { Client } from '../client/interfaces/Client'; import { writeFile } from './fileSystem'; -import { Templates } from './registerHandlebarTemplates'; +import type { Templates } from './registerHandlebarTemplates'; import { writeClientIndex } from './writeClientIndex'; jest.mock('./fileSystem'); diff --git a/src/utils/writeClientModels.spec.ts b/src/utils/writeClientModels.spec.ts index 61e2255b..81b7b58b 100644 --- a/src/utils/writeClientModels.spec.ts +++ b/src/utils/writeClientModels.spec.ts @@ -2,7 +2,7 @@ import type { Model } from '../client/interfaces/Model'; import { HttpClient } from '../HttpClient'; import { Indent } from '../Indent'; import { writeFile } from './fileSystem'; -import { Templates } from './registerHandlebarTemplates'; +import type { Templates } from './registerHandlebarTemplates'; import { writeClientModels } from './writeClientModels'; jest.mock('./fileSystem'); diff --git a/src/utils/writeClientModels.ts b/src/utils/writeClientModels.ts index 8ea5fc22..9ecf7568 100644 --- a/src/utils/writeClientModels.ts +++ b/src/utils/writeClientModels.ts @@ -1,12 +1,12 @@ import { resolve } from 'path'; import type { Model } from '../client/interfaces/Model'; -import { HttpClient } from '../HttpClient'; -import { Indent } from '../Indent'; +import type { HttpClient } from '../HttpClient'; +import type { Indent } from '../Indent'; import { writeFile } from './fileSystem'; import { formatCode as f } from './formatCode'; import { formatIndentation as i } from './formatIndentation'; -import { Templates } from './registerHandlebarTemplates'; +import type { Templates } from './registerHandlebarTemplates'; /** * Generate Models using the Handlebar template and write to disk. diff --git a/src/utils/writeClientSchemas.spec.ts b/src/utils/writeClientSchemas.spec.ts index 1f917223..499aba3e 100644 --- a/src/utils/writeClientSchemas.spec.ts +++ b/src/utils/writeClientSchemas.spec.ts @@ -2,7 +2,7 @@ import type { Model } from '../client/interfaces/Model'; import { HttpClient } from '../HttpClient'; import { Indent } from '../Indent'; import { writeFile } from './fileSystem'; -import { Templates } from './registerHandlebarTemplates'; +import type { Templates } from './registerHandlebarTemplates'; import { writeClientSchemas } from './writeClientSchemas'; jest.mock('./fileSystem'); diff --git a/src/utils/writeClientSchemas.ts b/src/utils/writeClientSchemas.ts index 18727198..0e51e6fb 100644 --- a/src/utils/writeClientSchemas.ts +++ b/src/utils/writeClientSchemas.ts @@ -1,12 +1,12 @@ import { resolve } from 'path'; import type { Model } from '../client/interfaces/Model'; -import { HttpClient } from '../HttpClient'; -import { Indent } from '../Indent'; +import type { HttpClient } from '../HttpClient'; +import type { Indent } from '../Indent'; import { writeFile } from './fileSystem'; import { formatCode as f } from './formatCode'; import { formatIndentation as i } from './formatIndentation'; -import { Templates } from './registerHandlebarTemplates'; +import type { Templates } from './registerHandlebarTemplates'; /** * Generate Schemas using the Handlebar template and write to disk. diff --git a/src/utils/writeClientServices.spec.ts b/src/utils/writeClientServices.spec.ts index 387ea208..38a64948 100644 --- a/src/utils/writeClientServices.spec.ts +++ b/src/utils/writeClientServices.spec.ts @@ -2,7 +2,7 @@ import type { Service } from '../client/interfaces/Service'; import { HttpClient } from '../HttpClient'; import { Indent } from '../Indent'; import { writeFile } from './fileSystem'; -import { Templates } from './registerHandlebarTemplates'; +import type { Templates } from './registerHandlebarTemplates'; import { writeClientServices } from './writeClientServices'; jest.mock('./fileSystem'); diff --git a/src/utils/writeClientServices.ts b/src/utils/writeClientServices.ts index 7bf47652..633fe3af 100644 --- a/src/utils/writeClientServices.ts +++ b/src/utils/writeClientServices.ts @@ -1,12 +1,12 @@ import { resolve } from 'path'; import type { Service } from '../client/interfaces/Service'; -import { HttpClient } from '../HttpClient'; -import { Indent } from '../Indent'; +import type { HttpClient } from '../HttpClient'; +import type { Indent } from '../Indent'; import { writeFile } from './fileSystem'; import { formatCode as f } from './formatCode'; import { formatIndentation as i } from './formatIndentation'; -import { Templates } from './registerHandlebarTemplates'; +import type { Templates } from './registerHandlebarTemplates'; const VERSION_TEMPLATE_STRING = 'OpenAPI.VERSION'; From 5f58982210bdd263de9b90740e1c8042e609fce1 Mon Sep 17 00:00:00 2001 From: Ferdi Koomen Date: Tue, 25 Jan 2022 14:37:41 +0100 Subject: [PATCH 16/19] - Working solution for export client --- src/index.ts | 14 ++++----- src/openApi/v2/parser/getOperation.ts | 4 +-- .../v2/parser/getOperationPath.spec.ts | 18 ------------ src/openApi/v2/parser/getOperationPath.ts | 16 ---------- src/openApi/v3/parser/getOperation.ts | 4 +-- .../v3/parser/getOperationPath.spec.ts | 18 ------------ src/openApi/v3/parser/getOperationPath.ts | 16 ---------- src/templates/client.hbs | 4 +-- src/templates/core/ApiRequestOptions.hbs | 3 +- src/templates/core/BaseHttpRequest.hbs | 1 + src/templates/core/functions/getUrl.hbs | 21 ++++++++++---- src/templates/exportService.hbs | 29 +++++++++++++++++-- src/utils/getOpenApiSpec.ts | 2 +- src/utils/postProcessModel.ts | 4 +-- src/utils/writeClient.ts | 21 +++++++------- src/utils/writeClientClass.ts | 4 +-- src/utils/writeClientCore.ts | 5 ++-- src/utils/writeClientIndex.ts | 10 +++---- src/utils/writeClientModels.ts | 2 +- src/utils/writeClientSchemas.ts | 2 +- src/utils/writeClientServices.ts | 14 ++++----- test/custom/request.ts | 2 +- test/index.js | 2 +- test/spec/v2.json | 14 ++++----- test/spec/v3.json | 10 +++---- 25 files changed, 102 insertions(+), 138 deletions(-) delete mode 100644 src/openApi/v2/parser/getOperationPath.spec.ts delete mode 100644 src/openApi/v2/parser/getOperationPath.ts delete mode 100644 src/openApi/v3/parser/getOperationPath.spec.ts delete mode 100644 src/openApi/v3/parser/getOperationPath.ts diff --git a/src/index.ts b/src/index.ts index eef0c2dc..ef7a8b1b 100644 --- a/src/index.ts +++ b/src/index.ts @@ -39,13 +39,13 @@ export type Options = { * @param clientName Custom client class name * @param useOptions Use options or arguments functions * @param useUnionTypes Use union types instead of enums - * @param exportCore: Generate core client classes - * @param exportServices: Generate services - * @param exportModels: Generate models - * @param exportSchemas: Generate schemas - * @param indent: Indentation options (4, 2 or tab) - * @param postfix: Service name postfix - * @param request: Path to custom request file + * @param exportCore Generate core client classes + * @param exportServices Generate services + * @param exportModels Generate models + * @param exportSchemas Generate schemas + * @param indent Indentation options (4, 2 or tab) + * @param postfix Service name postfix + * @param request Path to custom request file * @param write Write the files to disk (true or false) */ export const generate = async ({ diff --git a/src/openApi/v2/parser/getOperation.ts b/src/openApi/v2/parser/getOperation.ts index e344c7f9..089ade17 100644 --- a/src/openApi/v2/parser/getOperation.ts +++ b/src/openApi/v2/parser/getOperation.ts @@ -5,7 +5,6 @@ import type { OpenApiOperation } from '../interfaces/OpenApiOperation'; import { getOperationErrors } from './getOperationErrors'; import { getOperationName } from './getOperationName'; import { getOperationParameters } from './getOperationParameters'; -import { getOperationPath } from './getOperationPath'; import { getOperationResponseHeader } from './getOperationResponseHeader'; import { getOperationResponses } from './getOperationResponses'; import { getOperationResults } from './getOperationResults'; @@ -22,7 +21,6 @@ export const getOperation = ( ): Operation => { const serviceName = getServiceName(tag); const operationName = getOperationName(op.operationId || `${method}`); - const operationPath = getOperationPath(url); // Create a new operation object for this method. const operation: Operation = { @@ -32,7 +30,7 @@ export const getOperation = ( description: op.description || null, deprecated: op.deprecated === true, method: method.toUpperCase(), - path: operationPath, + path: url, parameters: [...pathParams.parameters], parametersPath: [...pathParams.parametersPath], parametersQuery: [...pathParams.parametersQuery], diff --git a/src/openApi/v2/parser/getOperationPath.spec.ts b/src/openApi/v2/parser/getOperationPath.spec.ts deleted file mode 100644 index d69ac899..00000000 --- a/src/openApi/v2/parser/getOperationPath.spec.ts +++ /dev/null @@ -1,18 +0,0 @@ -import { getOperationPath } from './getOperationPath'; - -describe('getOperationPath', () => { - it('should produce correct result', () => { - expect(getOperationPath('/api/v{api-version}/list/{id}/{type}')).toEqual( - '/api/v${OpenAPI.VERSION}/list/${id}/${type}' - ); - expect(getOperationPath('/api/v{api-version}/list/{id}')).toEqual('/api/v${OpenAPI.VERSION}/list/${id}'); - expect(getOperationPath('/api/v1/list/{id}')).toEqual('/api/v1/list/${id}'); - expect(getOperationPath('/api/{foobar}')).toEqual('/api/${foobar}'); - expect(getOperationPath('/api/{fooBar}')).toEqual('/api/${fooBar}'); - expect(getOperationPath('/api/{foo-bar}')).toEqual('/api/${fooBar}'); - expect(getOperationPath('/api/{foo_bar}')).toEqual('/api/${fooBar}'); - expect(getOperationPath('/api/{foo.bar}')).toEqual('/api/${fooBar}'); - expect(getOperationPath('/api/{Foo-Bar}')).toEqual('/api/${fooBar}'); - expect(getOperationPath('/api/{FOO-BAR}')).toEqual('/api/${fooBar}'); - }); -}); diff --git a/src/openApi/v2/parser/getOperationPath.ts b/src/openApi/v2/parser/getOperationPath.ts deleted file mode 100644 index 17594a2c..00000000 --- a/src/openApi/v2/parser/getOperationPath.ts +++ /dev/null @@ -1,16 +0,0 @@ -import { getOperationParameterName } from './getOperationParameterName'; - -/** - * Get the final service path, this replaces the "{api-version}" placeholder - * with a new template string placeholder so we can dynamically inject the - * OpenAPI version without the need to hardcode this in the URL. - * Plus we return the correct parameter names to replace in the URL. - * @param path - */ -export const getOperationPath = (path: string): string => { - return path - .replace(/\{(.*?)\}/g, (_, w: string) => { - return `\${${getOperationParameterName(w)}}`; - }) - .replace('${apiVersion}', '${OpenAPI.VERSION}'); -}; diff --git a/src/openApi/v3/parser/getOperation.ts b/src/openApi/v3/parser/getOperation.ts index 027d9f13..c8b3e316 100644 --- a/src/openApi/v3/parser/getOperation.ts +++ b/src/openApi/v3/parser/getOperation.ts @@ -6,7 +6,6 @@ import type { OpenApiRequestBody } from '../interfaces/OpenApiRequestBody'; import { getOperationErrors } from './getOperationErrors'; import { getOperationName } from './getOperationName'; import { getOperationParameters } from './getOperationParameters'; -import { getOperationPath } from './getOperationPath'; import { getOperationRequestBody } from './getOperationRequestBody'; import { getOperationResponseHeader } from './getOperationResponseHeader'; import { getOperationResponses } from './getOperationResponses'; @@ -25,7 +24,6 @@ export const getOperation = ( ): Operation => { const serviceName = getServiceName(tag); const operationName = getOperationName(op.operationId || `${method}`); - const operationPath = getOperationPath(url); // Create a new operation object for this method. const operation: Operation = { @@ -35,7 +33,7 @@ export const getOperation = ( description: op.description || null, deprecated: op.deprecated === true, method: method.toUpperCase(), - path: operationPath, + path: url, parameters: [...pathParams.parameters], parametersPath: [...pathParams.parametersPath], parametersQuery: [...pathParams.parametersQuery], diff --git a/src/openApi/v3/parser/getOperationPath.spec.ts b/src/openApi/v3/parser/getOperationPath.spec.ts deleted file mode 100644 index d69ac899..00000000 --- a/src/openApi/v3/parser/getOperationPath.spec.ts +++ /dev/null @@ -1,18 +0,0 @@ -import { getOperationPath } from './getOperationPath'; - -describe('getOperationPath', () => { - it('should produce correct result', () => { - expect(getOperationPath('/api/v{api-version}/list/{id}/{type}')).toEqual( - '/api/v${OpenAPI.VERSION}/list/${id}/${type}' - ); - expect(getOperationPath('/api/v{api-version}/list/{id}')).toEqual('/api/v${OpenAPI.VERSION}/list/${id}'); - expect(getOperationPath('/api/v1/list/{id}')).toEqual('/api/v1/list/${id}'); - expect(getOperationPath('/api/{foobar}')).toEqual('/api/${foobar}'); - expect(getOperationPath('/api/{fooBar}')).toEqual('/api/${fooBar}'); - expect(getOperationPath('/api/{foo-bar}')).toEqual('/api/${fooBar}'); - expect(getOperationPath('/api/{foo_bar}')).toEqual('/api/${fooBar}'); - expect(getOperationPath('/api/{foo.bar}')).toEqual('/api/${fooBar}'); - expect(getOperationPath('/api/{Foo-Bar}')).toEqual('/api/${fooBar}'); - expect(getOperationPath('/api/{FOO-BAR}')).toEqual('/api/${fooBar}'); - }); -}); diff --git a/src/openApi/v3/parser/getOperationPath.ts b/src/openApi/v3/parser/getOperationPath.ts deleted file mode 100644 index 17594a2c..00000000 --- a/src/openApi/v3/parser/getOperationPath.ts +++ /dev/null @@ -1,16 +0,0 @@ -import { getOperationParameterName } from './getOperationParameterName'; - -/** - * Get the final service path, this replaces the "{api-version}" placeholder - * with a new template string placeholder so we can dynamically inject the - * OpenAPI version without the need to hardcode this in the URL. - * Plus we return the correct parameter names to replace in the URL. - * @param path - */ -export const getOperationPath = (path: string): string => { - return path - .replace(/\{(.*?)\}/g, (_, w: string) => { - return `\${${getOperationParameterName(w)}}`; - }) - .replace('${apiVersion}', '${OpenAPI.VERSION}'); -}; diff --git a/src/templates/client.hbs b/src/templates/client.hbs index 4f643fb2..bd29b940 100644 --- a/src/templates/client.hbs +++ b/src/templates/client.hbs @@ -14,9 +14,9 @@ type HttpRequestConstructor = new (config: OpenAPIConfig) => BaseHttpRequest; export class {{{clientName}}} { -{{#each services}} + {{#each services}} public readonly {{{camelCase name}}}: {{{name}}}{{{@root.postfix}}}; -{{/each}} + {{/each}} private readonly request: BaseHttpRequest; diff --git a/src/templates/core/ApiRequestOptions.hbs b/src/templates/core/ApiRequestOptions.hbs index 690c19f8..355929a7 100644 --- a/src/templates/core/ApiRequestOptions.hbs +++ b/src/templates/core/ApiRequestOptions.hbs @@ -2,7 +2,8 @@ export type ApiRequestOptions = { readonly method: 'GET' | 'PUT' | 'POST' | 'DELETE' | 'OPTIONS' | 'HEAD' | 'PATCH'; - readonly path: string; + readonly url: string; + readonly path?: Record; readonly cookies?: Record; readonly headers?: Record; readonly query?: Record; diff --git a/src/templates/core/BaseHttpRequest.hbs b/src/templates/core/BaseHttpRequest.hbs index 6a70629a..2b7ca480 100644 --- a/src/templates/core/BaseHttpRequest.hbs +++ b/src/templates/core/BaseHttpRequest.hbs @@ -5,6 +5,7 @@ import type { CancelablePromise } from './CancelablePromise'; import type { OpenAPIConfig } from './OpenAPI'; export class BaseHttpRequest { + protected readonly config: OpenAPIConfig; constructor(config: OpenAPIConfig) { diff --git a/src/templates/core/functions/getUrl.hbs b/src/templates/core/functions/getUrl.hbs index 7c309ca2..4624533d 100644 --- a/src/templates/core/functions/getUrl.hbs +++ b/src/templates/core/functions/getUrl.hbs @@ -1,9 +1,18 @@ const getUrl = (config: OpenAPIConfig, options: ApiRequestOptions): string => { - const path = config.ENCODE_PATH ? config.ENCODE_PATH(options.path) : options.path; - const url = `${config.BASE}${path}`; - if (options.query) { - return `${url}${getQueryString(options.query)}`; - } + const encoder = config.ENCODE_PATH || encodeURI; - return url; + const path = options.url + .replace('{api-version}', config.VERSION) + .replace(/{(.*?)}/g, (substring: string, group: string) => { + if (options.path?.hasOwnProperty(group)) { + return encoder(String(options.path[group])); + } + return substring; + }); + + const url = `${config.BASE}${path}`; + if (options.query) { + return `${url}${getQueryString(options.query)}`; + } + return url; }; diff --git a/src/templates/exportService.hbs b/src/templates/exportService.hbs index 13becbfa..d0f8aa5c 100644 --- a/src/templates/exportService.hbs +++ b/src/templates/exportService.hbs @@ -6,12 +6,22 @@ import type { {{{this}}} } from '../models/{{{this}}}'; {{/each}} {{/if}} import type { CancelablePromise } from '../core/CancelablePromise'; -import { request as __request } from '../core/request'; -{{#if @root.useVersion}} +{{#if @root.exportClient}} +import type { BaseHttpRequest } from '../core/BaseHttpRequest'; +{{else}} import { OpenAPI } from '../core/OpenAPI'; +import { request as __request } from '../core/request'; {{/if}} export class {{{name}}}{{{@root.postfix}}} { + {{#if @root.exportClient}} + + private readonly httpRequest: BaseHttpRequest; + + constructor(httpRequest: BaseHttpRequest) { + this.httpRequest = httpRequest; + } + {{/if}} {{#each operations}} /** @@ -36,10 +46,23 @@ export class {{{name}}}{{{@root.postfix}}} { {{/each}} * @throws ApiError */ + {{#if @root.exportClient}} + public {{{name}}}({{>parameters}}): CancelablePromise<{{>result}}> { + return this.httpRequest.request({ + {{/if}} + {{#unless @root.exportClient}} public static {{{name}}}({{>parameters}}): CancelablePromise<{{>result}}> { return __request(OpenAPI, { + {{/unless}} method: '{{{method}}}', - path: `{{{path}}}`, + url: '{{{path}}}', + {{#if parametersPath}} + path: { + {{#each parametersPath}} + '{{{prop}}}': {{{name}}}, + {{/each}} + }, + {{/if}} {{#if parametersCookie}} cookies: { {{#each parametersCookie}} diff --git a/src/utils/getOpenApiSpec.ts b/src/utils/getOpenApiSpec.ts index 9b52ccd2..148b1469 100644 --- a/src/utils/getOpenApiSpec.ts +++ b/src/utils/getOpenApiSpec.ts @@ -2,7 +2,7 @@ import RefParser from 'json-schema-ref-parser'; /** * Load and parse te open api spec. If the file extension is ".yml" or ".yaml" - * we will try to parse the file as a YAML spec, otherwise we will fallback + * we will try to parse the file as a YAML spec, otherwise we will fall back * on parsing the file as JSON. * @param location: Path or url */ diff --git a/src/utils/postProcessModel.ts b/src/utils/postProcessModel.ts index 3c8e3f01..195a94e4 100644 --- a/src/utils/postProcessModel.ts +++ b/src/utils/postProcessModel.ts @@ -4,8 +4,8 @@ import { postProcessModelEnums } from './postProcessModelEnums'; import { postProcessModelImports } from './postProcessModelImports'; /** - * Post process the model. - * This will cleanup any double imports or enum values. + * Post processes the model. + * This will clean up any double imports or enum values. * @param model */ export const postProcessModel = (model: Model): Model => { diff --git a/src/utils/writeClient.ts b/src/utils/writeClient.ts index e77828db..41a28a7c 100644 --- a/src/utils/writeClient.ts +++ b/src/utils/writeClient.ts @@ -22,15 +22,15 @@ import { writeClientServices } from './writeClientServices'; * @param httpClient The selected httpClient (fetch, xhr, node or axios) * @param useOptions Use options or arguments functions * @param useUnionTypes Use union types instead of enums - * @param exportCore: Generate core client classes - * @param exportServices: Generate services - * @param exportModels: Generate models - * @param exportSchemas: Generate schemas - * @param exportSchemas: Generate schemas - * @param indent: Indentation options (4, 2 or tab) - * @param postfix: Service name postfix - * @param clientName: Custom client class name - * @param request: Path to custom request file + * @param exportCore Generate core client classes + * @param exportServices Generate services + * @param exportModels Generate models + * @param exportSchemas Generate schemas + * @param exportSchemas Generate schemas + * @param indent Indentation options (4, 2 or tab) + * @param postfix Service name postfix + * @param clientName Custom client class name + * @param request Path to custom request file */ export const writeClient = async ( client: Client, @@ -75,7 +75,8 @@ export const writeClient = async ( useUnionTypes, useOptions, indent, - postfix + postfix, + clientName ); } diff --git a/src/utils/writeClientClass.ts b/src/utils/writeClientClass.ts index be0702c8..549a5c5b 100644 --- a/src/utils/writeClientClass.ts +++ b/src/utils/writeClientClass.ts @@ -20,8 +20,8 @@ import { sortServicesByName } from './sortServicesByName'; * @param outputPath Directory to write the generated files to * @param httpClient The selected httpClient (fetch, xhr, node or axios) * @param clientName Custom client class name - * @param indent: Indentation options (4, 2 or tab) - * @param postfix: Service name postfix + * @param indent Indentation options (4, 2 or tab) + * @param postfix Service name postfix */ export const writeClientClass = async ( client: Client, diff --git a/src/utils/writeClientCore.ts b/src/utils/writeClientCore.ts index 3be78d9e..6d35849d 100644 --- a/src/utils/writeClientCore.ts +++ b/src/utils/writeClientCore.ts @@ -15,8 +15,9 @@ import type { Templates } from './registerHandlebarTemplates'; * @param templates The loaded handlebar templates * @param outputPath Directory to write the generated files to * @param httpClient The selected httpClient (fetch, xhr, node or axios) - * @param indent: Indentation options (4, 2 or tab) - * @param request: Path to custom request file + * @param indent Indentation options (4, 2 or tab) + * @param clientName Custom client class name + * @param request Path to custom request file */ export const writeClientCore = async ( client: Client, diff --git a/src/utils/writeClientIndex.ts b/src/utils/writeClientIndex.ts index eb13cbb1..d72d12d2 100644 --- a/src/utils/writeClientIndex.ts +++ b/src/utils/writeClientIndex.ts @@ -14,11 +14,11 @@ import { sortServicesByName } from './sortServicesByName'; * @param templates The loaded handlebar templates * @param outputPath Directory to write the generated files to * @param useUnionTypes Use union types instead of enums - * @param exportCore: Generate core - * @param exportServices: Generate services - * @param exportModels: Generate models - * @param exportSchemas: Generate schemas - * @param postfix: Service name postfix + * @param exportCore Generate core + * @param exportServices Generate services + * @param exportModels Generate models + * @param exportSchemas Generate schemas + * @param postfix Service name postfix */ export const writeClientIndex = async ( client: Client, diff --git a/src/utils/writeClientModels.ts b/src/utils/writeClientModels.ts index 9ecf7568..997569b9 100644 --- a/src/utils/writeClientModels.ts +++ b/src/utils/writeClientModels.ts @@ -15,7 +15,7 @@ import type { Templates } from './registerHandlebarTemplates'; * @param outputPath Directory to write the generated files to * @param httpClient The selected httpClient (fetch, xhr, node or axios) * @param useUnionTypes Use union types instead of enums - * @param indent: Indentation options (4, 2 or tab) + * @param indent Indentation options (4, 2 or tab) */ export const writeClientModels = async ( models: Model[], diff --git a/src/utils/writeClientSchemas.ts b/src/utils/writeClientSchemas.ts index 0e51e6fb..e1c885f6 100644 --- a/src/utils/writeClientSchemas.ts +++ b/src/utils/writeClientSchemas.ts @@ -15,7 +15,7 @@ import type { Templates } from './registerHandlebarTemplates'; * @param outputPath Directory to write the generated files to * @param httpClient The selected httpClient (fetch, xhr, node or axios) * @param useUnionTypes Use union types instead of enums - * @param indent: Indentation options (4, 2 or tab) + * @param indent Indentation options (4, 2 or tab) */ export const writeClientSchemas = async ( models: Model[], diff --git a/src/utils/writeClientServices.ts b/src/utils/writeClientServices.ts index 633fe3af..2f95341d 100644 --- a/src/utils/writeClientServices.ts +++ b/src/utils/writeClientServices.ts @@ -6,10 +6,9 @@ import type { Indent } from '../Indent'; import { writeFile } from './fileSystem'; import { formatCode as f } from './formatCode'; import { formatIndentation as i } from './formatIndentation'; +import { isDefined } from './isDefined'; import type { Templates } from './registerHandlebarTemplates'; -const VERSION_TEMPLATE_STRING = 'OpenAPI.VERSION'; - /** * Generate Services using the Handlebar template and write to disk. * @param services Array of Services to write @@ -18,8 +17,9 @@ const VERSION_TEMPLATE_STRING = 'OpenAPI.VERSION'; * @param httpClient The selected httpClient (fetch, xhr, node or axios) * @param useUnionTypes Use union types instead of enums * @param useOptions Use options or arguments functions - * @param indent: Indentation options (4, 2 or tab) - * @param postfix: Service name postfix + * @param indent Indentation options (4, 2 or tab) + * @param postfix Service name postfix + * @param clientName Custom client class name */ export const writeClientServices = async ( services: Service[], @@ -29,18 +29,18 @@ export const writeClientServices = async ( useUnionTypes: boolean, useOptions: boolean, indent: Indent, - postfix: string + postfix: string, + clientName?: string ): Promise => { for (const service of services) { const file = resolve(outputPath, `${service.name}${postfix}.ts`); - const useVersion = service.operations.some(operation => operation.path.includes(VERSION_TEMPLATE_STRING)); const templateResult = templates.exports.service({ ...service, httpClient, useUnionTypes, - useVersion, useOptions, postfix, + exportClient: isDefined(clientName), }); await writeFile(file, i(f(templateResult), indent)); } diff --git a/test/custom/request.ts b/test/custom/request.ts index 522f85cf..8252ea39 100644 --- a/test/custom/request.ts +++ b/test/custom/request.ts @@ -4,7 +4,7 @@ import type { OpenAPIConfig } from './OpenAPI'; export const request = (config: OpenAPIConfig, options: ApiRequestOptions): CancelablePromise => { return new CancelablePromise((resolve, reject, onCancel) => { - const url = `${config.BASE}${options.path}`; + const url = `${config.BASE}${options.path}`.replace('{api-version}', config.VERSION); try { // Do your request... diff --git a/test/index.js b/test/index.js index d945a191..bcb3b9f5 100644 --- a/test/index.js +++ b/test/index.js @@ -7,7 +7,7 @@ const generate = async (input, output) => { await OpenAPI.generate({ input, output, - httpClient: OpenAPI.HttpClient.NODE, + httpClient: OpenAPI.HttpClient.FETCH, useOptions: false, useUnionTypes: false, exportCore: true, diff --git a/test/spec/v2.json b/test/spec/v2.json index 8171551f..2b3a314b 100644 --- a/test/spec/v2.json +++ b/test/spec/v2.json @@ -89,7 +89,7 @@ "required": true }, { - "description": "This is the parameter that is send as request body", + "description": "This is the parameter that is sent as request body", "name": "parameterBody", "in": "body", "type": "string", @@ -168,7 +168,7 @@ "required": true }, { - "description": "This is the parameter that is send as request body", + "description": "This is the parameter that is sent as request body", "name": "PARAMETER-BODY", "in": "body", "type": "string", @@ -574,7 +574,7 @@ "operationId": "CollectionFormat", "parameters": [ { - "description": "This is an array parameter that is send as csv format (comma-separated values)", + "description": "This is an array parameter that is sent as csv format (comma-separated values)", "name": "parameterArrayCSV", "in": "query", "required": true, @@ -585,7 +585,7 @@ "collectionFormat": "csv" }, { - "description": "This is an array parameter that is send as ssv format (space-separated values)", + "description": "This is an array parameter that is sent as ssv format (space-separated values)", "name": "parameterArraySSV", "in": "query", "required": true, @@ -596,7 +596,7 @@ "collectionFormat": "ssv" }, { - "description": "This is an array parameter that is send as tsv format (tab-separated values)", + "description": "This is an array parameter that is sent as tsv format (tab-separated values)", "name": "parameterArrayTSV", "in": "query", "required": true, @@ -607,7 +607,7 @@ "collectionFormat": "tsv" }, { - "description": "This is an array parameter that is send as pipes format (pipe-separated values)", + "description": "This is an array parameter that is sent as pipes format (pipe-separated values)", "name": "parameterArrayPipes", "in": "query", "required": true, @@ -618,7 +618,7 @@ "collectionFormat": "pipes" }, { - "description": "This is an array parameter that is send as multi format (multiple parameter instances)", + "description": "This is an array parameter that is sent as multi format (multiple parameter instances)", "name": "parameterArrayMulti", "in": "query", "required": true, diff --git a/test/spec/v3.json b/test/spec/v3.json index dcfd011e..f1872aff 100644 --- a/test/spec/v3.json +++ b/test/spec/v3.json @@ -814,7 +814,7 @@ "operationId": "CollectionFormat", "parameters": [ { - "description": "This is an array parameter that is send as csv format (comma-separated values)", + "description": "This is an array parameter that is sent as csv format (comma-separated values)", "name": "parameterArrayCSV", "in": "query", "required": true, @@ -828,7 +828,7 @@ "collectionFormat": "csv" }, { - "description": "This is an array parameter that is send as ssv format (space-separated values)", + "description": "This is an array parameter that is sent as ssv format (space-separated values)", "name": "parameterArraySSV", "in": "query", "required": true, @@ -842,7 +842,7 @@ "collectionFormat": "ssv" }, { - "description": "This is an array parameter that is send as tsv format (tab-separated values)", + "description": "This is an array parameter that is sent as tsv format (tab-separated values)", "name": "parameterArrayTSV", "in": "query", "required": true, @@ -856,7 +856,7 @@ "collectionFormat": "tsv" }, { - "description": "This is an array parameter that is send as pipes format (pipe-separated values)", + "description": "This is an array parameter that is sent as pipes format (pipe-separated values)", "name": "parameterArrayPipes", "in": "query", "required": true, @@ -870,7 +870,7 @@ "collectionFormat": "pipes" }, { - "description": "This is an array parameter that is send as multi format (multiple parameter instances)", + "description": "This is an array parameter that is sent as multi format (multiple parameter instances)", "name": "parameterArrayMulti", "in": "query", "required": true, From b2d80960316760e5ec3e48a129c08136c35d9c09 Mon Sep 17 00:00:00 2001 From: Ferdi Koomen Date: Tue, 25 Jan 2022 15:32:20 +0100 Subject: [PATCH 17/19] - Added e2e test - Cleanup of new export client logic --- jest.config.ts | 5 + src/openApi/v2/parser/getServices.spec.ts | 2 +- src/openApi/v3/parser/getServices.spec.ts | 2 +- src/templates/client.hbs | 2 +- src/templates/index.hbs | 8 +- src/utils/writeClient.ts | 3 +- src/utils/writeClientClass.spec.ts | 4 +- src/utils/writeClientIndex.ts | 6 +- test/__snapshots__/index.spec.ts.snap | 679 +++++++++++++--------- test/e2e/client.axios.spec.ts | 84 +++ test/e2e/client.babel.spec.ts | 62 ++ test/e2e/client.fetch.spec.ts | 161 +++++ test/e2e/client.node.spec.ts | 142 +++++ test/e2e/client.xhr.spec.ts | 142 +++++ test/e2e/scripts/generate.ts | 4 +- test/index.js | 2 +- 16 files changed, 1007 insertions(+), 301 deletions(-) create mode 100644 test/e2e/client.axios.spec.ts create mode 100644 test/e2e/client.babel.spec.ts create mode 100644 test/e2e/client.fetch.spec.ts create mode 100644 test/e2e/client.node.spec.ts create mode 100644 test/e2e/client.xhr.spec.ts diff --git a/jest.config.ts b/jest.config.ts index 04ba4641..9c39db93 100644 --- a/jest.config.ts +++ b/jest.config.ts @@ -25,6 +25,11 @@ const config: Config.InitialOptions = { '/test/e2e/v3.node.spec.ts', '/test/e2e/v3.axios.spec.ts', '/test/e2e/v3.babel.spec.ts', + '/test/e2e/client.fetch.spec.ts', + '/test/e2e/client.xhr.spec.ts', + '/test/e2e/client.node.spec.ts', + '/test/e2e/client.axios.spec.ts', + '/test/e2e/client.babel.spec.ts', ], }, ], diff --git a/src/openApi/v2/parser/getServices.spec.ts b/src/openApi/v2/parser/getServices.spec.ts index 75228719..915ee6b0 100644 --- a/src/openApi/v2/parser/getServices.spec.ts +++ b/src/openApi/v2/parser/getServices.spec.ts @@ -26,6 +26,6 @@ describe('getServices', () => { }); expect(services).toHaveLength(1); - expect(services[0].name).toEqual(''); + expect(services[0].name).toEqual('Default'); }); }); diff --git a/src/openApi/v3/parser/getServices.spec.ts b/src/openApi/v3/parser/getServices.spec.ts index 873970ad..baea07e6 100644 --- a/src/openApi/v3/parser/getServices.spec.ts +++ b/src/openApi/v3/parser/getServices.spec.ts @@ -26,6 +26,6 @@ describe('getServices', () => { }); expect(services).toHaveLength(1); - expect(services[0].name).toEqual(''); + expect(services[0].name).toEqual('Default'); }); }); diff --git a/src/templates/client.hbs b/src/templates/client.hbs index bd29b940..b535311f 100644 --- a/src/templates/client.hbs +++ b/src/templates/client.hbs @@ -20,7 +20,7 @@ export class {{{clientName}}} { private readonly request: BaseHttpRequest; - constructor(config?: OpenAPIConfig, HttpRequest: HttpRequestConstructor = {{{httpRequest}}}) { + constructor(config?: Partial, HttpRequest: HttpRequestConstructor = {{{httpRequest}}}) { this.request = new HttpRequest({ BASE: config?.BASE ?? '{{{server}}}', VERSION: config?.VERSION ?? '{{{version}}}', diff --git a/src/templates/index.hbs b/src/templates/index.hbs index 86a25715..3c58e1cf 100644 --- a/src/templates/index.hbs +++ b/src/templates/index.hbs @@ -1,7 +1,13 @@ {{>header}} -{{#if @root.exportCore}} +{{#if @root.exportClient}} +export { AppClient } from './client'; +{{/if}} +{{#if @root.exportCore}} export { ApiError } from './core/ApiError'; +{{#if @root.exportClient}} +export { BaseHttpRequest } from './core/BaseHttpRequest'; +{{/if}} export { CancelablePromise, CancelError } from './core/CancelablePromise'; export { OpenAPI } from './core/OpenAPI'; export type { OpenAPIConfig } from './core/OpenAPI'; diff --git a/src/utils/writeClient.ts b/src/utils/writeClient.ts index 41a28a7c..a0ffc182 100644 --- a/src/utils/writeClient.ts +++ b/src/utils/writeClient.ts @@ -108,7 +108,8 @@ export const writeClient = async ( exportServices, exportModels, exportSchemas, - postfix + postfix, + clientName ); } }; diff --git a/src/utils/writeClientClass.spec.ts b/src/utils/writeClientClass.spec.ts index 3aa6d29c..102f2eb5 100644 --- a/src/utils/writeClientClass.spec.ts +++ b/src/utils/writeClientClass.spec.ts @@ -1,7 +1,7 @@ import type { Client } from '../client/interfaces/Client'; import { HttpClient } from '../HttpClient'; import { Indent } from '../Indent'; -import { mkdir, rmdir, writeFile } from './fileSystem'; +import { writeFile } from './fileSystem'; import type { Templates } from './registerHandlebarTemplates'; import { writeClientClass } from './writeClientClass'; @@ -38,8 +38,6 @@ describe('writeClientClass', () => { await writeClientClass(client, templates, './dist', HttpClient.FETCH, 'AppClient', Indent.SPACE_4, ''); - expect(rmdir).toBeCalled(); - expect(mkdir).toBeCalled(); expect(writeFile).toBeCalled(); }); }); diff --git a/src/utils/writeClientIndex.ts b/src/utils/writeClientIndex.ts index d72d12d2..67ef0ced 100644 --- a/src/utils/writeClientIndex.ts +++ b/src/utils/writeClientIndex.ts @@ -2,6 +2,7 @@ import { resolve } from 'path'; import type { Client } from '../client/interfaces/Client'; import { writeFile } from './fileSystem'; +import { isDefined } from './isDefined'; import { Templates } from './registerHandlebarTemplates'; import { sortModelsByName } from './sortModelsByName'; import { sortServicesByName } from './sortServicesByName'; @@ -19,6 +20,7 @@ import { sortServicesByName } from './sortServicesByName'; * @param exportModels Generate models * @param exportSchemas Generate schemas * @param postfix Service name postfix + * @param clientName Custom client class name */ export const writeClientIndex = async ( client: Client, @@ -29,7 +31,8 @@ export const writeClientIndex = async ( exportServices: boolean, exportModels: boolean, exportSchemas: boolean, - postfix: string + postfix: string, + clientName?: string ): Promise => { const templateResult = templates.index({ exportCore, @@ -42,6 +45,7 @@ export const writeClientIndex = async ( version: client.version, models: sortModelsByName(client.models), services: sortServicesByName(client.services), + exportClient: isDefined(clientName), }); await writeFile(resolve(outputPath, 'index.ts'), templateResult); diff --git a/test/__snapshots__/index.spec.ts.snap b/test/__snapshots__/index.spec.ts.snap index 0d3dc80f..f280a93b 100644 --- a/test/__snapshots__/index.spec.ts.snap +++ b/test/__snapshots__/index.spec.ts.snap @@ -30,7 +30,8 @@ exports[`v2 should generate: ./test/generated/v2/core/ApiRequestOptions.ts 1`] = /* eslint-disable */ export type ApiRequestOptions = { readonly method: 'GET' | 'PUT' | 'POST' | 'DELETE' | 'OPTIONS' | 'HEAD' | 'PATCH'; - readonly path: string; + readonly url: string; + readonly path?: Record; readonly cookies?: Record; readonly headers?: Record; readonly query?: Record; @@ -195,7 +196,7 @@ import type { ApiRequestOptions } from './ApiRequestOptions'; type Resolver = (options: ApiRequestOptions) => Promise; type Headers = Record; -type Config = { +export type OpenAPIConfig = { BASE: string; VERSION: string; WITH_CREDENTIALS: boolean; @@ -207,7 +208,7 @@ type Config = { ENCODE_PATH?: (path: string) => string; }; -export const OpenAPI: Config = { +export const OpenAPI: OpenAPIConfig = { BASE: 'http://localhost:3000/base', VERSION: '1.0', WITH_CREDENTIALS: false, @@ -229,21 +230,21 @@ import type { ApiRequestOptions } from './ApiRequestOptions'; import type { ApiResult } from './ApiResult'; import { CancelablePromise } from './CancelablePromise'; import type { OnCancel } from './CancelablePromise'; -import { OpenAPI } from './OpenAPI'; +import type { OpenAPIConfig } from './OpenAPI'; -function isDefined(value: T | null | undefined): value is Exclude { +const isDefined = (value: T | null | undefined): value is Exclude => { return value !== undefined && value !== null; -} +}; -function isString(value: any): value is string { +const isString = (value: any): value is string => { return typeof value === 'string'; -} +}; -function isStringWithValue(value: any): value is string { +const isStringWithValue = (value: any): value is string => { return isString(value) && value !== ''; -} +}; -function isBlob(value: any): value is Blob { +const isBlob = (value: any): value is Blob => { return ( typeof value === 'object' && typeof value.type === 'string' && @@ -254,22 +255,22 @@ function isBlob(value: any): value is Blob { /^(Blob|File)$/.test(value.constructor.name) && /^(Blob|File)$/.test(value[Symbol.toStringTag]) ); -} +}; -function isFormData(value: any): value is FormData { +const isFormData = (value: any): value is FormData => { return value instanceof FormData; -} +}; -function base64(str: string): string { +const base64 = (str: string): string => { try { return btoa(str); } catch (err) { // @ts-ignore return Buffer.from(str).toString('base64'); } -} +}; -function getQueryString(params: Record): string { +const getQueryString = (params: Record): string => { const searchParams = new URLSearchParams(); const process = (key: string, value: any) => { @@ -298,19 +299,28 @@ function getQueryString(params: Record): string { } return ''; -} +}; -function getUrl(options: ApiRequestOptions): string { - const path = OpenAPI.ENCODE_PATH ? OpenAPI.ENCODE_PATH(options.path) : options.path; - const url = \`\${OpenAPI.BASE}\${path}\`; +const getUrl = (config: OpenAPIConfig, options: ApiRequestOptions): string => { + const encoder = config.ENCODE_PATH || encodeURI; + + const path = options.url + .replace('{api-version}', config.VERSION) + .replace(/{(.*?)}/g, (substring: string, group: string) => { + if (options.path?.hasOwnProperty(group)) { + return encoder(String(options.path[group])); + } + return substring; + }); + + const url = \`\${config.BASE}\${path}\`; if (options.query) { return \`\${url}\${getQueryString(options.query)}\`; } - return url; -} +}; -function getFormData(options: ApiRequestOptions): FormData | undefined { +const getFormData = (options: ApiRequestOptions): FormData | undefined => { if (options.formData) { const formData = new FormData(); @@ -335,22 +345,22 @@ function getFormData(options: ApiRequestOptions): FormData | undefined { return formData; } return; -} +}; type Resolver = (options: ApiRequestOptions) => Promise; -async function resolve(options: ApiRequestOptions, resolver?: T | Resolver): Promise { +const resolve = async (options: ApiRequestOptions, resolver?: T | Resolver): Promise => { if (typeof resolver === 'function') { return (resolver as Resolver)(options); } return resolver; -} +}; -async function getHeaders(options: ApiRequestOptions): Promise { - const token = await resolve(options, OpenAPI.TOKEN); - const username = await resolve(options, OpenAPI.USERNAME); - const password = await resolve(options, OpenAPI.PASSWORD); - const additionalHeaders = await resolve(options, OpenAPI.HEADERS); +const getHeaders = async (config: OpenAPIConfig, options: ApiRequestOptions): Promise => { + const token = await resolve(options, config.TOKEN); + const username = await resolve(options, config.USERNAME); + const password = await resolve(options, config.PASSWORD); + const additionalHeaders = await resolve(options, config.HEADERS); const defaultHeaders = Object.entries({ Accept: 'application/json', @@ -387,9 +397,9 @@ async function getHeaders(options: ApiRequestOptions): Promise { } return headers; -} +}; -function getRequestBody(options: ApiRequestOptions): BodyInit | undefined { +const getRequestBody = (options: ApiRequestOptions): BodyInit | undefined => { if (options.body) { if (options.mediaType?.includes('/json')) { return JSON.stringify(options.body) @@ -400,35 +410,36 @@ function getRequestBody(options: ApiRequestOptions): BodyInit | undefined { } } return; -} +}; -async function sendRequest( +export const sendRequest = async ( + config: OpenAPIConfig, options: ApiRequestOptions, url: string, formData: FormData | undefined, body: BodyInit | undefined, headers: Headers, onCancel: OnCancel -): Promise { +): Promise => { const controller = new AbortController(); const request: RequestInit = { headers, - body: body || formData, + body: body ?? formData, method: options.method, signal: controller.signal, }; - if (OpenAPI.WITH_CREDENTIALS) { - request.credentials = OpenAPI.CREDENTIALS; + if (config.WITH_CREDENTIALS) { + request.credentials = config.CREDENTIALS; } onCancel(() => controller.abort()); return await fetch(url, request); -} +}; -function getResponseHeader(response: Response, responseHeader?: string): string | undefined { +const getResponseHeader = (response: Response, responseHeader?: string): string | undefined => { if (responseHeader) { const content = response.headers.get(responseHeader); if (isString(content)) { @@ -436,9 +447,9 @@ function getResponseHeader(response: Response, responseHeader?: string): string } } return; -} +}; -async function getResponseBody(response: Response): Promise { +const getResponseBody = async (response: Response): Promise => { if (response.status !== 204) { try { const contentType = response.headers.get('Content-Type'); @@ -455,9 +466,9 @@ async function getResponseBody(response: Response): Promise { } } return; -} +}; -function catchErrors(options: ApiRequestOptions, result: ApiResult): void { +const catchErrors = (options: ApiRequestOptions, result: ApiResult): void => { const errors: Record = { 400: 'Bad Request', 401: 'Unauthorized', @@ -477,24 +488,25 @@ function catchErrors(options: ApiRequestOptions, result: ApiResult): void { if (!result.ok) { throw new ApiError(result, 'Generic Error'); } -} +}; /** - * Request using fetch client + * Request method + * @param config The OpenAPI configuration object * @param options The request options from the service * @returns CancelablePromise * @throws ApiError */ -export function request(options: ApiRequestOptions): CancelablePromise { +export const request = (config: OpenAPIConfig, options: ApiRequestOptions): CancelablePromise => { return new CancelablePromise(async (resolve, reject, onCancel) => { try { - const url = getUrl(options); + const url = getUrl(config, options); const formData = getFormData(options); const body = getRequestBody(options); - const headers = await getHeaders(options); + const headers = await getHeaders(config, options); if (!onCancel.isCancelled) { - const response = await sendRequest(options, url, formData, body, headers, onCancel); + const response = await sendRequest(config, options, url, formData, body, headers, onCancel); const responseBody = await getResponseBody(response); const responseHeader = getResponseHeader(response, options.responseHeader); @@ -503,7 +515,7 @@ export function request(options: ApiRequestOptions): CancelablePromise { ok: response.ok, status: response.status, statusText: response.statusText, - body: responseHeader || responseBody, + body: responseHeader ?? responseBody, }; catchErrors(options, result); @@ -514,7 +526,7 @@ export function request(options: ApiRequestOptions): CancelablePromise { reject(error); } }); -}" +};" `; exports[`v2 should generate: ./test/generated/v2/index.ts 1`] = ` @@ -524,6 +536,7 @@ exports[`v2 should generate: ./test/generated/v2/index.ts 1`] = ` export { ApiError } from './core/ApiError'; export { CancelablePromise, CancelError } from './core/CancelablePromise'; export { OpenAPI } from './core/OpenAPI'; +export type { OpenAPIConfig } from './core/OpenAPI'; export type { ArrayWithArray } from './models/ArrayWithArray'; export type { ArrayWithBooleans } from './models/ArrayWithBooleans'; @@ -623,6 +636,7 @@ export { $SimpleStringWithPattern } from './schemas/$SimpleStringWithPattern'; export { CollectionFormatService } from './services/CollectionFormatService'; export { ComplexService } from './services/ComplexService'; +export { DefaultService } from './services/DefaultService'; export { DefaultsService } from './services/DefaultsService'; export { DuplicateService } from './services/DuplicateService'; export { ErrorService } from './services/ErrorService'; @@ -2138,17 +2152,17 @@ exports[`v2 should generate: ./test/generated/v2/services/CollectionFormatServic /* tslint:disable */ /* eslint-disable */ import type { CancelablePromise } from '../core/CancelablePromise'; -import { request as __request } from '../core/request'; import { OpenAPI } from '../core/OpenAPI'; +import { request as __request } from '../core/request'; export class CollectionFormatService { /** - * @param parameterArrayCsv This is an array parameter that is send as csv format (comma-separated values) - * @param parameterArraySsv This is an array parameter that is send as ssv format (space-separated values) - * @param parameterArrayTsv This is an array parameter that is send as tsv format (tab-separated values) - * @param parameterArrayPipes This is an array parameter that is send as pipes format (pipe-separated values) - * @param parameterArrayMulti This is an array parameter that is send as multi format (multiple parameter instances) + * @param parameterArrayCsv This is an array parameter that is sent as csv format (comma-separated values) + * @param parameterArraySsv This is an array parameter that is sent as ssv format (space-separated values) + * @param parameterArrayTsv This is an array parameter that is sent as tsv format (tab-separated values) + * @param parameterArrayPipes This is an array parameter that is sent as pipes format (pipe-separated values) + * @param parameterArrayMulti This is an array parameter that is sent as multi format (multiple parameter instances) * @throws ApiError */ public static collectionFormat( @@ -2158,9 +2172,9 @@ export class CollectionFormatService { parameterArrayPipes: Array, parameterArrayMulti: Array, ): CancelablePromise { - return __request({ + return __request(OpenAPI, { method: 'GET', - path: \`/api/v\${OpenAPI.VERSION}/collectionFormat\`, + url: '/api/v{api-version}/collectionFormat', query: { 'parameterArrayCSV': parameterArrayCsv, 'parameterArraySSV': parameterArraySsv, @@ -2180,8 +2194,8 @@ exports[`v2 should generate: ./test/generated/v2/services/ComplexService.ts 1`] /* eslint-disable */ import type { ModelWithString } from '../models/ModelWithString'; import type { CancelablePromise } from '../core/CancelablePromise'; -import { request as __request } from '../core/request'; import { OpenAPI } from '../core/OpenAPI'; +import { request as __request } from '../core/request'; export class ComplexService { @@ -2201,9 +2215,9 @@ export class ComplexService { }, parameterReference: ModelWithString, ): CancelablePromise> { - return __request({ + return __request(OpenAPI, { method: 'GET', - path: \`/api/v\${OpenAPI.VERSION}/complex\`, + url: '/api/v{api-version}/complex', query: { 'parameterObject': parameterObject, 'parameterReference': parameterReference, @@ -2218,14 +2232,37 @@ export class ComplexService { }" `; +exports[`v2 should generate: ./test/generated/v2/services/DefaultService.ts 1`] = ` +"/* istanbul ignore file */ +/* tslint:disable */ +/* eslint-disable */ +import type { CancelablePromise } from '../core/CancelablePromise'; +import { OpenAPI } from '../core/OpenAPI'; +import { request as __request } from '../core/request'; + +export class DefaultService { + + /** + * @throws ApiError + */ + public static serviceWithEmptyTag(): CancelablePromise { + return __request(OpenAPI, { + method: 'GET', + url: '/api/v{api-version}/no-tag', + }); + } + +}" +`; + exports[`v2 should generate: ./test/generated/v2/services/DefaultsService.ts 1`] = ` "/* istanbul ignore file */ /* tslint:disable */ /* eslint-disable */ import type { ModelWithString } from '../models/ModelWithString'; import type { CancelablePromise } from '../core/CancelablePromise'; -import { request as __request } from '../core/request'; import { OpenAPI } from '../core/OpenAPI'; +import { request as __request } from '../core/request'; export class DefaultsService { @@ -2246,9 +2283,9 @@ export class DefaultsService { \\"prop\\": \\"Hello World!\\" }, ): CancelablePromise { - return __request({ + return __request(OpenAPI, { method: 'GET', - path: \`/api/v\${OpenAPI.VERSION}/defaults\`, + url: '/api/v{api-version}/defaults', query: { 'parameterString': parameterString, 'parameterNumber': parameterNumber, @@ -2276,9 +2313,9 @@ export class DefaultsService { \\"prop\\": \\"Hello World!\\" }, ): CancelablePromise { - return __request({ + return __request(OpenAPI, { method: 'POST', - path: \`/api/v\${OpenAPI.VERSION}/defaults\`, + url: '/api/v{api-version}/defaults', query: { 'parameterString': parameterString, 'parameterNumber': parameterNumber, @@ -2310,9 +2347,9 @@ export class DefaultsService { parameterStringNullableWithNoDefault?: string | null, parameterStringNullableWithDefault: string | null = null, ): CancelablePromise { - return __request({ + return __request(OpenAPI, { method: 'PUT', - path: \`/api/v\${OpenAPI.VERSION}/defaults\`, + url: '/api/v{api-version}/defaults', query: { 'parameterOptionalStringWithDefault': parameterOptionalStringWithDefault, 'parameterOptionalStringWithEmptyDefault': parameterOptionalStringWithEmptyDefault, @@ -2334,8 +2371,8 @@ exports[`v2 should generate: ./test/generated/v2/services/DuplicateService.ts 1` /* tslint:disable */ /* eslint-disable */ import type { CancelablePromise } from '../core/CancelablePromise'; -import { request as __request } from '../core/request'; import { OpenAPI } from '../core/OpenAPI'; +import { request as __request } from '../core/request'; export class DuplicateService { @@ -2343,9 +2380,9 @@ export class DuplicateService { * @throws ApiError */ public static duplicateName(): CancelablePromise { - return __request({ + return __request(OpenAPI, { method: 'GET', - path: \`/api/v\${OpenAPI.VERSION}/duplicate\`, + url: '/api/v{api-version}/duplicate', }); } @@ -2353,9 +2390,9 @@ export class DuplicateService { * @throws ApiError */ public static duplicateName1(): CancelablePromise { - return __request({ + return __request(OpenAPI, { method: 'POST', - path: \`/api/v\${OpenAPI.VERSION}/duplicate\`, + url: '/api/v{api-version}/duplicate', }); } @@ -2363,9 +2400,9 @@ export class DuplicateService { * @throws ApiError */ public static duplicateName2(): CancelablePromise { - return __request({ + return __request(OpenAPI, { method: 'PUT', - path: \`/api/v\${OpenAPI.VERSION}/duplicate\`, + url: '/api/v{api-version}/duplicate', }); } @@ -2373,9 +2410,9 @@ export class DuplicateService { * @throws ApiError */ public static duplicateName3(): CancelablePromise { - return __request({ + return __request(OpenAPI, { method: 'DELETE', - path: \`/api/v\${OpenAPI.VERSION}/duplicate\`, + url: '/api/v{api-version}/duplicate', }); } @@ -2387,8 +2424,8 @@ exports[`v2 should generate: ./test/generated/v2/services/ErrorService.ts 1`] = /* tslint:disable */ /* eslint-disable */ import type { CancelablePromise } from '../core/CancelablePromise'; -import { request as __request } from '../core/request'; import { OpenAPI } from '../core/OpenAPI'; +import { request as __request } from '../core/request'; export class ErrorService { @@ -2400,9 +2437,9 @@ export class ErrorService { public static testErrorCode( status: string, ): CancelablePromise { - return __request({ + return __request(OpenAPI, { method: 'POST', - path: \`/api/v\${OpenAPI.VERSION}/error\`, + url: '/api/v{api-version}/error', query: { 'status': status, }, @@ -2423,8 +2460,8 @@ exports[`v2 should generate: ./test/generated/v2/services/HeaderService.ts 1`] = /* tslint:disable */ /* eslint-disable */ import type { CancelablePromise } from '../core/CancelablePromise'; -import { request as __request } from '../core/request'; import { OpenAPI } from '../core/OpenAPI'; +import { request as __request } from '../core/request'; export class HeaderService { @@ -2433,9 +2470,9 @@ export class HeaderService { * @throws ApiError */ public static callWithResultFromHeader(): CancelablePromise { - return __request({ + return __request(OpenAPI, { method: 'POST', - path: \`/api/v\${OpenAPI.VERSION}/header\`, + url: '/api/v{api-version}/header', responseHeader: 'operation-location', errors: { 400: \`400 server error\`, @@ -2452,8 +2489,8 @@ exports[`v2 should generate: ./test/generated/v2/services/MultipleTags1Service.t /* tslint:disable */ /* eslint-disable */ import type { CancelablePromise } from '../core/CancelablePromise'; -import { request as __request } from '../core/request'; import { OpenAPI } from '../core/OpenAPI'; +import { request as __request } from '../core/request'; export class MultipleTags1Service { @@ -2462,9 +2499,9 @@ export class MultipleTags1Service { * @throws ApiError */ public static dummyA(): CancelablePromise { - return __request({ + return __request(OpenAPI, { method: 'GET', - path: \`/api/v\${OpenAPI.VERSION}/multiple-tags/a\`, + url: '/api/v{api-version}/multiple-tags/a', }); } @@ -2473,9 +2510,9 @@ export class MultipleTags1Service { * @throws ApiError */ public static dummyB(): CancelablePromise { - return __request({ + return __request(OpenAPI, { method: 'GET', - path: \`/api/v\${OpenAPI.VERSION}/multiple-tags/b\`, + url: '/api/v{api-version}/multiple-tags/b', }); } @@ -2487,8 +2524,8 @@ exports[`v2 should generate: ./test/generated/v2/services/MultipleTags2Service.t /* tslint:disable */ /* eslint-disable */ import type { CancelablePromise } from '../core/CancelablePromise'; -import { request as __request } from '../core/request'; import { OpenAPI } from '../core/OpenAPI'; +import { request as __request } from '../core/request'; export class MultipleTags2Service { @@ -2497,9 +2534,9 @@ export class MultipleTags2Service { * @throws ApiError */ public static dummyA(): CancelablePromise { - return __request({ + return __request(OpenAPI, { method: 'GET', - path: \`/api/v\${OpenAPI.VERSION}/multiple-tags/a\`, + url: '/api/v{api-version}/multiple-tags/a', }); } @@ -2508,9 +2545,9 @@ export class MultipleTags2Service { * @throws ApiError */ public static dummyB(): CancelablePromise { - return __request({ + return __request(OpenAPI, { method: 'GET', - path: \`/api/v\${OpenAPI.VERSION}/multiple-tags/b\`, + url: '/api/v{api-version}/multiple-tags/b', }); } @@ -2522,8 +2559,8 @@ exports[`v2 should generate: ./test/generated/v2/services/MultipleTags3Service.t /* tslint:disable */ /* eslint-disable */ import type { CancelablePromise } from '../core/CancelablePromise'; -import { request as __request } from '../core/request'; import { OpenAPI } from '../core/OpenAPI'; +import { request as __request } from '../core/request'; export class MultipleTags3Service { @@ -2532,9 +2569,9 @@ export class MultipleTags3Service { * @throws ApiError */ public static dummyB(): CancelablePromise { - return __request({ + return __request(OpenAPI, { method: 'GET', - path: \`/api/v\${OpenAPI.VERSION}/multiple-tags/b\`, + url: '/api/v{api-version}/multiple-tags/b', }); } @@ -2546,8 +2583,8 @@ exports[`v2 should generate: ./test/generated/v2/services/NoContentService.ts 1` /* tslint:disable */ /* eslint-disable */ import type { CancelablePromise } from '../core/CancelablePromise'; -import { request as __request } from '../core/request'; import { OpenAPI } from '../core/OpenAPI'; +import { request as __request } from '../core/request'; export class NoContentService { @@ -2556,9 +2593,9 @@ export class NoContentService { * @throws ApiError */ public static callWithNoContentResponse(): CancelablePromise { - return __request({ + return __request(OpenAPI, { method: 'GET', - path: \`/api/v\${OpenAPI.VERSION}/no-content\`, + url: '/api/v{api-version}/no-content', }); } @@ -2570,8 +2607,8 @@ exports[`v2 should generate: ./test/generated/v2/services/ParametersService.ts 1 /* tslint:disable */ /* eslint-disable */ import type { CancelablePromise } from '../core/CancelablePromise'; -import { request as __request } from '../core/request'; import { OpenAPI } from '../core/OpenAPI'; +import { request as __request } from '../core/request'; export class ParametersService { @@ -2579,7 +2616,7 @@ 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 send as request body + * @param parameterBody This is the parameter that is sent as request body * @param parameterPath This is the parameter that goes into the path * @throws ApiError */ @@ -2590,9 +2627,12 @@ export class ParametersService { parameterBody: string, parameterPath: string, ): CancelablePromise { - return __request({ + return __request(OpenAPI, { method: 'POST', - path: \`/api/v\${OpenAPI.VERSION}/parameters/\${parameterPath}\`, + url: '/api/v{api-version}/parameters/{parameterPath}', + path: { + 'parameterPath': parameterPath, + }, headers: { 'parameterHeader': parameterHeader, }, @@ -2610,7 +2650,7 @@ 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 send as request body + * @param parameterBody This is the parameter that is sent as request body * @param parameterPath1 This is the parameter that goes into the path * @param parameterPath2 This is the parameter that goes into the path * @param parameterPath3 This is the parameter that goes into the path @@ -2627,9 +2667,14 @@ export class ParametersService { parameterPath3?: string, _default?: string, ): CancelablePromise { - return __request({ + return __request(OpenAPI, { method: 'POST', - path: \`/api/v\${OpenAPI.VERSION}/parameters/\${parameterPath1}/\${parameterPath2}/\${parameterPath3}\`, + url: '/api/v{api-version}/parameters/{parameter.path.1}/{parameter-path-2}/{PARAMETER-PATH-3}', + path: { + 'parameter.path.1': parameterPath1, + 'parameter-path-2': parameterPath2, + 'PARAMETER-PATH-3': parameterPath3, + }, headers: { 'parameter.header': parameterHeader, }, @@ -2655,8 +2700,8 @@ import type { ModelThatExtends } from '../models/ModelThatExtends'; import type { ModelThatExtendsExtends } from '../models/ModelThatExtendsExtends'; import type { ModelWithString } from '../models/ModelWithString'; import type { CancelablePromise } from '../core/CancelablePromise'; -import { request as __request } from '../core/request'; import { OpenAPI } from '../core/OpenAPI'; +import { request as __request } from '../core/request'; export class ResponseService { @@ -2665,9 +2710,9 @@ export class ResponseService { * @throws ApiError */ public static callWithResponse(): CancelablePromise { - return __request({ + return __request(OpenAPI, { method: 'GET', - path: \`/api/v\${OpenAPI.VERSION}/response\`, + url: '/api/v{api-version}/response', }); } @@ -2676,9 +2721,9 @@ export class ResponseService { * @throws ApiError */ public static callWithDuplicateResponses(): CancelablePromise { - return __request({ + return __request(OpenAPI, { method: 'POST', - path: \`/api/v\${OpenAPI.VERSION}/response\`, + url: '/api/v{api-version}/response', errors: { 500: \`Message for 500 error\`, 501: \`Message for 501 error\`, @@ -2699,9 +2744,9 @@ export class ResponseService { readonly '@namespace.integer'?: number; readonly value?: Array; } | ModelWithString | ModelThatExtends | ModelThatExtendsExtends> { - return __request({ + return __request(OpenAPI, { method: 'PUT', - path: \`/api/v\${OpenAPI.VERSION}/response\`, + url: '/api/v{api-version}/response', errors: { 500: \`Message for 500 error\`, 501: \`Message for 501 error\`, @@ -2718,8 +2763,8 @@ exports[`v2 should generate: ./test/generated/v2/services/SimpleService.ts 1`] = /* tslint:disable */ /* eslint-disable */ import type { CancelablePromise } from '../core/CancelablePromise'; -import { request as __request } from '../core/request'; import { OpenAPI } from '../core/OpenAPI'; +import { request as __request } from '../core/request'; export class SimpleService { @@ -2727,9 +2772,9 @@ export class SimpleService { * @throws ApiError */ public static getCallWithoutParametersAndResponse(): CancelablePromise { - return __request({ + return __request(OpenAPI, { method: 'GET', - path: \`/api/v\${OpenAPI.VERSION}/simple\`, + url: '/api/v{api-version}/simple', }); } @@ -2737,9 +2782,9 @@ export class SimpleService { * @throws ApiError */ public static putCallWithoutParametersAndResponse(): CancelablePromise { - return __request({ + return __request(OpenAPI, { method: 'PUT', - path: \`/api/v\${OpenAPI.VERSION}/simple\`, + url: '/api/v{api-version}/simple', }); } @@ -2747,9 +2792,9 @@ export class SimpleService { * @throws ApiError */ public static postCallWithoutParametersAndResponse(): CancelablePromise { - return __request({ + return __request(OpenAPI, { method: 'POST', - path: \`/api/v\${OpenAPI.VERSION}/simple\`, + url: '/api/v{api-version}/simple', }); } @@ -2757,9 +2802,9 @@ export class SimpleService { * @throws ApiError */ public static deleteCallWithoutParametersAndResponse(): CancelablePromise { - return __request({ + return __request(OpenAPI, { method: 'DELETE', - path: \`/api/v\${OpenAPI.VERSION}/simple\`, + url: '/api/v{api-version}/simple', }); } @@ -2767,9 +2812,9 @@ export class SimpleService { * @throws ApiError */ public static optionsCallWithoutParametersAndResponse(): CancelablePromise { - return __request({ + return __request(OpenAPI, { method: 'OPTIONS', - path: \`/api/v\${OpenAPI.VERSION}/simple\`, + url: '/api/v{api-version}/simple', }); } @@ -2777,9 +2822,9 @@ export class SimpleService { * @throws ApiError */ public static headCallWithoutParametersAndResponse(): CancelablePromise { - return __request({ + return __request(OpenAPI, { method: 'HEAD', - path: \`/api/v\${OpenAPI.VERSION}/simple\`, + url: '/api/v{api-version}/simple', }); } @@ -2787,9 +2832,9 @@ export class SimpleService { * @throws ApiError */ public static patchCallWithoutParametersAndResponse(): CancelablePromise { - return __request({ + return __request(OpenAPI, { method: 'PATCH', - path: \`/api/v\${OpenAPI.VERSION}/simple\`, + url: '/api/v{api-version}/simple', }); } @@ -2801,8 +2846,8 @@ exports[`v2 should generate: ./test/generated/v2/services/TypesService.ts 1`] = /* tslint:disable */ /* eslint-disable */ import type { CancelablePromise } from '../core/CancelablePromise'; -import { request as __request } from '../core/request'; import { OpenAPI } from '../core/OpenAPI'; +import { request as __request } from '../core/request'; export class TypesService { @@ -2831,9 +2876,12 @@ export class TypesService { parameterObject: any = null, id?: number, ): CancelablePromise { - return __request({ + return __request(OpenAPI, { method: 'GET', - path: \`/api/v\${OpenAPI.VERSION}/types\`, + url: '/api/v{api-version}/types', + path: { + 'id': id, + }, query: { 'parameterNumber': parameterNumber, 'parameterString': parameterString, @@ -2879,7 +2927,8 @@ exports[`v3 should generate: ./test/generated/v3/core/ApiRequestOptions.ts 1`] = /* eslint-disable */ export type ApiRequestOptions = { readonly method: 'GET' | 'PUT' | 'POST' | 'DELETE' | 'OPTIONS' | 'HEAD' | 'PATCH'; - readonly path: string; + readonly url: string; + readonly path?: Record; readonly cookies?: Record; readonly headers?: Record; readonly query?: Record; @@ -3044,7 +3093,7 @@ import type { ApiRequestOptions } from './ApiRequestOptions'; type Resolver = (options: ApiRequestOptions) => Promise; type Headers = Record; -type Config = { +export type OpenAPIConfig = { BASE: string; VERSION: string; WITH_CREDENTIALS: boolean; @@ -3056,7 +3105,7 @@ type Config = { ENCODE_PATH?: (path: string) => string; }; -export const OpenAPI: Config = { +export const OpenAPI: OpenAPIConfig = { BASE: 'http://localhost:3000/base', VERSION: '1.0', WITH_CREDENTIALS: false, @@ -3078,21 +3127,21 @@ import type { ApiRequestOptions } from './ApiRequestOptions'; import type { ApiResult } from './ApiResult'; import { CancelablePromise } from './CancelablePromise'; import type { OnCancel } from './CancelablePromise'; -import { OpenAPI } from './OpenAPI'; +import type { OpenAPIConfig } from './OpenAPI'; -function isDefined(value: T | null | undefined): value is Exclude { +const isDefined = (value: T | null | undefined): value is Exclude => { return value !== undefined && value !== null; -} +}; -function isString(value: any): value is string { +const isString = (value: any): value is string => { return typeof value === 'string'; -} +}; -function isStringWithValue(value: any): value is string { +const isStringWithValue = (value: any): value is string => { return isString(value) && value !== ''; -} +}; -function isBlob(value: any): value is Blob { +const isBlob = (value: any): value is Blob => { return ( typeof value === 'object' && typeof value.type === 'string' && @@ -3103,22 +3152,22 @@ function isBlob(value: any): value is Blob { /^(Blob|File)$/.test(value.constructor.name) && /^(Blob|File)$/.test(value[Symbol.toStringTag]) ); -} +}; -function isFormData(value: any): value is FormData { +const isFormData = (value: any): value is FormData => { return value instanceof FormData; -} +}; -function base64(str: string): string { +const base64 = (str: string): string => { try { return btoa(str); } catch (err) { // @ts-ignore return Buffer.from(str).toString('base64'); } -} +}; -function getQueryString(params: Record): string { +const getQueryString = (params: Record): string => { const searchParams = new URLSearchParams(); const process = (key: string, value: any) => { @@ -3147,19 +3196,28 @@ function getQueryString(params: Record): string { } return ''; -} +}; -function getUrl(options: ApiRequestOptions): string { - const path = OpenAPI.ENCODE_PATH ? OpenAPI.ENCODE_PATH(options.path) : options.path; - const url = \`\${OpenAPI.BASE}\${path}\`; +const getUrl = (config: OpenAPIConfig, options: ApiRequestOptions): string => { + const encoder = config.ENCODE_PATH || encodeURI; + + const path = options.url + .replace('{api-version}', config.VERSION) + .replace(/{(.*?)}/g, (substring: string, group: string) => { + if (options.path?.hasOwnProperty(group)) { + return encoder(String(options.path[group])); + } + return substring; + }); + + const url = \`\${config.BASE}\${path}\`; if (options.query) { return \`\${url}\${getQueryString(options.query)}\`; } - return url; -} +}; -function getFormData(options: ApiRequestOptions): FormData | undefined { +const getFormData = (options: ApiRequestOptions): FormData | undefined => { if (options.formData) { const formData = new FormData(); @@ -3184,22 +3242,22 @@ function getFormData(options: ApiRequestOptions): FormData | undefined { return formData; } return; -} +}; type Resolver = (options: ApiRequestOptions) => Promise; -async function resolve(options: ApiRequestOptions, resolver?: T | Resolver): Promise { +const resolve = async (options: ApiRequestOptions, resolver?: T | Resolver): Promise => { if (typeof resolver === 'function') { return (resolver as Resolver)(options); } return resolver; -} +}; -async function getHeaders(options: ApiRequestOptions): Promise { - const token = await resolve(options, OpenAPI.TOKEN); - const username = await resolve(options, OpenAPI.USERNAME); - const password = await resolve(options, OpenAPI.PASSWORD); - const additionalHeaders = await resolve(options, OpenAPI.HEADERS); +const getHeaders = async (config: OpenAPIConfig, options: ApiRequestOptions): Promise => { + const token = await resolve(options, config.TOKEN); + const username = await resolve(options, config.USERNAME); + const password = await resolve(options, config.PASSWORD); + const additionalHeaders = await resolve(options, config.HEADERS); const defaultHeaders = Object.entries({ Accept: 'application/json', @@ -3236,9 +3294,9 @@ async function getHeaders(options: ApiRequestOptions): Promise { } return headers; -} +}; -function getRequestBody(options: ApiRequestOptions): BodyInit | undefined { +const getRequestBody = (options: ApiRequestOptions): BodyInit | undefined => { if (options.body) { if (options.mediaType?.includes('/json')) { return JSON.stringify(options.body) @@ -3249,35 +3307,36 @@ function getRequestBody(options: ApiRequestOptions): BodyInit | undefined { } } return; -} +}; -async function sendRequest( +export const sendRequest = async ( + config: OpenAPIConfig, options: ApiRequestOptions, url: string, formData: FormData | undefined, body: BodyInit | undefined, headers: Headers, onCancel: OnCancel -): Promise { +): Promise => { const controller = new AbortController(); const request: RequestInit = { headers, - body: body || formData, + body: body ?? formData, method: options.method, signal: controller.signal, }; - if (OpenAPI.WITH_CREDENTIALS) { - request.credentials = OpenAPI.CREDENTIALS; + if (config.WITH_CREDENTIALS) { + request.credentials = config.CREDENTIALS; } onCancel(() => controller.abort()); return await fetch(url, request); -} +}; -function getResponseHeader(response: Response, responseHeader?: string): string | undefined { +const getResponseHeader = (response: Response, responseHeader?: string): string | undefined => { if (responseHeader) { const content = response.headers.get(responseHeader); if (isString(content)) { @@ -3285,9 +3344,9 @@ function getResponseHeader(response: Response, responseHeader?: string): string } } return; -} +}; -async function getResponseBody(response: Response): Promise { +const getResponseBody = async (response: Response): Promise => { if (response.status !== 204) { try { const contentType = response.headers.get('Content-Type'); @@ -3304,9 +3363,9 @@ async function getResponseBody(response: Response): Promise { } } return; -} +}; -function catchErrors(options: ApiRequestOptions, result: ApiResult): void { +const catchErrors = (options: ApiRequestOptions, result: ApiResult): void => { const errors: Record = { 400: 'Bad Request', 401: 'Unauthorized', @@ -3326,24 +3385,25 @@ function catchErrors(options: ApiRequestOptions, result: ApiResult): void { if (!result.ok) { throw new ApiError(result, 'Generic Error'); } -} +}; /** - * Request using fetch client + * Request method + * @param config The OpenAPI configuration object * @param options The request options from the service * @returns CancelablePromise * @throws ApiError */ -export function request(options: ApiRequestOptions): CancelablePromise { +export const request = (config: OpenAPIConfig, options: ApiRequestOptions): CancelablePromise => { return new CancelablePromise(async (resolve, reject, onCancel) => { try { - const url = getUrl(options); + const url = getUrl(config, options); const formData = getFormData(options); const body = getRequestBody(options); - const headers = await getHeaders(options); + const headers = await getHeaders(config, options); if (!onCancel.isCancelled) { - const response = await sendRequest(options, url, formData, body, headers, onCancel); + const response = await sendRequest(config, options, url, formData, body, headers, onCancel); const responseBody = await getResponseBody(response); const responseHeader = getResponseHeader(response, options.responseHeader); @@ -3352,7 +3412,7 @@ export function request(options: ApiRequestOptions): CancelablePromise { ok: response.ok, status: response.status, statusText: response.statusText, - body: responseHeader || responseBody, + body: responseHeader ?? responseBody, }; catchErrors(options, result); @@ -3363,7 +3423,7 @@ export function request(options: ApiRequestOptions): CancelablePromise { reject(error); } }); -}" +};" `; exports[`v3 should generate: ./test/generated/v3/index.ts 1`] = ` @@ -3373,6 +3433,7 @@ exports[`v3 should generate: ./test/generated/v3/index.ts 1`] = ` export { ApiError } from './core/ApiError'; export { CancelablePromise, CancelError } from './core/CancelablePromise'; export { OpenAPI } from './core/OpenAPI'; +export type { OpenAPIConfig } from './core/OpenAPI'; export type { ArrayWithArray } from './models/ArrayWithArray'; export type { ArrayWithBooleans } from './models/ArrayWithBooleans'; @@ -3496,6 +3557,7 @@ export { $SimpleStringWithPattern } from './schemas/$SimpleStringWithPattern'; export { CollectionFormatService } from './services/CollectionFormatService'; export { ComplexService } from './services/ComplexService'; +export { DefaultService } from './services/DefaultService'; export { DefaultsService } from './services/DefaultsService'; export { DuplicateService } from './services/DuplicateService'; export { ErrorService } from './services/ErrorService'; @@ -5564,17 +5626,17 @@ exports[`v3 should generate: ./test/generated/v3/services/CollectionFormatServic /* tslint:disable */ /* eslint-disable */ import type { CancelablePromise } from '../core/CancelablePromise'; -import { request as __request } from '../core/request'; import { OpenAPI } from '../core/OpenAPI'; +import { request as __request } from '../core/request'; export class CollectionFormatService { /** - * @param parameterArrayCsv This is an array parameter that is send as csv format (comma-separated values) - * @param parameterArraySsv This is an array parameter that is send as ssv format (space-separated values) - * @param parameterArrayTsv This is an array parameter that is send as tsv format (tab-separated values) - * @param parameterArrayPipes This is an array parameter that is send as pipes format (pipe-separated values) - * @param parameterArrayMulti This is an array parameter that is send as multi format (multiple parameter instances) + * @param parameterArrayCsv This is an array parameter that is sent as csv format (comma-separated values) + * @param parameterArraySsv This is an array parameter that is sent as ssv format (space-separated values) + * @param parameterArrayTsv This is an array parameter that is sent as tsv format (tab-separated values) + * @param parameterArrayPipes This is an array parameter that is sent as pipes format (pipe-separated values) + * @param parameterArrayMulti This is an array parameter that is sent as multi format (multiple parameter instances) * @throws ApiError */ public static collectionFormat( @@ -5584,9 +5646,9 @@ export class CollectionFormatService { parameterArrayPipes: Array | null, parameterArrayMulti: Array | null, ): CancelablePromise { - return __request({ + return __request(OpenAPI, { method: 'GET', - path: \`/api/v\${OpenAPI.VERSION}/collectionFormat\`, + url: '/api/v{api-version}/collectionFormat', query: { 'parameterArrayCSV': parameterArrayCsv, 'parameterArraySSV': parameterArraySsv, @@ -5609,8 +5671,8 @@ import type { ModelWithDictionary } from '../models/ModelWithDictionary'; import type { ModelWithEnum } from '../models/ModelWithEnum'; import type { ModelWithString } from '../models/ModelWithString'; import type { CancelablePromise } from '../core/CancelablePromise'; -import { request as __request } from '../core/request'; import { OpenAPI } from '../core/OpenAPI'; +import { request as __request } from '../core/request'; export class ComplexService { @@ -5630,9 +5692,9 @@ export class ComplexService { }, parameterReference: ModelWithString, ): CancelablePromise> { - return __request({ + return __request(OpenAPI, { method: 'GET', - path: \`/api/v\${OpenAPI.VERSION}/complex\`, + url: '/api/v{api-version}/complex', query: { 'parameterObject': parameterObject, 'parameterReference': parameterReference, @@ -5666,9 +5728,12 @@ export class ComplexService { }; }, ): CancelablePromise { - return __request({ + return __request(OpenAPI, { method: 'PUT', - path: \`/api/v\${OpenAPI.VERSION}/complex/\${id}\`, + url: '/api/v{api-version}/complex/{id}', + path: { + 'id': id, + }, body: requestBody, mediaType: 'application/json-patch+json', }); @@ -5677,14 +5742,37 @@ export class ComplexService { }" `; +exports[`v3 should generate: ./test/generated/v3/services/DefaultService.ts 1`] = ` +"/* istanbul ignore file */ +/* tslint:disable */ +/* eslint-disable */ +import type { CancelablePromise } from '../core/CancelablePromise'; +import { OpenAPI } from '../core/OpenAPI'; +import { request as __request } from '../core/request'; + +export class DefaultService { + + /** + * @throws ApiError + */ + public static serviceWithEmptyTag(): CancelablePromise { + return __request(OpenAPI, { + method: 'GET', + url: '/api/v{api-version}/no-tag', + }); + } + +}" +`; + exports[`v3 should generate: ./test/generated/v3/services/DefaultsService.ts 1`] = ` "/* istanbul ignore file */ /* tslint:disable */ /* eslint-disable */ import type { ModelWithString } from '../models/ModelWithString'; import type { CancelablePromise } from '../core/CancelablePromise'; -import { request as __request } from '../core/request'; import { OpenAPI } from '../core/OpenAPI'; +import { request as __request } from '../core/request'; export class DefaultsService { @@ -5705,9 +5793,9 @@ export class DefaultsService { \\"prop\\": \\"Hello World!\\" }, ): CancelablePromise { - return __request({ + return __request(OpenAPI, { method: 'GET', - path: \`/api/v\${OpenAPI.VERSION}/defaults\`, + url: '/api/v{api-version}/defaults', query: { 'parameterString': parameterString, 'parameterNumber': parameterNumber, @@ -5735,9 +5823,9 @@ export class DefaultsService { \\"prop\\": \\"Hello World!\\" }, ): CancelablePromise { - return __request({ + return __request(OpenAPI, { method: 'POST', - path: \`/api/v\${OpenAPI.VERSION}/defaults\`, + url: '/api/v{api-version}/defaults', query: { 'parameterString': parameterString, 'parameterNumber': parameterNumber, @@ -5769,9 +5857,9 @@ export class DefaultsService { parameterStringNullableWithNoDefault?: string | null, parameterStringNullableWithDefault: string | null = null, ): CancelablePromise { - return __request({ + return __request(OpenAPI, { method: 'PUT', - path: \`/api/v\${OpenAPI.VERSION}/defaults\`, + url: '/api/v{api-version}/defaults', query: { 'parameterOptionalStringWithDefault': parameterOptionalStringWithDefault, 'parameterOptionalStringWithEmptyDefault': parameterOptionalStringWithEmptyDefault, @@ -5793,8 +5881,8 @@ exports[`v3 should generate: ./test/generated/v3/services/DuplicateService.ts 1` /* tslint:disable */ /* eslint-disable */ import type { CancelablePromise } from '../core/CancelablePromise'; -import { request as __request } from '../core/request'; import { OpenAPI } from '../core/OpenAPI'; +import { request as __request } from '../core/request'; export class DuplicateService { @@ -5802,9 +5890,9 @@ export class DuplicateService { * @throws ApiError */ public static duplicateName(): CancelablePromise { - return __request({ + return __request(OpenAPI, { method: 'GET', - path: \`/api/v\${OpenAPI.VERSION}/duplicate\`, + url: '/api/v{api-version}/duplicate', }); } @@ -5812,9 +5900,9 @@ export class DuplicateService { * @throws ApiError */ public static duplicateName1(): CancelablePromise { - return __request({ + return __request(OpenAPI, { method: 'POST', - path: \`/api/v\${OpenAPI.VERSION}/duplicate\`, + url: '/api/v{api-version}/duplicate', }); } @@ -5822,9 +5910,9 @@ export class DuplicateService { * @throws ApiError */ public static duplicateName2(): CancelablePromise { - return __request({ + return __request(OpenAPI, { method: 'PUT', - path: \`/api/v\${OpenAPI.VERSION}/duplicate\`, + url: '/api/v{api-version}/duplicate', }); } @@ -5832,9 +5920,9 @@ export class DuplicateService { * @throws ApiError */ public static duplicateName3(): CancelablePromise { - return __request({ + return __request(OpenAPI, { method: 'DELETE', - path: \`/api/v\${OpenAPI.VERSION}/duplicate\`, + url: '/api/v{api-version}/duplicate', }); } @@ -5846,8 +5934,8 @@ exports[`v3 should generate: ./test/generated/v3/services/ErrorService.ts 1`] = /* tslint:disable */ /* eslint-disable */ import type { CancelablePromise } from '../core/CancelablePromise'; -import { request as __request } from '../core/request'; import { OpenAPI } from '../core/OpenAPI'; +import { request as __request } from '../core/request'; export class ErrorService { @@ -5859,9 +5947,9 @@ export class ErrorService { public static testErrorCode( status: number, ): CancelablePromise { - return __request({ + return __request(OpenAPI, { method: 'POST', - path: \`/api/v\${OpenAPI.VERSION}/error\`, + url: '/api/v{api-version}/error', query: { 'status': status, }, @@ -5883,8 +5971,8 @@ exports[`v3 should generate: ./test/generated/v3/services/FormDataService.ts 1`] /* eslint-disable */ import type { ModelWithString } from '../models/ModelWithString'; import type { CancelablePromise } from '../core/CancelablePromise'; -import { request as __request } from '../core/request'; import { OpenAPI } from '../core/OpenAPI'; +import { request as __request } from '../core/request'; export class FormDataService { @@ -5893,13 +5981,13 @@ export class FormDataService { * @param formData A reusable request body * @throws ApiError */ - public static postFormData( + public static post( parameter?: string, formData?: ModelWithString, ): CancelablePromise { - return __request({ + return __request(OpenAPI, { method: 'POST', - path: \`/api/v\${OpenAPI.VERSION}/formData/\`, + url: '/api/v{api-version}/formData/', query: { 'parameter': parameter, }, @@ -5916,8 +6004,8 @@ exports[`v3 should generate: ./test/generated/v3/services/HeaderService.ts 1`] = /* tslint:disable */ /* eslint-disable */ import type { CancelablePromise } from '../core/CancelablePromise'; -import { request as __request } from '../core/request'; import { OpenAPI } from '../core/OpenAPI'; +import { request as __request } from '../core/request'; export class HeaderService { @@ -5926,9 +6014,9 @@ export class HeaderService { * @throws ApiError */ public static callWithResultFromHeader(): CancelablePromise { - return __request({ + return __request(OpenAPI, { method: 'POST', - path: \`/api/v\${OpenAPI.VERSION}/header\`, + url: '/api/v{api-version}/header', responseHeader: 'operation-location', errors: { 400: \`400 server error\`, @@ -5946,8 +6034,8 @@ exports[`v3 should generate: ./test/generated/v3/services/MultipartService.ts 1` /* eslint-disable */ import type { ModelWithString } from '../models/ModelWithString'; import type { CancelablePromise } from '../core/CancelablePromise'; -import { request as __request } from '../core/request'; import { OpenAPI } from '../core/OpenAPI'; +import { request as __request } from '../core/request'; export class MultipartService { @@ -5961,9 +6049,9 @@ export class MultipartService { data?: ModelWithString | null; }, ): CancelablePromise { - return __request({ + return __request(OpenAPI, { method: 'POST', - path: \`/api/v\${OpenAPI.VERSION}/multipart\`, + url: '/api/v{api-version}/multipart', formData: formData, mediaType: 'multipart/form-data', }); @@ -5980,9 +6068,9 @@ export class MultipartService { bar?: string; }; }> { - return __request({ + return __request(OpenAPI, { method: 'GET', - path: \`/api/v\${OpenAPI.VERSION}/multipart\`, + url: '/api/v{api-version}/multipart', }); } @@ -5994,8 +6082,8 @@ exports[`v3 should generate: ./test/generated/v3/services/MultipleTags1Service.t /* tslint:disable */ /* eslint-disable */ import type { CancelablePromise } from '../core/CancelablePromise'; -import { request as __request } from '../core/request'; import { OpenAPI } from '../core/OpenAPI'; +import { request as __request } from '../core/request'; export class MultipleTags1Service { @@ -6004,9 +6092,9 @@ export class MultipleTags1Service { * @throws ApiError */ public static dummyA(): CancelablePromise { - return __request({ + return __request(OpenAPI, { method: 'GET', - path: \`/api/v\${OpenAPI.VERSION}/multiple-tags/a\`, + url: '/api/v{api-version}/multiple-tags/a', }); } @@ -6015,9 +6103,9 @@ export class MultipleTags1Service { * @throws ApiError */ public static dummyB(): CancelablePromise { - return __request({ + return __request(OpenAPI, { method: 'GET', - path: \`/api/v\${OpenAPI.VERSION}/multiple-tags/b\`, + url: '/api/v{api-version}/multiple-tags/b', }); } @@ -6029,8 +6117,8 @@ exports[`v3 should generate: ./test/generated/v3/services/MultipleTags2Service.t /* tslint:disable */ /* eslint-disable */ import type { CancelablePromise } from '../core/CancelablePromise'; -import { request as __request } from '../core/request'; import { OpenAPI } from '../core/OpenAPI'; +import { request as __request } from '../core/request'; export class MultipleTags2Service { @@ -6039,9 +6127,9 @@ export class MultipleTags2Service { * @throws ApiError */ public static dummyA(): CancelablePromise { - return __request({ + return __request(OpenAPI, { method: 'GET', - path: \`/api/v\${OpenAPI.VERSION}/multiple-tags/a\`, + url: '/api/v{api-version}/multiple-tags/a', }); } @@ -6050,9 +6138,9 @@ export class MultipleTags2Service { * @throws ApiError */ public static dummyB(): CancelablePromise { - return __request({ + return __request(OpenAPI, { method: 'GET', - path: \`/api/v\${OpenAPI.VERSION}/multiple-tags/b\`, + url: '/api/v{api-version}/multiple-tags/b', }); } @@ -6064,8 +6152,8 @@ exports[`v3 should generate: ./test/generated/v3/services/MultipleTags3Service.t /* tslint:disable */ /* eslint-disable */ import type { CancelablePromise } from '../core/CancelablePromise'; -import { request as __request } from '../core/request'; import { OpenAPI } from '../core/OpenAPI'; +import { request as __request } from '../core/request'; export class MultipleTags3Service { @@ -6074,9 +6162,9 @@ export class MultipleTags3Service { * @throws ApiError */ public static dummyB(): CancelablePromise { - return __request({ + return __request(OpenAPI, { method: 'GET', - path: \`/api/v\${OpenAPI.VERSION}/multiple-tags/b\`, + url: '/api/v{api-version}/multiple-tags/b', }); } @@ -6088,8 +6176,8 @@ exports[`v3 should generate: ./test/generated/v3/services/NoContentService.ts 1` /* tslint:disable */ /* eslint-disable */ import type { CancelablePromise } from '../core/CancelablePromise'; -import { request as __request } from '../core/request'; import { OpenAPI } from '../core/OpenAPI'; +import { request as __request } from '../core/request'; export class NoContentService { @@ -6098,9 +6186,9 @@ export class NoContentService { * @throws ApiError */ public static callWithNoContentResponse(): CancelablePromise { - return __request({ + return __request(OpenAPI, { method: 'GET', - path: \`/api/v\${OpenAPI.VERSION}/no-content\`, + url: '/api/v{api-version}/no-content', }); } @@ -6113,8 +6201,8 @@ exports[`v3 should generate: ./test/generated/v3/services/ParametersService.ts 1 /* eslint-disable */ import type { ModelWithString } from '../models/ModelWithString'; import type { CancelablePromise } from '../core/CancelablePromise'; -import { request as __request } from '../core/request'; import { OpenAPI } from '../core/OpenAPI'; +import { request as __request } from '../core/request'; export class ParametersService { @@ -6135,9 +6223,12 @@ export class ParametersService { parameterPath: string | null, requestBody: ModelWithString | null, ): CancelablePromise { - return __request({ + return __request(OpenAPI, { method: 'POST', - path: \`/api/v\${OpenAPI.VERSION}/parameters/\${parameterPath}\`, + url: '/api/v{api-version}/parameters/{parameterPath}', + path: { + 'parameterPath': parameterPath, + }, cookies: { 'parameterCookie': parameterCookie, }, @@ -6178,9 +6269,14 @@ export class ParametersService { parameterPath3?: string, _default?: string, ): CancelablePromise { - return __request({ + return __request(OpenAPI, { method: 'POST', - path: \`/api/v\${OpenAPI.VERSION}/parameters/\${parameterPath1}/\${parameterPath2}/\${parameterPath3}\`, + url: '/api/v{api-version}/parameters/{parameter.path.1}/{parameter-path-2}/{PARAMETER-PATH-3}', + path: { + 'parameter.path.1': parameterPath1, + 'parameter-path-2': parameterPath2, + 'PARAMETER-PATH-3': parameterPath3, + }, cookies: { 'PARAMETER-COOKIE': parameterCookie, }, @@ -6208,9 +6304,9 @@ export class ParametersService { requestBody: ModelWithString, parameter?: string, ): CancelablePromise { - return __request({ + return __request(OpenAPI, { method: 'GET', - path: \`/api/v\${OpenAPI.VERSION}/parameters/\`, + url: '/api/v{api-version}/parameters/', query: { 'parameter': parameter, }, @@ -6228,9 +6324,9 @@ export class ParametersService { parameter: string, requestBody?: ModelWithString, ): CancelablePromise { - return __request({ + return __request(OpenAPI, { method: 'POST', - path: \`/api/v\${OpenAPI.VERSION}/parameters/\`, + url: '/api/v{api-version}/parameters/', query: { 'parameter': parameter, }, @@ -6248,8 +6344,8 @@ exports[`v3 should generate: ./test/generated/v3/services/RequestBodyService.ts /* eslint-disable */ import type { ModelWithString } from '../models/ModelWithString'; import type { CancelablePromise } from '../core/CancelablePromise'; -import { request as __request } from '../core/request'; import { OpenAPI } from '../core/OpenAPI'; +import { request as __request } from '../core/request'; export class RequestBodyService { @@ -6258,13 +6354,13 @@ export class RequestBodyService { * @param requestBody A reusable request body * @throws ApiError */ - public static postRequestBody( + public static post( parameter?: string, requestBody?: ModelWithString, ): CancelablePromise { - return __request({ + return __request(OpenAPI, { method: 'POST', - path: \`/api/v\${OpenAPI.VERSION}/requestBody/\`, + url: '/api/v{api-version}/requestBody/', query: { 'parameter': parameter, }, @@ -6284,8 +6380,8 @@ import type { ModelThatExtends } from '../models/ModelThatExtends'; import type { ModelThatExtendsExtends } from '../models/ModelThatExtendsExtends'; import type { ModelWithString } from '../models/ModelWithString'; import type { CancelablePromise } from '../core/CancelablePromise'; -import { request as __request } from '../core/request'; import { OpenAPI } from '../core/OpenAPI'; +import { request as __request } from '../core/request'; export class ResponseService { @@ -6294,9 +6390,9 @@ export class ResponseService { * @throws ApiError */ public static callWithResponse(): CancelablePromise { - return __request({ + return __request(OpenAPI, { method: 'GET', - path: \`/api/v\${OpenAPI.VERSION}/response\`, + url: '/api/v{api-version}/response', }); } @@ -6305,9 +6401,9 @@ export class ResponseService { * @throws ApiError */ public static callWithDuplicateResponses(): CancelablePromise { - return __request({ + return __request(OpenAPI, { method: 'POST', - path: \`/api/v\${OpenAPI.VERSION}/response\`, + url: '/api/v{api-version}/response', errors: { 500: \`Message for 500 error\`, 501: \`Message for 501 error\`, @@ -6328,9 +6424,9 @@ export class ResponseService { readonly '@namespace.integer'?: number; readonly value?: Array; } | ModelWithString | ModelThatExtends | ModelThatExtendsExtends> { - return __request({ + return __request(OpenAPI, { method: 'PUT', - path: \`/api/v\${OpenAPI.VERSION}/response\`, + url: '/api/v{api-version}/response', errors: { 500: \`Message for 500 error\`, 501: \`Message for 501 error\`, @@ -6347,8 +6443,8 @@ exports[`v3 should generate: ./test/generated/v3/services/SimpleService.ts 1`] = /* tslint:disable */ /* eslint-disable */ import type { CancelablePromise } from '../core/CancelablePromise'; -import { request as __request } from '../core/request'; import { OpenAPI } from '../core/OpenAPI'; +import { request as __request } from '../core/request'; export class SimpleService { @@ -6356,9 +6452,9 @@ export class SimpleService { * @throws ApiError */ public static getCallWithoutParametersAndResponse(): CancelablePromise { - return __request({ + return __request(OpenAPI, { method: 'GET', - path: \`/api/v\${OpenAPI.VERSION}/simple\`, + url: '/api/v{api-version}/simple', }); } @@ -6366,9 +6462,9 @@ export class SimpleService { * @throws ApiError */ public static putCallWithoutParametersAndResponse(): CancelablePromise { - return __request({ + return __request(OpenAPI, { method: 'PUT', - path: \`/api/v\${OpenAPI.VERSION}/simple\`, + url: '/api/v{api-version}/simple', }); } @@ -6376,9 +6472,9 @@ export class SimpleService { * @throws ApiError */ public static postCallWithoutParametersAndResponse(): CancelablePromise { - return __request({ + return __request(OpenAPI, { method: 'POST', - path: \`/api/v\${OpenAPI.VERSION}/simple\`, + url: '/api/v{api-version}/simple', }); } @@ -6386,9 +6482,9 @@ export class SimpleService { * @throws ApiError */ public static deleteCallWithoutParametersAndResponse(): CancelablePromise { - return __request({ + return __request(OpenAPI, { method: 'DELETE', - path: \`/api/v\${OpenAPI.VERSION}/simple\`, + url: '/api/v{api-version}/simple', }); } @@ -6396,9 +6492,9 @@ export class SimpleService { * @throws ApiError */ public static optionsCallWithoutParametersAndResponse(): CancelablePromise { - return __request({ + return __request(OpenAPI, { method: 'OPTIONS', - path: \`/api/v\${OpenAPI.VERSION}/simple\`, + url: '/api/v{api-version}/simple', }); } @@ -6406,9 +6502,9 @@ export class SimpleService { * @throws ApiError */ public static headCallWithoutParametersAndResponse(): CancelablePromise { - return __request({ + return __request(OpenAPI, { method: 'HEAD', - path: \`/api/v\${OpenAPI.VERSION}/simple\`, + url: '/api/v{api-version}/simple', }); } @@ -6416,9 +6512,9 @@ export class SimpleService { * @throws ApiError */ public static patchCallWithoutParametersAndResponse(): CancelablePromise { - return __request({ + return __request(OpenAPI, { method: 'PATCH', - path: \`/api/v\${OpenAPI.VERSION}/simple\`, + url: '/api/v{api-version}/simple', }); } @@ -6430,8 +6526,8 @@ exports[`v3 should generate: ./test/generated/v3/services/TypesService.ts 1`] = /* tslint:disable */ /* eslint-disable */ import type { CancelablePromise } from '../core/CancelablePromise'; -import { request as __request } from '../core/request'; import { OpenAPI } from '../core/OpenAPI'; +import { request as __request } from '../core/request'; export class TypesService { @@ -6460,9 +6556,12 @@ export class TypesService { parameterObject: any = null, id?: number, ): CancelablePromise { - return __request({ + return __request(OpenAPI, { method: 'GET', - path: \`/api/v\${OpenAPI.VERSION}/types\`, + url: '/api/v{api-version}/types', + path: { + 'id': id, + }, query: { 'parameterNumber': parameterNumber, 'parameterString': parameterString, @@ -6483,8 +6582,8 @@ exports[`v3 should generate: ./test/generated/v3/services/UploadService.ts 1`] = /* tslint:disable */ /* eslint-disable */ import type { CancelablePromise } from '../core/CancelablePromise'; -import { request as __request } from '../core/request'; import { OpenAPI } from '../core/OpenAPI'; +import { request as __request } from '../core/request'; export class UploadService { @@ -6496,9 +6595,9 @@ export class UploadService { public static uploadFile( file: Blob, ): CancelablePromise { - return __request({ + return __request(OpenAPI, { method: 'POST', - path: \`/api/v\${OpenAPI.VERSION}/upload\`, + url: '/api/v{api-version}/upload', formData: { 'file': file, }, diff --git a/test/e2e/client.axios.spec.ts b/test/e2e/client.axios.spec.ts new file mode 100644 index 00000000..3a96ac85 --- /dev/null +++ b/test/e2e/client.axios.spec.ts @@ -0,0 +1,84 @@ +import { compileWithTypescript } from './scripts/compileWithTypescript'; +import { generate } from './scripts/generate'; +import server from './scripts/server'; + +describe('v3.node', () => { + beforeAll(async () => { + await generate('client/axios', 'v3', 'axios', false, false, 'AppClient'); + compileWithTypescript('client/axios'); + await server.start('client/axios'); + }, 30000); + + afterAll(async () => { + await server.stop(); + }); + + it('requests token', async () => { + const { AppClient } = require('./generated/client/axios/index.js'); + const tokenRequest = jest.fn().mockResolvedValue('MY_TOKEN'); + const client = new AppClient({ + TOKEN: tokenRequest, + USERNAME: undefined, + PASSWORD: undefined, + }); + const result = await client.simple.getCallWithoutParametersAndResponse(); + expect(tokenRequest.mock.calls.length).toBe(1); + expect(result.headers.authorization).toBe('Bearer MY_TOKEN'); + }); + + it('uses credentials', async () => { + const { AppClient } = require('./generated/client/axios/index.js'); + const client = new AppClient({ + TOKEN: undefined, + USERNAME: 'username', + PASSWORD: 'password', + }); + const result = await client.simple.getCallWithoutParametersAndResponse(); + expect(result.headers.authorization).toBe('Basic dXNlcm5hbWU6cGFzc3dvcmQ='); + }); + + it('supports complex params', async () => { + const { AppClient } = require('./generated/client/axios/index.js'); + const client = new AppClient(); + const result = await client.complex.complexTypes({ + first: { + second: { + third: 'Hello World!', + }, + }, + }); + expect(result).toBeDefined(); + }); + + it('supports form data', async () => { + const { AppClient } = require('./generated/client/axios/index.js'); + const client = new AppClient(); + const result = await client.parameters.callWithParameters( + 'valueHeader', + 'valueQuery', + 'valueForm', + 'valueCookie', + 'valuePath', + { + prop: 'valueBody', + } + ); + expect(result).toBeDefined(); + }); + + it('can abort the request', async () => { + let error; + try { + const { AppClient } = require('./generated/client/axios/index.js'); + const client = new AppClient(); + const promise = client.simple.getCallWithoutParametersAndResponse(); + setTimeout(() => { + promise.cancel(); + }, 10); + await promise; + } catch (e) { + error = (e as Error).message; + } + expect(error).toContain('Request aborted'); + }); +}); diff --git a/test/e2e/client.babel.spec.ts b/test/e2e/client.babel.spec.ts new file mode 100644 index 00000000..5354f5ec --- /dev/null +++ b/test/e2e/client.babel.spec.ts @@ -0,0 +1,62 @@ +import browser from './scripts/browser'; +import { compileWithBabel } from './scripts/compileWithBabel'; +import { copy } from './scripts/copy'; +import { generate } from './scripts/generate'; +import server from './scripts/server'; + +describe('v3.babel', () => { + beforeAll(async () => { + await generate('client/babel', 'v3', 'fetch', true, true, 'AppClient'); + await copy('client/babel'); + compileWithBabel('client/babel'); + await server.start('client/babel'); + await browser.start(); + }, 30000); + + afterAll(async () => { + await browser.stop(); + await server.stop(); + }); + + it('requests token', async () => { + await browser.exposeFunction('tokenRequest', jest.fn().mockResolvedValue('MY_TOKEN')); + const result = await browser.evaluate(async () => { + const { AppClient } = (window as any).api; + const client = new AppClient({ + TOKEN: (window as any).tokenRequest, + USERNAME: undefined, + PASSWORD: undefined, + }); + return await client.simple.getCallWithoutParametersAndResponse(); + }); + expect(result.headers.authorization).toBe('Bearer MY_TOKEN'); + }); + + it('uses credentials', async () => { + const result = await browser.evaluate(async () => { + const { AppClient } = (window as any).api; + const client = new AppClient({ + TOKEN: undefined, + USERNAME: 'username', + PASSWORD: 'password', + }); + return await client.simple.getCallWithoutParametersAndResponse(); + }); + expect(result.headers.authorization).toBe('Basic dXNlcm5hbWU6cGFzc3dvcmQ='); + }); + + it('supports complex params', async () => { + const result = await browser.evaluate(async () => { + const { AppClient } = (window as any).api; + const client = new AppClient(); + return await client.complex.complexTypes({ + first: { + second: { + third: 'Hello World!', + }, + }, + }); + }); + expect(result).toBeDefined(); + }); +}); diff --git a/test/e2e/client.fetch.spec.ts b/test/e2e/client.fetch.spec.ts new file mode 100644 index 00000000..126030a1 --- /dev/null +++ b/test/e2e/client.fetch.spec.ts @@ -0,0 +1,161 @@ +import browser from './scripts/browser'; +import { compileWithTypescript } from './scripts/compileWithTypescript'; +import { copy } from './scripts/copy'; +import { generate } from './scripts/generate'; +import server from './scripts/server'; + +describe('v3.fetch', () => { + beforeAll(async () => { + await generate('client/fetch', 'v3', 'fetch', false, false, 'AppClient'); + await copy('client/fetch'); + compileWithTypescript('client/fetch'); + await server.start('client/fetch'); + await browser.start(); + }, 30000); + + afterAll(async () => { + await browser.stop(); + await server.stop(); + }); + + it('requests token', async () => { + await browser.exposeFunction('tokenRequest', jest.fn().mockResolvedValue('MY_TOKEN')); + const result = await browser.evaluate(async () => { + const { AppClient } = (window as any).api; + const client = new AppClient({ + TOKEN: (window as any).tokenRequest, + USERNAME: undefined, + PASSWORD: undefined, + }); + return await client.simple.getCallWithoutParametersAndResponse(); + }); + expect(result.headers.authorization).toBe('Bearer MY_TOKEN'); + }); + + it('uses credentials', async () => { + const result = await browser.evaluate(async () => { + const { AppClient } = (window as any).api; + const client = new AppClient({ + TOKEN: undefined, + USERNAME: 'username', + PASSWORD: 'password', + }); + return await client.simple.getCallWithoutParametersAndResponse(); + }); + expect(result.headers.authorization).toBe('Basic dXNlcm5hbWU6cGFzc3dvcmQ='); + }); + + it('supports complex params', async () => { + const result = await browser.evaluate(async () => { + const { AppClient } = (window as any).api; + const client = new AppClient(); + return await client.complex.complexTypes({ + first: { + second: { + third: 'Hello World!', + }, + }, + }); + }); + expect(result).toBeDefined(); + }); + + it('support form data', async () => { + const result = await browser.evaluate(async () => { + const { AppClient } = (window as any).api; + const client = new AppClient(); + return await client.parameters.callWithParameters( + 'valueHeader', + 'valueQuery', + 'valueForm', + 'valueCookie', + 'valuePath', + { + prop: 'valueBody', + } + ); + }); + expect(result).toBeDefined(); + }); + + it('can abort the request', async () => { + let error; + try { + await browser.evaluate(async () => { + const { AppClient } = (window as any).api; + const client = new AppClient(); + const promise = client.simple.getCallWithoutParametersAndResponse(); + setTimeout(() => { + promise.cancel(); + }, 10); + await promise; + }); + } catch (e) { + error = (e as Error).message; + } + expect(error).toContain('CancelError: Request aborted'); + }); + + it('should throw known error (500)', async () => { + const error = await browser.evaluate(async () => { + try { + const { AppClient } = (window as any).api; + const client = new AppClient(); + await client.error.testErrorCode(500); + } catch (e) { + const error = e as any; + return JSON.stringify({ + name: error.name, + message: error.message, + url: error.url, + status: error.status, + statusText: error.statusText, + body: error.body, + }); + } + return; + }); + + expect(error).toBe( + JSON.stringify({ + name: 'ApiError', + message: 'Custom message: Internal Server Error', + url: 'http://localhost:3000/base/api/v1.0/error?status=500', + status: 500, + statusText: 'Internal Server Error', + body: 'Internal Server Error', + }) + ); + }); + + it('should throw unknown error (409)', async () => { + const error = await browser.evaluate(async () => { + try { + const { AppClient } = (window as any).api; + const client = new AppClient(); + await client.error.testErrorCode(409); + } catch (e) { + const error = e as any; + return JSON.stringify({ + name: error.name, + message: error.message, + url: error.url, + status: error.status, + statusText: error.statusText, + body: error.body, + }); + } + return; + }); + expect(error).toBe( + JSON.stringify({ + name: 'ApiError', + message: 'Generic Error', + url: 'http://localhost:3000/base/api/v1.0/error?status=409', + status: 409, + statusText: 'Conflict', + body: 'Conflict', + }) + ); + }); +}); diff --git a/test/e2e/client.node.spec.ts b/test/e2e/client.node.spec.ts new file mode 100644 index 00000000..8ed61d96 --- /dev/null +++ b/test/e2e/client.node.spec.ts @@ -0,0 +1,142 @@ +import { compileWithTypescript } from './scripts/compileWithTypescript'; +import { generate } from './scripts/generate'; +import server from './scripts/server'; + +describe('v3.node', () => { + beforeAll(async () => { + await generate('client/node', 'v3', 'node', false, false, 'AppClient'); + compileWithTypescript('client/node'); + await server.start('client/node'); + }, 30000); + + afterAll(async () => { + await server.stop(); + }); + + it('requests token', async () => { + const { AppClient } = require('./generated/client/node/index.js'); + const tokenRequest = jest.fn().mockResolvedValue('MY_TOKEN'); + const client = new AppClient({ + TOKEN: tokenRequest, + USERNAME: undefined, + PASSWORD: undefined, + }); + const result = await client.simple.getCallWithoutParametersAndResponse(); + expect(tokenRequest.mock.calls.length).toBe(1); + expect(result.headers.authorization).toBe('Bearer MY_TOKEN'); + }); + + it('uses credentials', async () => { + const { AppClient } = require('./generated/client/node/index.js'); + const client = new AppClient({ + TOKEN: undefined, + USERNAME: 'username', + PASSWORD: 'password', + }); + const result = await client.simple.getCallWithoutParametersAndResponse(); + expect(result.headers.authorization).toBe('Basic dXNlcm5hbWU6cGFzc3dvcmQ='); + }); + + it('supports complex params', async () => { + const { AppClient } = require('./generated/client/node/index.js'); + const client = new AppClient(); + const result = await client.complex.complexTypes({ + first: { + second: { + third: 'Hello World!', + }, + }, + }); + expect(result).toBeDefined(); + }); + + it('support form data', async () => { + const { AppClient } = require('./generated/client/node/index.js'); + const client = new AppClient(); + const result = await client.parameters.callWithParameters( + 'valueHeader', + 'valueQuery', + 'valueForm', + 'valueCookie', + 'valuePath', + { + prop: 'valueBody', + } + ); + expect(result).toBeDefined(); + }); + + it('can abort the request', async () => { + let error; + try { + const { AppClient } = require('./generated/client/node/index.js'); + const client = new AppClient(); + const promise = client.simple.getCallWithoutParametersAndResponse(); + setTimeout(() => { + promise.cancel(); + }, 10); + await promise; + } catch (e) { + error = (e as Error).message; + } + expect(error).toContain('Request aborted'); + }); + + it('should throw known error (500)', async () => { + let error; + try { + const { AppClient } = require('./generated/client/node/index.js'); + const client = new AppClient(); + await client.error.testErrorCode(500); + } catch (e) { + const err = e as any; + error = JSON.stringify({ + name: err.name, + message: err.message, + url: err.url, + status: err.status, + statusText: err.statusText, + body: err.body, + }); + } + expect(error).toBe( + JSON.stringify({ + name: 'ApiError', + message: 'Custom message: Internal Server Error', + url: 'http://localhost:3000/base/api/v1.0/error?status=500', + status: 500, + statusText: 'Internal Server Error', + body: 'Internal Server Error', + }) + ); + }); + + it('should throw unknown error (409)', async () => { + let error; + try { + const { AppClient } = require('./generated/client/node/index.js'); + const client = new AppClient(); + await client.error.testErrorCode(409); + } catch (e) { + const err = e as any; + error = JSON.stringify({ + name: err.name, + message: err.message, + url: err.url, + status: err.status, + statusText: err.statusText, + body: err.body, + }); + } + expect(error).toBe( + JSON.stringify({ + name: 'ApiError', + message: 'Generic Error', + url: 'http://localhost:3000/base/api/v1.0/error?status=409', + status: 409, + statusText: 'Conflict', + body: 'Conflict', + }) + ); + }); +}); diff --git a/test/e2e/client.xhr.spec.ts b/test/e2e/client.xhr.spec.ts new file mode 100644 index 00000000..67446c42 --- /dev/null +++ b/test/e2e/client.xhr.spec.ts @@ -0,0 +1,142 @@ +import browser from './scripts/browser'; +import { compileWithTypescript } from './scripts/compileWithTypescript'; +import { copy } from './scripts/copy'; +import { generate } from './scripts/generate'; +import server from './scripts/server'; + +describe('v3.xhr', () => { + beforeAll(async () => { + await generate('client/xhr', 'v3', 'xhr', false, false, 'AppClient'); + await copy('client/xhr'); + compileWithTypescript('client/xhr'); + await server.start('client/xhr'); + await browser.start(); + }, 30000); + + afterAll(async () => { + await browser.stop(); + await server.stop(); + }); + + it('requests token', async () => { + await browser.exposeFunction('tokenRequest', jest.fn().mockResolvedValue('MY_TOKEN')); + const result = await browser.evaluate(async () => { + const { AppClient } = (window as any).api; + const client = new AppClient({ + TOKEN: (window as any).tokenRequest, + USERNAME: undefined, + PASSWORD: undefined, + }); + return await client.simple.getCallWithoutParametersAndResponse(); + }); + expect(result.headers.authorization).toBe('Bearer MY_TOKEN'); + }); + + it('uses credentials', async () => { + const result = await browser.evaluate(async () => { + const { AppClient } = (window as any).api; + const client = new AppClient({ + TOKEN: undefined, + USERNAME: 'username', + PASSWORD: 'password', + }); + return await client.simple.getCallWithoutParametersAndResponse(); + }); + expect(result.headers.authorization).toBe('Basic dXNlcm5hbWU6cGFzc3dvcmQ='); + }); + + it('supports complex params', async () => { + const result = await browser.evaluate(async () => { + const { AppClient } = (window as any).api; + const client = new AppClient(); + return await client.complex.complexTypes({ + first: { + second: { + third: 'Hello World!', + }, + }, + }); + }); + expect(result).toBeDefined(); + }); + + it('can abort the request', async () => { + let error; + try { + await browser.evaluate(async () => { + const { AppClient } = (window as any).api; + const client = new AppClient(); + const promise = client.simple.getCallWithoutParametersAndResponse(); + setTimeout(() => { + promise.cancel(); + }, 10); + await promise; + }); + } catch (e) { + error = (e as Error).message; + } + expect(error).toContain('CancelError: Request aborted'); + }); + + it('should throw known error (500)', async () => { + const error = await browser.evaluate(async () => { + try { + const { AppClient } = (window as any).api; + const client = new AppClient(); + await client.error.testErrorCode(500); + } catch (e) { + const error = e as any; + return JSON.stringify({ + name: error.name, + message: error.message, + url: error.url, + status: error.status, + statusText: error.statusText, + body: error.body, + }); + } + return; + }); + expect(error).toBe( + JSON.stringify({ + name: 'ApiError', + message: 'Custom message: Internal Server Error', + url: 'http://localhost:3000/base/api/v1.0/error?status=500', + status: 500, + statusText: 'Internal Server Error', + body: 'Internal Server Error', + }) + ); + }); + + it('should throw unknown error (409)', async () => { + const error = await browser.evaluate(async () => { + try { + const { AppClient } = (window as any).api; + const client = new AppClient(); + await client.error.testErrorCode(409); + } catch (e) { + const error = e as any; + return JSON.stringify({ + name: error.name, + message: error.message, + url: error.url, + status: error.status, + statusText: error.statusText, + body: error.body, + }); + } + return; + }); + expect(error).toBe( + JSON.stringify({ + name: 'ApiError', + message: 'Generic Error', + url: 'http://localhost:3000/base/api/v1.0/error?status=409', + status: 409, + statusText: 'Conflict', + body: 'Conflict', + }) + ); + }); +}); diff --git a/test/e2e/scripts/generate.ts b/test/e2e/scripts/generate.ts index 31d38d32..3e2794fd 100644 --- a/test/e2e/scripts/generate.ts +++ b/test/e2e/scripts/generate.ts @@ -5,7 +5,8 @@ export const generate = async ( version: string, client: 'fetch' | 'xhr' | 'node' | 'axios', useOptions: boolean = false, - useUnionTypes: boolean = false + useUnionTypes: boolean = false, + clientName?: string ) => { await __generate({ input: `./test/spec/${version}.json`, @@ -13,5 +14,6 @@ export const generate = async ( httpClient: client, useOptions, useUnionTypes, + clientName, }); }; diff --git a/test/index.js b/test/index.js index bcb3b9f5..9ed5fd85 100644 --- a/test/index.js +++ b/test/index.js @@ -14,7 +14,7 @@ const generate = async (input, output) => { exportSchemas: true, exportModels: true, exportServices: true, - clientName: 'AppClient', + // clientName: 'AppClient', // indent: OpenAPI.Indent.SPACE_2, // postfix: 'Api', // request: './test/custom/request.ts', From 016ea82a87bc8b7e2d926d256b3f82025db3007e Mon Sep 17 00:00:00 2001 From: Ferdi Koomen Date: Tue, 25 Jan 2022 15:38:27 +0100 Subject: [PATCH 18/19] - Prepare new version --- CHANGELOG.md | 8 ++ package.json | 10 +- yarn.lock | 356 ++++++++++++++++++--------------------------------- 3 files changed, 137 insertions(+), 237 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index edeb2a4e..0a3ec6ea 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,14 @@ # Changelog All notable changes to this project will be documented in this file. +## [0.16.0] - 2021-01-25 +### Added +- Added option to set the indentation (spaces and tabs) +- Added option to export separate client file that allows usage for multiple backends +### Fixed +- Decoupled OpenAPI object from requests +- Updated dependencies + ## [0.15.0] - 2021-01-24 ### Added - Added change log and releases on GitHub diff --git a/package.json b/package.json index 0008a311..7bcd910b 100644 --- a/package.json +++ b/package.json @@ -79,10 +79,10 @@ "@types/express": "4.17.13", "@types/glob": "7.2.0", "@types/jest": "27.4.0", - "@types/node": "17.0.10", + "@types/node": "17.0.12", "@types/qs": "6.9.7", - "@typescript-eslint/eslint-plugin": "5.10.0", - "@typescript-eslint/parser": "5.10.0", + "@typescript-eslint/eslint-plugin": "5.10.1", + "@typescript-eslint/parser": "5.10.1", "codecov": "3.8.3", "eslint": "8.7.0", "eslint-config-prettier": "8.3.0", @@ -93,10 +93,10 @@ "jest": "27.4.7", "jest-cli": "27.4.7", "prettier": "2.5.1", - "puppeteer": "13.1.1", + "puppeteer": "13.1.2", "qs": "6.10.3", "rimraf": "^3.0.2", - "rollup": "2.66.0", + "rollup": "2.66.1", "rollup-plugin-node-externals": "3.1.2", "rollup-plugin-terser": "7.0.2", "ts-node": "10.4.0", diff --git a/yarn.lock b/yarn.lock index f145c522..5a2496c0 100644 --- a/yarn.lock +++ b/yarn.lock @@ -35,17 +35,12 @@ dependencies: "@babel/highlight" "^7.16.7" -"@babel/compat-data@^7.13.11", "@babel/compat-data@^7.16.4": - version "7.16.4" - resolved "https://registry.yarnpkg.com/@babel/compat-data/-/compat-data-7.16.4.tgz#081d6bbc336ec5c2435c6346b2ae1fb98b5ac68e" - integrity sha512-1o/jo7D+kC9ZjHX5v+EHrdjl3PhxMrLSOTGsOdHJ+KL8HCaEK6ehrVL2RS6oHDZp+L7xLirLrPmQtEng769J/Q== - -"@babel/compat-data@^7.16.8": +"@babel/compat-data@^7.13.11", "@babel/compat-data@^7.16.4", "@babel/compat-data@^7.16.8": version "7.16.8" resolved "https://registry.yarnpkg.com/@babel/compat-data/-/compat-data-7.16.8.tgz#31560f9f29fdf1868de8cb55049538a1b9732a60" integrity sha512-m7OkX0IdKLKPpBlJtF561YJal5y/jyI5fNfWbPxh2D/nbzzGI4qRyrD8xO2jB24u7l+5I2a43scCG2IrfjC50Q== -"@babel/core@7.16.12": +"@babel/core@7.16.12", "@babel/core@^7.1.0", "@babel/core@^7.12.3", "@babel/core@^7.7.2", "@babel/core@^7.8.0": version "7.16.12" resolved "https://registry.yarnpkg.com/@babel/core/-/core-7.16.12.tgz#5edc53c1b71e54881315923ae2aedea2522bb784" integrity sha512-dK5PtG1uiN2ikk++5OzSYsitZKny4wOCD0nrO4TqnW4BVBTQ2NGS3NgilvT/TEyxTST7LNyWV/T4tXDoD3fOgg== @@ -66,37 +61,7 @@ semver "^6.3.0" source-map "^0.5.0" -"@babel/core@^7.1.0", "@babel/core@^7.12.3", "@babel/core@^7.7.2", "@babel/core@^7.8.0": - version "7.16.7" - resolved "https://registry.yarnpkg.com/@babel/core/-/core-7.16.7.tgz#db990f931f6d40cb9b87a0dc7d2adc749f1dcbcf" - integrity sha512-aeLaqcqThRNZYmbMqtulsetOQZ/5gbR/dWruUCJcpas4Qoyy+QeagfDsPdMrqwsPRDNxJvBlRiZxxX7THO7qtA== - dependencies: - "@babel/code-frame" "^7.16.7" - "@babel/generator" "^7.16.7" - "@babel/helper-compilation-targets" "^7.16.7" - "@babel/helper-module-transforms" "^7.16.7" - "@babel/helpers" "^7.16.7" - "@babel/parser" "^7.16.7" - "@babel/template" "^7.16.7" - "@babel/traverse" "^7.16.7" - "@babel/types" "^7.16.7" - convert-source-map "^1.7.0" - debug "^4.1.0" - gensync "^1.0.0-beta.2" - json5 "^2.1.2" - semver "^6.3.0" - source-map "^0.5.0" - -"@babel/generator@^7.16.7", "@babel/generator@^7.7.2": - version "7.16.7" - resolved "https://registry.yarnpkg.com/@babel/generator/-/generator-7.16.7.tgz#b42bf46a3079fa65e1544135f32e7958f048adbb" - integrity sha512-/ST3Sg8MLGY5HVYmrjOgL60ENux/HfO/CsUh7y4MalThufhE/Ff/6EibFDHi4jiDCaWfJKoqbE6oTh21c5hrRg== - dependencies: - "@babel/types" "^7.16.7" - jsesc "^2.5.1" - source-map "^0.5.0" - -"@babel/generator@^7.16.8": +"@babel/generator@^7.16.8", "@babel/generator@^7.7.2": version "7.16.8" resolved "https://registry.yarnpkg.com/@babel/generator/-/generator-7.16.8.tgz#359d44d966b8cd059d543250ce79596f792f2ebe" integrity sha512-1ojZwE9+lOXzcWdWmO6TbUzDfqLD39CmEhN8+2cX9XkDo5yW1OpgfejfliysR2AWLpMamTiOiAp/mtroaymhpw== @@ -130,7 +95,7 @@ browserslist "^4.17.5" semver "^6.3.0" -"@babel/helper-create-class-features-plugin@^7.16.10": +"@babel/helper-create-class-features-plugin@^7.16.10", "@babel/helper-create-class-features-plugin@^7.16.7": version "7.16.10" resolved "https://registry.yarnpkg.com/@babel/helper-create-class-features-plugin/-/helper-create-class-features-plugin-7.16.10.tgz#8a6959b9cc818a88815ba3c5474619e9c0f2c21c" integrity sha512-wDeej0pu3WN/ffTxMNCPW5UCiOav8IcLRxSIyp/9+IF2xJUM9h/OYjg0IJLHaL6F8oU8kqMz9nc1vryXhMsgXg== @@ -143,19 +108,6 @@ "@babel/helper-replace-supers" "^7.16.7" "@babel/helper-split-export-declaration" "^7.16.7" -"@babel/helper-create-class-features-plugin@^7.16.7": - version "7.16.7" - resolved "https://registry.yarnpkg.com/@babel/helper-create-class-features-plugin/-/helper-create-class-features-plugin-7.16.7.tgz#9c5b34b53a01f2097daf10678d65135c1b9f84ba" - integrity sha512-kIFozAvVfK05DM4EVQYKK+zteWvY85BFdGBRQBytRyY3y+6PX0DkDOn/CZ3lEuczCfrCxEzwt0YtP/87YPTWSw== - dependencies: - "@babel/helper-annotate-as-pure" "^7.16.7" - "@babel/helper-environment-visitor" "^7.16.7" - "@babel/helper-function-name" "^7.16.7" - "@babel/helper-member-expression-to-functions" "^7.16.7" - "@babel/helper-optimise-call-expression" "^7.16.7" - "@babel/helper-replace-supers" "^7.16.7" - "@babel/helper-split-export-declaration" "^7.16.7" - "@babel/helper-create-regexp-features-plugin@^7.16.7": version "7.16.7" resolved "https://registry.yarnpkg.com/@babel/helper-create-regexp-features-plugin/-/helper-create-regexp-features-plugin-7.16.7.tgz#0cb82b9bac358eb73bfbd73985a776bfa6b14d48" @@ -164,20 +116,6 @@ "@babel/helper-annotate-as-pure" "^7.16.7" regexpu-core "^4.7.1" -"@babel/helper-define-polyfill-provider@^0.3.0": - version "0.3.0" - resolved "https://registry.yarnpkg.com/@babel/helper-define-polyfill-provider/-/helper-define-polyfill-provider-0.3.0.tgz#c5b10cf4b324ff840140bb07e05b8564af2ae971" - integrity sha512-7hfT8lUljl/tM3h+izTX/pO3W3frz2ok6Pk+gzys8iJqDfZrZy2pXjRTZAvG2YmfHun1X4q8/UZRLatMfqc5Tg== - dependencies: - "@babel/helper-compilation-targets" "^7.13.0" - "@babel/helper-module-imports" "^7.12.13" - "@babel/helper-plugin-utils" "^7.13.0" - "@babel/traverse" "^7.13.0" - debug "^4.1.1" - lodash.debounce "^4.0.8" - resolve "^1.14.2" - semver "^6.1.2" - "@babel/helper-define-polyfill-provider@^0.3.1": version "0.3.1" resolved "https://registry.yarnpkg.com/@babel/helper-define-polyfill-provider/-/helper-define-polyfill-provider-0.3.1.tgz#52411b445bdb2e676869e5a74960d2d3826d2665" @@ -340,20 +278,15 @@ "@babel/types" "^7.16.7" "@babel/highlight@^7.16.7": - version "7.16.7" - resolved "https://registry.yarnpkg.com/@babel/highlight/-/highlight-7.16.7.tgz#81a01d7d675046f0d96f82450d9d9578bdfd6b0b" - integrity sha512-aKpPMfLvGO3Q97V0qhw/V2SWNWlwfJknuwAunU7wZLSfrM4xTBvg7E5opUVi1kJTBKihE38CPg4nBiqX83PWYw== + version "7.16.10" + resolved "https://registry.yarnpkg.com/@babel/highlight/-/highlight-7.16.10.tgz#744f2eb81579d6eea753c227b0f570ad785aba88" + integrity sha512-5FnTQLSLswEj6IkgVw5KusNUUFY9ZGqe/TRFnP/BKYHYgfh7tc+C7mwiy95/yNP7Dh9x580Vv8r7u7ZfTBFxdw== dependencies: "@babel/helper-validator-identifier" "^7.16.7" chalk "^2.0.0" js-tokens "^4.0.0" -"@babel/parser@^7.1.0", "@babel/parser@^7.14.7", "@babel/parser@^7.16.7": - version "7.16.7" - resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.16.7.tgz#d372dda9c89fcec340a82630a9f533f2fe15877e" - integrity sha512-sR4eaSrnM7BV7QPzGfEX5paG/6wrZM3I0HDzfIAK06ESvo9oy3xBuVBxE3MbQaKNhvg8g/ixjMWo2CGpzpHsDA== - -"@babel/parser@^7.16.10", "@babel/parser@^7.16.12": +"@babel/parser@^7.1.0", "@babel/parser@^7.14.7", "@babel/parser@^7.16.10", "@babel/parser@^7.16.12", "@babel/parser@^7.16.7": version "7.16.12" resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.16.12.tgz#9474794f9a650cf5e2f892444227f98e28cdf8b6" integrity sha512-VfaV15po8RiZssrkPweyvbGVSe4x2y+aciFCgn0n0/SJMR22cwofRV1mtnJQYcSB1wUTaA/X1LnA3es66MCO5A== @@ -857,9 +790,9 @@ "@babel/helper-plugin-utils" "^7.16.7" "@babel/plugin-transform-typescript@^7.16.7": - version "7.16.7" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-typescript/-/plugin-transform-typescript-7.16.7.tgz#33f8c2c890fbfdc4ef82446e9abb8de8211a3ff3" - integrity sha512-Hzx1lvBtOCWuCEwMmYOfpQpO7joFeXLgoPuzZZBtTxXqSqUGUubvFGZv2ygo1tB5Bp9q6PXV3H0E/kf7KM0RLA== + version "7.16.8" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-typescript/-/plugin-transform-typescript-7.16.8.tgz#591ce9b6b83504903fa9dd3652c357c2ba7a1ee0" + integrity sha512-bHdQ9k7YpBDO2d0NVfkj51DpQcvwIzIusJ7mEUaMlbZq3Kt/U47j24inXZHQ5MDiYpCs+oZiwnXyKedE8+q7AQ== dependencies: "@babel/helper-create-class-features-plugin" "^7.16.7" "@babel/helper-plugin-utils" "^7.16.7" @@ -996,23 +929,7 @@ "@babel/parser" "^7.16.7" "@babel/types" "^7.16.7" -"@babel/traverse@^7.13.0", "@babel/traverse@^7.16.7", "@babel/traverse@^7.7.2": - version "7.16.7" - resolved "https://registry.yarnpkg.com/@babel/traverse/-/traverse-7.16.7.tgz#dac01236a72c2560073658dd1a285fe4e0865d76" - integrity sha512-8KWJPIb8c2VvY8AJrydh6+fVRo2ODx1wYBU2398xJVq0JomuLBZmVQzLPBblJgHIGYG4znCpUZUZ0Pt2vdmVYQ== - dependencies: - "@babel/code-frame" "^7.16.7" - "@babel/generator" "^7.16.7" - "@babel/helper-environment-visitor" "^7.16.7" - "@babel/helper-function-name" "^7.16.7" - "@babel/helper-hoist-variables" "^7.16.7" - "@babel/helper-split-export-declaration" "^7.16.7" - "@babel/parser" "^7.16.7" - "@babel/types" "^7.16.7" - debug "^4.1.0" - globals "^11.1.0" - -"@babel/traverse@^7.16.10", "@babel/traverse@^7.16.8": +"@babel/traverse@^7.13.0", "@babel/traverse@^7.16.10", "@babel/traverse@^7.16.7", "@babel/traverse@^7.16.8", "@babel/traverse@^7.7.2": version "7.16.10" resolved "https://registry.yarnpkg.com/@babel/traverse/-/traverse-7.16.10.tgz#448f940defbe95b5a8029975b051f75993e8239f" integrity sha512-yzuaYXoRJBGMlBhsMJoUW7G1UmSb/eXr/JHYM/MsOJgavJibLwASijW7oXBdw3NQ6T0bW7Ty5P/VarOs9cHmqw== @@ -1028,15 +945,7 @@ debug "^4.1.0" globals "^11.1.0" -"@babel/types@^7.0.0", "@babel/types@^7.16.0", "@babel/types@^7.16.7", "@babel/types@^7.3.0", "@babel/types@^7.3.3", "@babel/types@^7.4.4": - version "7.16.7" - resolved "https://registry.yarnpkg.com/@babel/types/-/types-7.16.7.tgz#4ed19d51f840ed4bd5645be6ce40775fecf03159" - integrity sha512-E8HuV7FO9qLpx6OtoGfUQ2cjIYnbFwvZWYBS+87EwtdMvmUPJSwykpovFB+8insbpF0uJcpr8KMUi64XZntZcg== - dependencies: - "@babel/helper-validator-identifier" "^7.16.7" - to-fast-properties "^2.0.0" - -"@babel/types@^7.16.8": +"@babel/types@^7.0.0", "@babel/types@^7.16.0", "@babel/types@^7.16.7", "@babel/types@^7.16.8", "@babel/types@^7.3.0", "@babel/types@^7.3.3", "@babel/types@^7.4.4": version "7.16.8" resolved "https://registry.yarnpkg.com/@babel/types/-/types-7.16.8.tgz#0ba5da91dd71e0a4e7781a30f22770831062e3c1" integrity sha512-smN2DQc5s4M7fntyjGtyIPbRJv6wW4rU/94fmYJ7PKQuZkC0qGMHXJbg6sNGt12JmVr4k5YaptI/XtiLJBnmIg== @@ -1446,9 +1355,9 @@ integrity sha512-EYNwp3bU+98cpU4lAWYYL7Zz+2gryWH1qbdDTidVd6hkiR6weksdbMadyXKXNPEkQFhXM+hVO9ZygomHXp+AIw== "@types/express-serve-static-core@^4.17.18": - version "4.17.27" - resolved "https://registry.yarnpkg.com/@types/express-serve-static-core/-/express-serve-static-core-4.17.27.tgz#7a776191e47295d2a05962ecbb3a4ce97e38b401" - integrity sha512-e/sVallzUTPdyOTiqi8O8pMdBBphscvI6E4JYaKlja4Lm+zh7UFSSdW5VMkRbhDtmrONqOUHOXRguPsDckzxNA== + version "4.17.28" + resolved "https://registry.yarnpkg.com/@types/express-serve-static-core/-/express-serve-static-core-4.17.28.tgz#c47def9f34ec81dc6328d0b1b5303d1ec98d86b8" + integrity sha512-P1BJAEAW3E2DJUlkgq4tOL3RyMunoWXqbSCygWo5ZIWTjUgN1YnaXWW4VWl/oc8vs/XoYibEGBKP0uZyF4AHig== dependencies: "@types/node" "*" "@types/qs" "*" @@ -1529,20 +1438,15 @@ "@types/node" "*" form-data "^3.0.0" -"@types/node@*": - version "17.0.8" - resolved "https://registry.yarnpkg.com/@types/node/-/node-17.0.8.tgz#50d680c8a8a78fe30abe6906453b21ad8ab0ad7b" - integrity sha512-YofkM6fGv4gDJq78g4j0mMuGMkZVxZDgtU0JRdx6FgiJDG+0fY0GKVolOV8WqVmEhLCXkQRjwDdKyPxJp/uucg== - -"@types/node@17.0.10": - version "17.0.10" - resolved "https://registry.yarnpkg.com/@types/node/-/node-17.0.10.tgz#616f16e9d3a2a3d618136b1be244315d95bd7cab" - integrity sha512-S/3xB4KzyFxYGCppyDt68yzBU9ysL88lSdIah4D6cptdcltc4NCPCAMc0+PCpg/lLIyC7IPvj2Z52OJWeIUkog== +"@types/node@*", "@types/node@17.0.12": + version "17.0.12" + resolved "https://registry.yarnpkg.com/@types/node/-/node-17.0.12.tgz#f7aa331b27f08244888c47b7df126184bc2339c5" + integrity sha512-4YpbAsnJXWYK/fpTVFlMIcUIho2AYCi4wg5aNPrG1ng7fn/1/RZfCIpRCiBX+12RVa34RluilnvCqD+g3KiSiA== "@types/prettier@^2.1.5": - version "2.4.2" - resolved "https://registry.yarnpkg.com/@types/prettier/-/prettier-2.4.2.tgz#4c62fae93eb479660c3bd93f9d24d561597a8281" - integrity sha512-ekoj4qOQYp7CvjX8ZDBgN86w3MqQhLE1hczEJbEIjgFEumDy+na/4AJAbLXfgEWFNB2pKadM5rPFtuSGMWK7xA== + version "2.4.3" + resolved "https://registry.yarnpkg.com/@types/prettier/-/prettier-2.4.3.tgz#a3c65525b91fca7da00ab1a3ac2b5a2a4afbffbf" + integrity sha512-QzSuZMBuG5u8HqYz01qtMdg/Jfctlnvj1z/lYnIDXs/golxw0fxtRAHd9KrzjR7Yxz1qVeI00o0kiO3PmVdJ9w== "@types/qs@*", "@types/qs@6.9.7": version "6.9.7" @@ -1593,14 +1497,14 @@ dependencies: "@types/node" "*" -"@typescript-eslint/eslint-plugin@5.10.0": - version "5.10.0" - resolved "https://registry.yarnpkg.com/@typescript-eslint/eslint-plugin/-/eslint-plugin-5.10.0.tgz#e90afea96dff8620892ad216b0e4ccdf8ee32d3a" - integrity sha512-XXVKnMsq2fuu9K2KsIxPUGqb6xAImz8MEChClbXmE3VbveFtBUU5bzM6IPVWqzyADIgdkS2Ws/6Xo7W2TeZWjQ== +"@typescript-eslint/eslint-plugin@5.10.1": + version "5.10.1" + resolved "https://registry.yarnpkg.com/@typescript-eslint/eslint-plugin/-/eslint-plugin-5.10.1.tgz#870195d0f2146b36d11fc71131b75aba52354c69" + integrity sha512-xN3CYqFlyE/qOcy978/L0xLR2HlcAGIyIK5sMOasxaaAPfQRj/MmMV6OC3I7NZO84oEUdWCOju34Z9W8E0pFDQ== dependencies: - "@typescript-eslint/scope-manager" "5.10.0" - "@typescript-eslint/type-utils" "5.10.0" - "@typescript-eslint/utils" "5.10.0" + "@typescript-eslint/scope-manager" "5.10.1" + "@typescript-eslint/type-utils" "5.10.1" + "@typescript-eslint/utils" "5.10.1" debug "^4.3.2" functional-red-black-tree "^1.0.1" ignore "^5.1.8" @@ -1608,69 +1512,69 @@ semver "^7.3.5" tsutils "^3.21.0" -"@typescript-eslint/parser@5.10.0": - version "5.10.0" - resolved "https://registry.yarnpkg.com/@typescript-eslint/parser/-/parser-5.10.0.tgz#8f59e036f5f1cffc178cacbd5ccdd02aeb96c91c" - integrity sha512-pJB2CCeHWtwOAeIxv8CHVGJhI5FNyJAIpx5Pt72YkK3QfEzt6qAlXZuyaBmyfOdM62qU0rbxJzNToPTVeJGrQw== +"@typescript-eslint/parser@5.10.1": + version "5.10.1" + resolved "https://registry.yarnpkg.com/@typescript-eslint/parser/-/parser-5.10.1.tgz#4ce9633cc33fc70bc13786cb793c1a76fe5ad6bd" + integrity sha512-GReo3tjNBwR5RnRO0K2wDIDN31cM3MmDtgyQ85oAxAmC5K3j/g85IjP+cDfcqDsDDBf1HNKQAD0WqOYL8jXqUA== dependencies: - "@typescript-eslint/scope-manager" "5.10.0" - "@typescript-eslint/types" "5.10.0" - "@typescript-eslint/typescript-estree" "5.10.0" + "@typescript-eslint/scope-manager" "5.10.1" + "@typescript-eslint/types" "5.10.1" + "@typescript-eslint/typescript-estree" "5.10.1" debug "^4.3.2" -"@typescript-eslint/scope-manager@5.10.0": - version "5.10.0" - resolved "https://registry.yarnpkg.com/@typescript-eslint/scope-manager/-/scope-manager-5.10.0.tgz#bb5d872e8b9e36203908595507fbc4d3105329cb" - integrity sha512-tgNgUgb4MhqK6DoKn3RBhyZ9aJga7EQrw+2/OiDk5hKf3pTVZWyqBi7ukP+Z0iEEDMF5FDa64LqODzlfE4O/Dg== +"@typescript-eslint/scope-manager@5.10.1": + version "5.10.1" + resolved "https://registry.yarnpkg.com/@typescript-eslint/scope-manager/-/scope-manager-5.10.1.tgz#f0539c73804d2423506db2475352a4dec36cd809" + integrity sha512-Lyvi559Gvpn94k7+ElXNMEnXu/iundV5uFmCUNnftbFrUbAJ1WBoaGgkbOBm07jVZa682oaBU37ao/NGGX4ZDg== dependencies: - "@typescript-eslint/types" "5.10.0" - "@typescript-eslint/visitor-keys" "5.10.0" + "@typescript-eslint/types" "5.10.1" + "@typescript-eslint/visitor-keys" "5.10.1" -"@typescript-eslint/type-utils@5.10.0": - version "5.10.0" - resolved "https://registry.yarnpkg.com/@typescript-eslint/type-utils/-/type-utils-5.10.0.tgz#8524b9479c19c478347a7df216827e749e4a51e5" - integrity sha512-TzlyTmufJO5V886N+hTJBGIfnjQDQ32rJYxPaeiyWKdjsv2Ld5l8cbS7pxim4DeNs62fKzRSt8Q14Evs4JnZyQ== +"@typescript-eslint/type-utils@5.10.1": + version "5.10.1" + resolved "https://registry.yarnpkg.com/@typescript-eslint/type-utils/-/type-utils-5.10.1.tgz#5e526c00142585e40ab1503e83f1ff608c367405" + integrity sha512-AfVJkV8uck/UIoDqhu+ptEdBoQATON9GXnhOpPLzkQRJcSChkvD//qsz9JVffl2goxX+ybs5klvacE9vmrQyCw== dependencies: - "@typescript-eslint/utils" "5.10.0" + "@typescript-eslint/utils" "5.10.1" debug "^4.3.2" tsutils "^3.21.0" -"@typescript-eslint/types@5.10.0": - version "5.10.0" - resolved "https://registry.yarnpkg.com/@typescript-eslint/types/-/types-5.10.0.tgz#beb3cb345076f5b088afe996d57bcd1dfddaa75c" - integrity sha512-wUljCgkqHsMZbw60IbOqT/puLfyqqD5PquGiBo1u1IS3PLxdi3RDGlyf032IJyh+eQoGhz9kzhtZa+VC4eWTlQ== +"@typescript-eslint/types@5.10.1": + version "5.10.1" + resolved "https://registry.yarnpkg.com/@typescript-eslint/types/-/types-5.10.1.tgz#dca9bd4cb8c067fc85304a31f38ec4766ba2d1ea" + integrity sha512-ZvxQ2QMy49bIIBpTqFiOenucqUyjTQ0WNLhBM6X1fh1NNlYAC6Kxsx8bRTY3jdYsYg44a0Z/uEgQkohbR0H87Q== -"@typescript-eslint/typescript-estree@5.10.0": - version "5.10.0" - resolved "https://registry.yarnpkg.com/@typescript-eslint/typescript-estree/-/typescript-estree-5.10.0.tgz#4be24a3dea0f930bb1397c46187d0efdd955a224" - integrity sha512-x+7e5IqfwLwsxTdliHRtlIYkgdtYXzE0CkFeV6ytAqq431ZyxCFzNMNR5sr3WOlIG/ihVZr9K/y71VHTF/DUQA== +"@typescript-eslint/typescript-estree@5.10.1": + version "5.10.1" + resolved "https://registry.yarnpkg.com/@typescript-eslint/typescript-estree/-/typescript-estree-5.10.1.tgz#b268e67be0553f8790ba3fe87113282977adda15" + integrity sha512-PwIGnH7jIueXv4opcwEbVGDATjGPO1dx9RkUl5LlHDSe+FXxPwFL5W/qYd5/NHr7f6lo/vvTrAzd0KlQtRusJQ== dependencies: - "@typescript-eslint/types" "5.10.0" - "@typescript-eslint/visitor-keys" "5.10.0" + "@typescript-eslint/types" "5.10.1" + "@typescript-eslint/visitor-keys" "5.10.1" debug "^4.3.2" globby "^11.0.4" is-glob "^4.0.3" semver "^7.3.5" tsutils "^3.21.0" -"@typescript-eslint/utils@5.10.0": - version "5.10.0" - resolved "https://registry.yarnpkg.com/@typescript-eslint/utils/-/utils-5.10.0.tgz#c3d152a85da77c400e37281355561c72fb1b5a65" - integrity sha512-IGYwlt1CVcFoE2ueW4/ioEwybR60RAdGeiJX/iDAw0t5w0wK3S7QncDwpmsM70nKgGTuVchEWB8lwZwHqPAWRg== +"@typescript-eslint/utils@5.10.1": + version "5.10.1" + resolved "https://registry.yarnpkg.com/@typescript-eslint/utils/-/utils-5.10.1.tgz#fa682a33af47080ba2c4368ee0ad2128213a1196" + integrity sha512-RRmlITiUbLuTRtn/gcPRi4202niF+q7ylFLCKu4c+O/PcpRvZ/nAUwQ2G00bZgpWkhrNLNnvhZLbDn8Ml0qsQw== dependencies: "@types/json-schema" "^7.0.9" - "@typescript-eslint/scope-manager" "5.10.0" - "@typescript-eslint/types" "5.10.0" - "@typescript-eslint/typescript-estree" "5.10.0" + "@typescript-eslint/scope-manager" "5.10.1" + "@typescript-eslint/types" "5.10.1" + "@typescript-eslint/typescript-estree" "5.10.1" eslint-scope "^5.1.1" eslint-utils "^3.0.0" -"@typescript-eslint/visitor-keys@5.10.0": - version "5.10.0" - resolved "https://registry.yarnpkg.com/@typescript-eslint/visitor-keys/-/visitor-keys-5.10.0.tgz#770215497ad67cd15a572b52089991d5dfe06281" - integrity sha512-GMxj0K1uyrFLPKASLmZzCuSddmjZVbVj3Ouy5QVuIGKZopxvOr24JsS7gruz6C3GExE01mublZ3mIBOaon9zuQ== +"@typescript-eslint/visitor-keys@5.10.1": + version "5.10.1" + resolved "https://registry.yarnpkg.com/@typescript-eslint/visitor-keys/-/visitor-keys-5.10.1.tgz#29102de692f59d7d34ecc457ed59ab5fc558010b" + integrity sha512-NjQ0Xinhy9IL979tpoTRuLKxMc0zJC7QVSdeerXs2/QvOy2yRkzX5dRb10X5woNUdJgU8G3nYRDlI33sq1K4YQ== dependencies: - "@typescript-eslint/types" "5.10.0" + "@typescript-eslint/types" "5.10.1" eslint-visitor-keys "^3.0.0" abab@^2.0.3, abab@^2.0.5: @@ -1869,12 +1773,12 @@ babel-plugin-jest-hoist@^27.4.0: "@types/babel__traverse" "^7.0.6" babel-plugin-polyfill-corejs2@^0.3.0: - version "0.3.0" - resolved "https://registry.yarnpkg.com/babel-plugin-polyfill-corejs2/-/babel-plugin-polyfill-corejs2-0.3.0.tgz#407082d0d355ba565af24126fb6cb8e9115251fd" - integrity sha512-wMDoBJ6uG4u4PNFh72Ty6t3EgfA91puCuAwKIazbQlci+ENb/UU9A3xG5lutjUIiXCIn1CY5L15r9LimiJyrSA== + version "0.3.1" + resolved "https://registry.yarnpkg.com/babel-plugin-polyfill-corejs2/-/babel-plugin-polyfill-corejs2-0.3.1.tgz#440f1b70ccfaabc6b676d196239b138f8a2cfba5" + integrity sha512-v7/T6EQcNfVLfcN2X8Lulb7DjprieyLWJK/zOWH5DUYcAgex9sP3h25Q+DLsX9TloXe3y1O8l2q2Jv9q8UVB9w== dependencies: "@babel/compat-data" "^7.13.11" - "@babel/helper-define-polyfill-provider" "^0.3.0" + "@babel/helper-define-polyfill-provider" "^0.3.1" semver "^6.1.1" babel-plugin-polyfill-corejs3@^0.5.0: @@ -1886,11 +1790,11 @@ babel-plugin-polyfill-corejs3@^0.5.0: core-js-compat "^3.20.0" babel-plugin-polyfill-regenerator@^0.3.0: - version "0.3.0" - resolved "https://registry.yarnpkg.com/babel-plugin-polyfill-regenerator/-/babel-plugin-polyfill-regenerator-0.3.0.tgz#9ebbcd7186e1a33e21c5e20cae4e7983949533be" - integrity sha512-dhAPTDLGoMW5/84wkgwiLRwMnio2i1fUe53EuvtKMv0pn2p3S8OCoV1xAzfJPl0KOX7IB89s2ib85vbYiea3jg== + version "0.3.1" + resolved "https://registry.yarnpkg.com/babel-plugin-polyfill-regenerator/-/babel-plugin-polyfill-regenerator-0.3.1.tgz#2c0678ea47c75c8cc2fbb1852278d8fb68233990" + integrity sha512-Y2B06tvgHYt1x0yz17jGkGeeMr5FeKUu+ASJ+N6nB5lQ8Dapfg42i0OVrf8PNGJ3zKL4A23snMi1IRwrqqND7A== dependencies: - "@babel/helper-define-polyfill-provider" "^0.3.0" + "@babel/helper-define-polyfill-provider" "^0.3.1" babel-preset-current-node-syntax@^1.0.0: version "1.0.1" @@ -2053,9 +1957,9 @@ camelcase@^6.2.0, camelcase@^6.3.0: integrity sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA== caniuse-lite@^1.0.30001286: - version "1.0.30001296" - resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001296.tgz#d99f0f3bee66544800b93d261c4be55a35f1cec8" - integrity sha512-WfrtPEoNSoeATDlf4y3QvkwiELl9GyPLISV5GejTbbQRtQx4LhsXmc9IQ6XCL2d7UxCyEzToEZNMeqR79OUw8Q== + version "1.0.30001301" + resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001301.tgz#ebc9086026534cab0dab99425d9c3b4425e5f450" + integrity sha512-csfD/GpHMqgEL3V3uIgosvh+SVIQvCh43SNu9HRbP1lnxkKm1kjDG4f32PP571JplkLjfS+mg2p1gxR7MYrrIA== chalk@^2.0.0: version "2.4.2" @@ -2080,9 +1984,9 @@ char-regex@^1.0.2: integrity sha512-kWWXztvZ5SBQV+eRgKFeh8q5sLuZY2+8WUIzlxWVTg+oGwY14qylx1KbKzHd8P6ZYkAg0xyIDU9JMHhyJMZ1jw== chokidar@^3.4.0: - version "3.5.2" - resolved "https://registry.yarnpkg.com/chokidar/-/chokidar-3.5.2.tgz#dba3976fcadb016f66fd365021d91600d01c1e75" - integrity sha512-ekGhOnNVPgT77r4K/U3GDhu+FQ2S8TnK/s2KbIGXi0SZWuwkZ2QNyfWdZW+TVfn84DpEP7rLeCt2UI6bJ8GwbQ== + version "3.5.3" + resolved "https://registry.yarnpkg.com/chokidar/-/chokidar-3.5.3.tgz#1cf37c8707b932bd1af1ae22c0432e2acd1903bd" + integrity sha512-Dr3sfKRP6oTcjf2JmUmFJfeVMvXBdegxB0iVQ5eb2V10uFJUCAS8OByZdVAyVb8xXNz3GjjTgj9kLWsZTqE6kw== dependencies: anymatch "~3.1.2" braces "~3.0.2" @@ -2382,9 +2286,9 @@ ee-first@1.1.1: integrity sha1-WQxhFWsK4vTwJVcyoViyZrxWsh0= electron-to-chromium@^1.4.17: - version "1.4.36" - resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.4.36.tgz#446c6184dbe5baeb5eae9a875490831e4bc5319a" - integrity sha512-MbLlbF39vKrXWlFEFpCgDHwdlz4O3LmHM5W4tiLRHjSmEUXjJjz8sZkMgWgvYxlZw3N1iDTmCEtOkkESb5TMCg== + version "1.4.52" + resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.4.52.tgz#ce44c6d6cc449e7688a4356b8c261cfeafa26833" + integrity sha512-JGkh8HEh5PnVrhU4HbpyyO0O791dVY6k7AdqfDeqbcRMeoGxtNHWT77deR2nhvbLe4dKpxjlDEvdEwrvRLGu2Q== emittery@^0.8.1: version "0.8.1" @@ -2490,12 +2394,7 @@ eslint-visitor-keys@^2.0.0: resolved "https://registry.yarnpkg.com/eslint-visitor-keys/-/eslint-visitor-keys-2.1.0.tgz#f65328259305927392c938ed44eb0a5c9b2bd303" integrity sha512-0rSmRBzXgDzIsD6mGdJgevzgezI534Cer5L/vyMX0kHzT/jiB43jRhd9YUlMGYLQy2zprNmoT8qasCGtY+QaKw== -eslint-visitor-keys@^3.0.0, eslint-visitor-keys@^3.1.0: - version "3.1.0" - resolved "https://registry.yarnpkg.com/eslint-visitor-keys/-/eslint-visitor-keys-3.1.0.tgz#eee4acea891814cda67a7d8812d9647dd0179af2" - integrity sha512-yWJFpu4DtjsWKkt5GeNBBuZMlNcYVs6vRCLoCVEJrTjaSB6LC98gFipNK/erM2Heg/E8mIK+hXG/pJMLK+eRZA== - -eslint-visitor-keys@^3.2.0: +eslint-visitor-keys@^3.0.0, eslint-visitor-keys@^3.1.0, eslint-visitor-keys@^3.2.0: version "3.2.0" resolved "https://registry.yarnpkg.com/eslint-visitor-keys/-/eslint-visitor-keys-3.2.0.tgz#6fbb166a6798ee5991358bc2daa1ba76cc1254a1" integrity sha512-IOzT0X126zn7ALX0dwFiUQEdsfzrm4+ISsQS8nukaJXwEyYKRSnEIIDULYg1mCtGp7UUXgfGl7BIolXREQK+XQ== @@ -2691,10 +2590,10 @@ fast-diff@^1.1.2: resolved "https://registry.yarnpkg.com/fast-diff/-/fast-diff-1.2.0.tgz#73ee11982d86caaf7959828d519cfe927fac5f03" integrity sha512-xJuoT5+L99XlZ8twedaRf6Ax2TgQVxvgZOYoPKqZufmJib0tL2tegPBOZb1pVNgIhlqDlA0eO0c3wBvQcmzx4w== -fast-glob@^3.1.1: - version "3.2.7" - resolved "https://registry.yarnpkg.com/fast-glob/-/fast-glob-3.2.7.tgz#fd6cb7a2d7e9aa7a7846111e85a196d6b2f766a1" - integrity sha512-rYGMRwip6lUMvYD3BTScMwT1HtAs2d71SMv66Vrxs0IekGZEjhM0pcMfjQPnknBt2zeCwQMEupiN02ZP4DiT1Q== +fast-glob@^3.2.9: + version "3.2.11" + resolved "https://registry.yarnpkg.com/fast-glob/-/fast-glob-3.2.11.tgz#a1172ad95ceb8a16e20caa5c5e56480e5129c1d9" + integrity sha512-xrO3+1bxSo3ZVHAnqzyuewYT6aMFHRAd4Kcs92MAonjwQZLsK9d0SF1IyQ3k5PoirxTW0Oe/RqFgMQ6TcNE5Ew== dependencies: "@nodelib/fs.stat" "^2.0.2" "@nodelib/fs.walk" "^1.2.3" @@ -2934,15 +2833,15 @@ globals@^13.6.0, globals@^13.9.0: type-fest "^0.20.2" globby@^11.0.4: - version "11.0.4" - resolved "https://registry.yarnpkg.com/globby/-/globby-11.0.4.tgz#2cbaff77c2f2a62e71e9b2813a67b97a3a3001a5" - integrity sha512-9O4MVG9ioZJ08ffbcyVYyLOJLk5JQ688pJ4eMGLpdWLHq/Wr1D9BlriLQyL0E+jbkuePVZXYFj47QM/v093wHg== + version "11.1.0" + resolved "https://registry.yarnpkg.com/globby/-/globby-11.1.0.tgz#bd4be98bb042f83d796f7e3811991fbe82a0d34b" + integrity sha512-jhIXaOzy1sb8IyocaruWSn1TjmnBVs8Ayhcy83rmxNJ8q2uWKCAj3CnJY+KpGSXCueAPc0i05kVvVKtP1t9S3g== dependencies: array-union "^2.1.0" dir-glob "^3.0.1" - fast-glob "^3.1.1" - ignore "^5.1.4" - merge2 "^1.3.0" + fast-glob "^3.2.9" + ignore "^5.2.0" + merge2 "^1.4.1" slash "^3.0.0" graceful-fs@^4.2.4: @@ -3053,7 +2952,7 @@ ignore@^4.0.6: resolved "https://registry.yarnpkg.com/ignore/-/ignore-4.0.6.tgz#750e3db5862087b4737ebac8207ffd1ef27b25fc" integrity sha512-cyFDKrqc/YdcWFniJhzI42+AzS+gNwmUzOSFcRCQYwySuBBBy/KjuxWLZ/FHEH6Moq1NizMOBWyTcv8O4OZIMg== -ignore@^5.1.4, ignore@^5.1.8, ignore@^5.2.0: +ignore@^5.1.8, ignore@^5.2.0: version "5.2.0" resolved "https://registry.yarnpkg.com/ignore/-/ignore-5.2.0.tgz#6d3bac8fa7fe0d45d9f9be7bac2fc279577e345a" integrity sha512-CmxgYGiEPCLhfLnpPp1MoRmifwEIOgjcHXxOBjv7mY96c+eWScsOP9c112ZyLdWHi0FxHjI+4uVhKYp/gcdRmQ== @@ -3104,7 +3003,7 @@ is-binary-path@~2.1.0: dependencies: binary-extensions "^2.0.0" -is-core-module@^2.8.0: +is-core-module@^2.8.1: version "2.8.1" resolved "https://registry.yarnpkg.com/is-core-module/-/is-core-module-2.8.1.tgz#f59fdfca701d5879d0a6b100a40aa1560ce27211" integrity sha512-SdNCUs284hr40hFTFP6l0IfZ/RSrMXF3qgoRHd3/79unUTvrFO/JoXwkGm+5J/Oe3E/b5GsnG330uUNgRpu1PA== @@ -3823,7 +3722,7 @@ merge-stream@^2.0.0: resolved "https://registry.yarnpkg.com/merge-stream/-/merge-stream-2.0.0.tgz#52823629a14dd00c9770fb6ad47dc6310f2c1f60" integrity sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w== -merge2@^1.3.0: +merge2@^1.3.0, merge2@^1.4.1: version "1.4.1" resolved "https://registry.yarnpkg.com/merge2/-/merge2-1.4.1.tgz#4368892f885e907455a6fd7dc55c0c9d404990ae" integrity sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg== @@ -3910,17 +3809,10 @@ neo-async@^2.6.0: resolved "https://registry.yarnpkg.com/neo-async/-/neo-async-2.6.2.tgz#b4aafb93e3aeb2d8174ca53cf163ab7d7308305f" integrity sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw== -node-fetch@2.6.5: - version "2.6.5" - resolved "https://registry.yarnpkg.com/node-fetch/-/node-fetch-2.6.5.tgz#42735537d7f080a7e5f78b6c549b7146be1742fd" - integrity sha512-mmlIVHJEu5rnIxgEgez6b9GgWXbkZj5YZ7fx+2r94a2E+Uirsp6HsPTPlomfdHtpt/B0cdKviwkoaM6pyvUOpQ== - dependencies: - whatwg-url "^5.0.0" - -node-fetch@^2.6.1, node-fetch@^2.6.6: - version "2.6.6" - resolved "https://registry.yarnpkg.com/node-fetch/-/node-fetch-2.6.6.tgz#1751a7c01834e8e1697758732e9efb6eeadfaf89" - integrity sha512-Z8/6vRlTUChSdIgMa51jxQ4lrw/Jy5SOW10ObaA47/RElsAN2c5Pn8bTgFGWn/ibwzXTE8qwr1Yzx28vsecXEA== +node-fetch@2.6.7, node-fetch@^2.6.1, node-fetch@^2.6.6: + version "2.6.7" + resolved "https://registry.yarnpkg.com/node-fetch/-/node-fetch-2.6.7.tgz#24de9fba827e3b4ae44dc8b20256a379160052ad" + integrity sha512-ZjMPFEfVx5j+y2yF35Kzx5sF7kDzxuDj6ziH4FFbOp87zKDZNx8yExJIb05OGF4Nlt9IHFIMBkRl41VdvcNdbQ== dependencies: whatwg-url "^5.0.0" @@ -4122,9 +4014,9 @@ pify@^4.0.1: integrity sha512-uB80kBFb/tfd68bVleG9T5GGsGPjJrLAUpR5PZIrhBnIaRTQRjqdJSsIKkOP6OAIFbj7GOrcudc5pNjZ+geV2g== pirates@^4.0.4: - version "4.0.4" - resolved "https://registry.yarnpkg.com/pirates/-/pirates-4.0.4.tgz#07df81e61028e402735cdd49db701e4885b4e6e6" - integrity sha512-ZIrVPH+A52Dw84R0L3/VS9Op04PuQ2SEoJL6bkshmiTic/HldyW9Tf7oH5mhJZBK7NmDx27vSMrYEXPXclpDKw== + version "4.0.5" + resolved "https://registry.yarnpkg.com/pirates/-/pirates-4.0.5.tgz#feec352ea5c3268fb23a37c702ab1699f35a5f3b" + integrity sha512-8V9+HQPupnaXMA23c5hvl69zXvTwTzyAYasnkb0Tts4XvO4CliqONMOnvlq26rkhLC3nWDFBJf73LU1e1VZLaQ== pkg-dir@4.2.0, pkg-dir@^4.2.0: version "4.2.0" @@ -4213,16 +4105,16 @@ punycode@^2.1.0, punycode@^2.1.1: resolved "https://registry.yarnpkg.com/punycode/-/punycode-2.1.1.tgz#b58b010ac40c22c5657616c8d2c2c02c7bf479ec" integrity sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A== -puppeteer@13.1.1: - version "13.1.1" - resolved "https://registry.yarnpkg.com/puppeteer/-/puppeteer-13.1.1.tgz#63771eb744202aa91918c49123f846e1747da121" - integrity sha512-GwdFy1JQ43Hhxj6MraXme+XfCX2CKe18MuwToXTMEAk0txg6vUEgwqBnzErTTqDVZ7sWYrDtDaRCfD2y7ZwgGw== +puppeteer@13.1.2: + version "13.1.2" + resolved "https://registry.yarnpkg.com/puppeteer/-/puppeteer-13.1.2.tgz#d6ef3295d7551200b7e52076a3cc1b731eff4294" + integrity sha512-ozVM8Tdg0patMtm/xAr3Uh7rQ28vBpbTHLP+ECmoAxG/s4PKrVLN764H/poLux7Ln77jHThOd8OBJj5mTuA6Iw== dependencies: debug "4.3.2" devtools-protocol "0.0.948846" extract-zip "2.0.1" https-proxy-agent "5.0.0" - node-fetch "2.6.5" + node-fetch "2.6.7" pkg-dir "4.2.0" progress "2.0.3" proxy-from-env "1.1.0" @@ -4372,11 +4264,11 @@ resolve.exports@^1.1.0: integrity sha512-J1l+Zxxp4XK3LUDZ9m60LRJF/mAe4z6a4xyabPHk7pvK5t35dACV32iIjJDFeWZFfZlO29w6SZ67knR0tHzJtQ== resolve@^1.14.2, resolve@^1.17.0, resolve@^1.19.0, resolve@^1.20.0: - version "1.21.0" - resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.21.0.tgz#b51adc97f3472e6a5cf4444d34bc9d6b9037591f" - integrity sha512-3wCbTpk5WJlyE4mSOtDLhqQmGFi0/TD9VPwmiolnk8U0wRgMEktqCXd3vy5buTO3tljvalNvKrjHEfrd2WpEKA== + version "1.22.0" + resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.22.0.tgz#5e0b8c67c15df57a89bdbabe603a002f21731198" + integrity sha512-Hhtrw0nLeSrFQ7phPp4OOcVjLPIeMnRlr5mcnVuMe7M/7eBn98A3hmFRLoFo3DLZkivSYwhRUJTyPyWAk56WLw== dependencies: - is-core-module "^2.8.0" + is-core-module "^2.8.1" path-parse "^1.0.7" supports-preserve-symlinks-flag "^1.0.0" @@ -4409,10 +4301,10 @@ rollup-plugin-terser@7.0.2: serialize-javascript "^4.0.0" terser "^5.0.0" -rollup@2.66.0: - version "2.66.0" - resolved "https://registry.yarnpkg.com/rollup/-/rollup-2.66.0.tgz#ee529ea15a20485d579039637fec3050bad03bbb" - integrity sha512-L6mKOkdyP8HK5kKJXaiWG7KZDumPJjuo1P+cfyHOJPNNTK3Moe7zCH5+fy7v8pVmHXtlxorzaBjvkBMB23s98g== +rollup@2.66.1: + version "2.66.1" + resolved "https://registry.yarnpkg.com/rollup/-/rollup-2.66.1.tgz#366b0404de353c4331d538c3ad2963934fcb4937" + integrity sha512-crSgLhSkLMnKr4s9iZ/1qJCplgAgrRY+igWv8KhG/AjKOJ0YX/WpmANyn8oxrw+zenF3BXWDLa7Xl/QZISH+7w== optionalDependencies: fsevents "~2.3.2" @@ -4972,9 +4864,9 @@ v8-compile-cache@^2.0.3: integrity sha512-l8lCEmLcLYZh4nbunNZvQCJc5pv7+RCwa8q/LdUx8u7lsWvPDKmpodJAJNwkAhJC//dFY48KuIEmjtd4RViDrA== v8-to-istanbul@^8.1.0: - version "8.1.0" - resolved "https://registry.yarnpkg.com/v8-to-istanbul/-/v8-to-istanbul-8.1.0.tgz#0aeb763894f1a0a1676adf8a8b7612a38902446c" - integrity sha512-/PRhfd8aTNp9Ggr62HPzXg2XasNFGy5PBt0Rp04du7/8GNNSgxFL6WBTkgMKSL9bFjH+8kKEG3f37FmxiTqUUA== + version "8.1.1" + resolved "https://registry.yarnpkg.com/v8-to-istanbul/-/v8-to-istanbul-8.1.1.tgz#77b752fd3975e31bbcef938f85e9bd1c7a8d60ed" + integrity sha512-FGtKtv3xIpR6BYhvgH8MI/y78oT7d8Au3ww4QIxymrCtZEh5b8gCw2siywE+puhEmuWKDtmfrvF5UlB298ut3w== dependencies: "@types/istanbul-lib-coverage" "^2.0.1" convert-source-map "^1.6.0" From 8673f06ea40852d632fcd9a1b42f7a2a7f720a89 Mon Sep 17 00:00:00 2001 From: Ferdi Koomen Date: Tue, 25 Jan 2022 15:38:51 +0100 Subject: [PATCH 19/19] v0.16.0 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 7bcd910b..58cf089b 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "openapi-typescript-codegen", - "version": "0.15.0", + "version": "0.16.0", "description": "Library that generates Typescript clients based on the OpenAPI specification.", "author": "Ferdi Koomen", "homepage": "https://github.com/ferdikoomen/openapi-typescript-codegen",