From 6d44533ff9e5ba758205e26c44924494341751d3 Mon Sep 17 00:00:00 2001 From: Jordan Shatford Date: Tue, 26 Mar 2024 12:20:03 +1100 Subject: [PATCH 1/7] chore(parser): move discriminator file to v3 parser --- .../v3/parser}/discriminator.ts | 10 ++--- src/openApi/v3/parser/getModelProperties.ts | 2 +- src/utils/isEqual.ts | 40 ------------------- 3 files changed, 6 insertions(+), 46 deletions(-) rename src/{utils => openApi/v3/parser}/discriminator.ts (81%) delete mode 100644 src/utils/isEqual.ts diff --git a/src/utils/discriminator.ts b/src/openApi/v3/parser/discriminator.ts similarity index 81% rename from src/utils/discriminator.ts rename to src/openApi/v3/parser/discriminator.ts index b398621e4..8793d4054 100644 --- a/src/utils/discriminator.ts +++ b/src/openApi/v3/parser/discriminator.ts @@ -1,8 +1,8 @@ -import type { OpenApi } from '../openApi/v3/interfaces/OpenApi'; -import type { OpenApiDiscriminator } from '../openApi/v3/interfaces/OpenApiDiscriminator'; -import type { Model } from '../types/client'; -import type { Dictionary } from '../types/generic'; -import { stripNamespace } from './stripNamespace'; +import type { Model } from '../../../types/client'; +import type { Dictionary } from '../../../types/generic'; +import { stripNamespace } from '../../../utils/stripNamespace'; +import type { OpenApi } from '../interfaces/OpenApi'; +import type { OpenApiDiscriminator } from '../interfaces/OpenApiDiscriminator'; const inverseDictionary = (map: Dictionary): Dictionary => { const m2: Dictionary = {}; diff --git a/src/openApi/v3/parser/getModelProperties.ts b/src/openApi/v3/parser/getModelProperties.ts index fb8d02c24..fdf17cbd9 100644 --- a/src/openApi/v3/parser/getModelProperties.ts +++ b/src/openApi/v3/parser/getModelProperties.ts @@ -1,10 +1,10 @@ import type { Model } from '../../../types/client'; -import { findOneOfParentDiscriminator, mapPropertyValue } from '../../../utils/discriminator'; import { escapeName } from '../../../utils/escapeName'; import { getPattern } from '../../../utils/getPattern'; import { getType } from '../../../utils/type'; import type { OpenApi } from '../interfaces/OpenApi'; import type { OpenApiSchema } from '../interfaces/OpenApiSchema'; +import { findOneOfParentDiscriminator, mapPropertyValue } from './discriminator'; import type { getModel } from './getModel'; import { getModelDefault } from './getModelDefault'; diff --git a/src/utils/isEqual.ts b/src/utils/isEqual.ts deleted file mode 100644 index 678071e33..000000000 --- a/src/utils/isEqual.ts +++ /dev/null @@ -1,40 +0,0 @@ -export const isEqual = (a: A, b: B): boolean => { - // @ts-ignore - if (a === b) { - return true; - } - - if (a && b && typeof a === 'object' && typeof b === 'object') { - if (Array.isArray(a) && Array.isArray(b)) { - if (a.length !== b.length) { - return false; - } - for (let i = 0; i < a.length; i++) { - if (!isEqual(a[i], b[i])) { - return false; - } - } - return true; - } - - const keysA = Object.keys(a); - const keysB = Object.keys(b); - if (keysA.length !== keysB.length) { - return false; - } - - for (let i = 0; i < keysA.length; i++) { - const key = keysA[i]; - if (!Object.prototype.hasOwnProperty.call(b, key)) { - return false; - } - // @ts-ignore - if (!isEqual(a[key], b[key])) { - return false; - } - } - return true; - } - - return a !== a && b !== b; -}; From cad3afce8b2f0166e0ed264922def7a82d06e673 Mon Sep 17 00:00:00 2001 From: Jordan Shatford Date: Tue, 26 Mar 2024 12:28:31 +1100 Subject: [PATCH 2/7] chore(parser): move get operation name to common parser --- .../common/parser}/__tests__/operation.spec.ts | 0 src/{utils => openApi/common/parser}/operation.ts | 4 ++-- src/openApi/v2/parser/getOperation.ts | 2 +- src/openApi/v3/parser/operation.ts | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) rename src/{utils => openApi/common/parser}/__tests__/operation.spec.ts (100%) rename src/{utils => openApi/common/parser}/operation.ts (85%) diff --git a/src/utils/__tests__/operation.spec.ts b/src/openApi/common/parser/__tests__/operation.spec.ts similarity index 100% rename from src/utils/__tests__/operation.spec.ts rename to src/openApi/common/parser/__tests__/operation.spec.ts diff --git a/src/utils/operation.ts b/src/openApi/common/parser/operation.ts similarity index 85% rename from src/utils/operation.ts rename to src/openApi/common/parser/operation.ts index 6fd0bebaa..211bcb5e1 100644 --- a/src/utils/operation.ts +++ b/src/openApi/common/parser/operation.ts @@ -1,7 +1,7 @@ import camelCase from 'camelcase'; -import type { Config } from '../types/config'; -import { sanitizeOperationName } from './sanitize'; +import type { Config } from '../../../types/config'; +import { sanitizeOperationName } from '../../../utils/sanitize'; /** * Convert the input value to a correct operation (method) classname. diff --git a/src/openApi/v2/parser/getOperation.ts b/src/openApi/v2/parser/getOperation.ts index aea6064c2..a9309f763 100644 --- a/src/openApi/v2/parser/getOperation.ts +++ b/src/openApi/v2/parser/getOperation.ts @@ -1,6 +1,6 @@ import type { Operation, OperationParameters } from '../../../types/client'; import type { Config } from '../../../types/config'; -import { getOperationName } from '../../../utils/operation'; +import { getOperationName } from '../../common/parser/operation'; import { toSortedByRequired } from '../../common/parser/sort'; import type { OpenApi } from '../interfaces/OpenApi'; import type { OpenApiOperation } from '../interfaces/OpenApiOperation'; diff --git a/src/openApi/v3/parser/operation.ts b/src/openApi/v3/parser/operation.ts index 97f8ce3d2..5a74348cc 100644 --- a/src/openApi/v3/parser/operation.ts +++ b/src/openApi/v3/parser/operation.ts @@ -1,7 +1,7 @@ import type { Operation, OperationParameter, OperationParameters } from '../../../types/client'; import type { Config } from '../../../types/config'; -import { getOperationName } from '../../../utils/operation'; import { getRef } from '../../common/parser/getRef'; +import { getOperationName } from '../../common/parser/operation'; import { toSortedByRequired } from '../../common/parser/sort'; import type { OpenApi } from '../interfaces/OpenApi'; import type { OpenApiOperation } from '../interfaces/OpenApiOperation'; From 4ee7bb28a172bb33a3476c62ae4f98554c00089b Mon Sep 17 00:00:00 2001 From: Jordan Shatford Date: Tue, 26 Mar 2024 12:52:50 +1100 Subject: [PATCH 3/7] chore(parser): move getOperationParameterName to common parser --- .../common/parser/__tests__/operation.spec.ts | 218 ++++++++++++++---- src/openApi/common/parser/operation.ts | 12 +- .../v2/parser/getOperationParameter.ts | 2 +- .../parser/getOperationParameterName.spec.ts | 19 -- .../v2/parser/getOperationParameterName.ts | 13 -- .../v3/parser/getOperationParameter.ts | 2 +- .../parser/getOperationParameterName.spec.ts | 21 -- .../v3/parser/getOperationParameterName.ts | 13 -- 8 files changed, 189 insertions(+), 111 deletions(-) delete mode 100644 src/openApi/v2/parser/getOperationParameterName.spec.ts delete mode 100644 src/openApi/v2/parser/getOperationParameterName.ts delete mode 100644 src/openApi/v3/parser/getOperationParameterName.spec.ts delete mode 100644 src/openApi/v3/parser/getOperationParameterName.ts diff --git a/src/openApi/common/parser/__tests__/operation.spec.ts b/src/openApi/common/parser/__tests__/operation.spec.ts index be4da8cb9..94caff2c9 100644 --- a/src/openApi/common/parser/__tests__/operation.spec.ts +++ b/src/openApi/common/parser/__tests__/operation.spec.ts @@ -1,50 +1,184 @@ import { describe, expect, it } from 'vitest'; -import { getOperationName } from '../operation'; +import { getOperationName, getOperationParameterName } from '../operation'; describe('getOperationName', () => { - it('should produce correct result', () => { - const options: Parameters[2] = { - operationId: true, - }; - expect(getOperationName('/api/v{api-version}/users', 'GET', options, 'GetAllUsers')).toEqual('getAllUsers'); - expect(getOperationName('/api/v{api-version}/users', 'GET', options, undefined)).toEqual('getApiUsers'); - expect(getOperationName('/api/v{api-version}/users', 'POST', options, undefined)).toEqual('postApiUsers'); - expect(getOperationName('/api/v1/users', 'GET', options, 'GetAllUsers')).toEqual('getAllUsers'); - expect(getOperationName('/api/v1/users', 'GET', options, undefined)).toEqual('getApiV1Users'); - expect(getOperationName('/api/v1/users', 'POST', options, undefined)).toEqual('postApiV1Users'); - expect(getOperationName('/api/v1/users/{id}', 'GET', options, undefined)).toEqual('getApiV1UsersById'); - expect(getOperationName('/api/v1/users/{id}', 'POST', options, undefined)).toEqual('postApiV1UsersById'); + const options1: Parameters[2] = { + operationId: true, + }; - expect(getOperationName('/api/v{api-version}/users', 'GET', options, 'fooBar')).toEqual('fooBar'); - expect(getOperationName('/api/v{api-version}/users', 'GET', options, 'FooBar')).toEqual('fooBar'); - expect(getOperationName('/api/v{api-version}/users', 'GET', options, 'Foo Bar')).toEqual('fooBar'); - expect(getOperationName('/api/v{api-version}/users', 'GET', options, 'foo bar')).toEqual('fooBar'); - expect(getOperationName('/api/v{api-version}/users', 'GET', options, 'foo-bar')).toEqual('fooBar'); - expect(getOperationName('/api/v{api-version}/users', 'GET', options, 'foo_bar')).toEqual('fooBar'); - expect(getOperationName('/api/v{api-version}/users', 'GET', options, 'foo.bar')).toEqual('fooBar'); - expect(getOperationName('/api/v{api-version}/users', 'GET', options, '@foo.bar')).toEqual('fooBar'); - expect(getOperationName('/api/v{api-version}/users', 'GET', options, '$foo.bar')).toEqual('fooBar'); - expect(getOperationName('/api/v{api-version}/users', 'GET', options, '_foo.bar')).toEqual('fooBar'); - expect(getOperationName('/api/v{api-version}/users', 'GET', options, '-foo.bar')).toEqual('fooBar'); - expect(getOperationName('/api/v{api-version}/users', 'GET', options, '123.foo.bar')).toEqual('fooBar'); + const options2: Parameters[2] = { + operationId: false, + }; - const optionsIgnoreOperationId: Parameters[2] = { - operationId: false, - }; - expect(getOperationName('/api/v1/users', 'GET', optionsIgnoreOperationId, 'GetAllUsers')).toEqual( - 'getApiV1Users' - ); - expect(getOperationName('/api/v{api-version}/users', 'GET', optionsIgnoreOperationId, 'fooBar')).toEqual( - 'getApiUsers' - ); - expect( - getOperationName( - '/api/v{api-version}/users/{userId}/location/{locationId}', - 'GET', - optionsIgnoreOperationId, - 'fooBar' - ) - ).toEqual('getApiUsersByUserIdLocationByLocationId'); + it.each([ + { + url: '/api/v{api-version}/users', + method: 'GET', + options: options1, + operationId: 'GetAllUsers', + expected: 'getAllUsers', + }, + { + url: '/api/v{api-version}/users', + method: 'GET', + options: options1, + operationId: undefined, + expected: 'getApiUsers', + }, + { + url: '/api/v{api-version}/users', + method: 'POST', + options: options1, + operationId: undefined, + expected: 'postApiUsers', + }, + { url: '/api/v1/users', method: 'GET', options: options1, operationId: 'GetAllUsers', expected: 'getAllUsers' }, + { url: '/api/v1/users', method: 'GET', options: options1, operationId: undefined, expected: 'getApiV1Users' }, + { url: '/api/v1/users', method: 'POST', options: options1, operationId: undefined, expected: 'postApiV1Users' }, + { + url: '/api/v1/users/{id}', + method: 'GET', + options: options1, + operationId: undefined, + expected: 'getApiV1UsersById', + }, + { + url: '/api/v1/users/{id}', + method: 'POST', + options: options1, + operationId: undefined, + expected: 'postApiV1UsersById', + }, + { + url: '/api/v{api-version}/users', + method: 'GET', + options: options1, + operationId: 'fooBar', + expected: 'fooBar', + }, + { + url: '/api/v{api-version}/users', + method: 'GET', + options: options1, + operationId: 'FooBar', + expected: 'fooBar', + }, + { + url: '/api/v{api-version}/users', + method: 'GET', + options: options1, + operationId: 'Foo Bar', + expected: 'fooBar', + }, + { + url: '/api/v{api-version}/users', + method: 'GET', + options: options1, + operationId: 'foo bar', + expected: 'fooBar', + }, + { + url: '/api/v{api-version}/users', + method: 'GET', + options: options1, + operationId: 'foo-bar', + expected: 'fooBar', + }, + { + url: '/api/v{api-version}/users', + method: 'GET', + options: options1, + operationId: 'foo_bar', + expected: 'fooBar', + }, + { + url: '/api/v{api-version}/users', + method: 'GET', + options: options1, + operationId: 'foo.bar', + expected: 'fooBar', + }, + { + url: '/api/v{api-version}/users', + method: 'GET', + options: options1, + operationId: '@foo.bar', + expected: 'fooBar', + }, + { + url: '/api/v{api-version}/users', + method: 'GET', + options: options1, + operationId: '$foo.bar', + expected: 'fooBar', + }, + { + url: '/api/v{api-version}/users', + method: 'GET', + options: options1, + operationId: '_foo.bar', + expected: 'fooBar', + }, + { + url: '/api/v{api-version}/users', + method: 'GET', + options: options1, + operationId: '-foo.bar', + expected: 'fooBar', + }, + { + url: '/api/v{api-version}/users', + method: 'GET', + options: options1, + operationId: '123.foo.bar', + expected: 'fooBar', + }, + { + url: '/api/v1/users', + method: 'GET', + options: options2, + operationId: 'GetAllUsers', + expected: 'getApiV1Users', + }, + { + url: '/api/v{api-version}/users', + method: 'GET', + options: options2, + operationId: 'fooBar', + expected: 'getApiUsers', + }, + { + url: '/api/v{api-version}/users/{userId}/location/{locationId}', + method: 'GET', + options: options2, + operationId: 'fooBar', + expected: 'getApiUsersByUserIdLocationByLocationId', + }, + ])( + 'getOperationName($url, $method, { operationId: $useOperationId }, $operationId) -> $expected', + ({ url, method, options, operationId, expected }) => { + expect(getOperationName(url, method, options, operationId)).toEqual(expected); + } + ); +}); + +describe('getOperationParameterName', () => { + it.each([ + { input: '', expected: '' }, + { input: 'foobar', expected: 'foobar' }, + { input: 'fooBar', expected: 'fooBar' }, + { input: 'foo_bar', expected: 'fooBar' }, + { input: 'foo-bar', expected: 'fooBar' }, + { input: 'foo.bar', expected: 'fooBar' }, + { input: '@foo.bar', expected: 'fooBar' }, + { input: '$foo.bar', expected: 'fooBar' }, + { input: '123.foo.bar', expected: 'fooBar' }, + { input: 'Foo-Bar', expected: 'fooBar' }, + { input: 'FOO-BAR', expected: 'fooBar' }, + { input: 'foo[bar]', expected: 'fooBar' }, + { input: 'foo.bar[]', expected: 'fooBarArray' }, + ])('getOperationParameterName($input) -> $expected', ({ input, expected }) => { + expect(getOperationParameterName(input)).toEqual(expected); }); }); diff --git a/src/openApi/common/parser/operation.ts b/src/openApi/common/parser/operation.ts index 211bcb5e1..386c48cce 100644 --- a/src/openApi/common/parser/operation.ts +++ b/src/openApi/common/parser/operation.ts @@ -1,7 +1,8 @@ import camelCase from 'camelcase'; import type { Config } from '../../../types/config'; -import { sanitizeOperationName } from '../../../utils/sanitize'; +import { reservedWords } from '../../../utils/reservedWords'; +import { sanitizeOperationName, sanitizeOperationParameterName } from '../../../utils/sanitize'; /** * Convert the input value to a correct operation (method) classname. @@ -25,3 +26,12 @@ export const getOperationName = ( return camelCase(`${method}-${urlWithoutPlaceholders}`); }; + +/** + * Replaces any invalid characters from a parameter name. + * For example: 'filter.someProperty' becomes 'filterSomeProperty'. + */ +export const getOperationParameterName = (value: string): string => { + const clean = sanitizeOperationParameterName(value).trim(); + return camelCase(clean).replace(reservedWords, '_$1'); +}; diff --git a/src/openApi/v2/parser/getOperationParameter.ts b/src/openApi/v2/parser/getOperationParameter.ts index 2401e7695..c6059a743 100644 --- a/src/openApi/v2/parser/getOperationParameter.ts +++ b/src/openApi/v2/parser/getOperationParameter.ts @@ -3,12 +3,12 @@ import { getEnums } from '../../../utils/getEnums'; import { getPattern } from '../../../utils/getPattern'; import { getType } from '../../../utils/type'; import { getRef } from '../../common/parser/getRef'; +import { getOperationParameterName } from '../../common/parser/operation'; import type { OpenApi } from '../interfaces/OpenApi'; import type { OpenApiParameter } from '../interfaces/OpenApiParameter'; import type { OpenApiSchema } from '../interfaces/OpenApiSchema'; import { getModel } from './getModel'; import { getOperationParameterDefault } from './getOperationParameterDefault'; -import { getOperationParameterName } from './getOperationParameterName'; export const getOperationParameter = (openApi: OpenApi, parameter: OpenApiParameter): OperationParameter => { const operationParameter: OperationParameter = { diff --git a/src/openApi/v2/parser/getOperationParameterName.spec.ts b/src/openApi/v2/parser/getOperationParameterName.spec.ts deleted file mode 100644 index 8c2332400..000000000 --- a/src/openApi/v2/parser/getOperationParameterName.spec.ts +++ /dev/null @@ -1,19 +0,0 @@ -import { describe, expect, it } from 'vitest'; - -import { getOperationParameterName } from './getOperationParameterName'; - -describe('getOperationParameterName', () => { - it('should produce correct result', () => { - expect(getOperationParameterName('')).toEqual(''); - expect(getOperationParameterName('foobar')).toEqual('foobar'); - expect(getOperationParameterName('fooBar')).toEqual('fooBar'); - expect(getOperationParameterName('foo_bar')).toEqual('fooBar'); - expect(getOperationParameterName('foo-bar')).toEqual('fooBar'); - expect(getOperationParameterName('foo.bar')).toEqual('fooBar'); - expect(getOperationParameterName('@foo.bar')).toEqual('fooBar'); - expect(getOperationParameterName('$foo.bar')).toEqual('fooBar'); - expect(getOperationParameterName('123.foo.bar')).toEqual('fooBar'); - expect(getOperationParameterName('Foo-Bar')).toEqual('fooBar'); - expect(getOperationParameterName('FOO-BAR')).toEqual('fooBar'); - }); -}); diff --git a/src/openApi/v2/parser/getOperationParameterName.ts b/src/openApi/v2/parser/getOperationParameterName.ts deleted file mode 100644 index a27ccd696..000000000 --- a/src/openApi/v2/parser/getOperationParameterName.ts +++ /dev/null @@ -1,13 +0,0 @@ -import camelCase from 'camelcase'; - -import { reservedWords } from '../../../utils/reservedWords'; -import { sanitizeOperationParameterName } from '../../../utils/sanitize'; - -/** - * Replaces any invalid characters from a parameter name. - * For example: 'filter.someProperty' becomes 'filterSomeProperty'. - */ -export const getOperationParameterName = (value: string): string => { - const clean = sanitizeOperationParameterName(value).trim(); - return camelCase(clean).replace(reservedWords, '_$1'); -}; diff --git a/src/openApi/v3/parser/getOperationParameter.ts b/src/openApi/v3/parser/getOperationParameter.ts index aa24294db..ab933563d 100644 --- a/src/openApi/v3/parser/getOperationParameter.ts +++ b/src/openApi/v3/parser/getOperationParameter.ts @@ -2,12 +2,12 @@ import type { OperationParameter } from '../../../types/client'; import { getPattern } from '../../../utils/getPattern'; import { getType } from '../../../utils/type'; import { getRef } from '../../common/parser/getRef'; +import { getOperationParameterName } from '../../common/parser/operation'; import type { OpenApi } from '../interfaces/OpenApi'; import type { OpenApiParameter } from '../interfaces/OpenApiParameter'; import type { OpenApiSchema } from '../interfaces/OpenApiSchema'; import { getModel } from './getModel'; import { getModelDefault } from './getModelDefault'; -import { getOperationParameterName } from './getOperationParameterName'; export const getOperationParameter = (openApi: OpenApi, parameter: OpenApiParameter): OperationParameter => { const operationParameter: OperationParameter = { diff --git a/src/openApi/v3/parser/getOperationParameterName.spec.ts b/src/openApi/v3/parser/getOperationParameterName.spec.ts deleted file mode 100644 index acfc04595..000000000 --- a/src/openApi/v3/parser/getOperationParameterName.spec.ts +++ /dev/null @@ -1,21 +0,0 @@ -import { describe, expect, it } from 'vitest'; - -import { getOperationParameterName } from './getOperationParameterName'; - -describe('getOperationParameterName', () => { - it('should produce correct result', () => { - expect(getOperationParameterName('')).toEqual(''); - expect(getOperationParameterName('foobar')).toEqual('foobar'); - expect(getOperationParameterName('fooBar')).toEqual('fooBar'); - expect(getOperationParameterName('foo_bar')).toEqual('fooBar'); - expect(getOperationParameterName('foo-bar')).toEqual('fooBar'); - expect(getOperationParameterName('foo.bar')).toEqual('fooBar'); - expect(getOperationParameterName('@foo.bar')).toEqual('fooBar'); - expect(getOperationParameterName('$foo.bar')).toEqual('fooBar'); - expect(getOperationParameterName('123.foo.bar')).toEqual('fooBar'); - expect(getOperationParameterName('Foo-Bar')).toEqual('fooBar'); - expect(getOperationParameterName('FOO-BAR')).toEqual('fooBar'); - expect(getOperationParameterName('foo[bar]')).toEqual('fooBar'); - expect(getOperationParameterName('foo.bar[]')).toEqual('fooBarArray'); - }); -}); diff --git a/src/openApi/v3/parser/getOperationParameterName.ts b/src/openApi/v3/parser/getOperationParameterName.ts deleted file mode 100644 index a27ccd696..000000000 --- a/src/openApi/v3/parser/getOperationParameterName.ts +++ /dev/null @@ -1,13 +0,0 @@ -import camelCase from 'camelcase'; - -import { reservedWords } from '../../../utils/reservedWords'; -import { sanitizeOperationParameterName } from '../../../utils/sanitize'; - -/** - * Replaces any invalid characters from a parameter name. - * For example: 'filter.someProperty' becomes 'filterSomeProperty'. - */ -export const getOperationParameterName = (value: string): string => { - const clean = sanitizeOperationParameterName(value).trim(); - return camelCase(clean).replace(reservedWords, '_$1'); -}; From febab12a984ff2c5dfe5a0d20b5f2f350e30d5e6 Mon Sep 17 00:00:00 2001 From: Jordan Shatford Date: Tue, 26 Mar 2024 12:54:35 +1100 Subject: [PATCH 4/7] chore(parser): move getOperationResponseHeader to common parser --- src/openApi/common/parser/operation.ts | 9 +++++++++ src/openApi/v2/parser/getOperation.ts | 3 +-- src/openApi/v2/parser/getOperationResponseHeader.ts | 9 --------- src/openApi/v3/parser/getOperationResponseHeader.ts | 9 --------- src/openApi/v3/parser/operation.ts | 3 +-- 5 files changed, 11 insertions(+), 22 deletions(-) delete mode 100644 src/openApi/v2/parser/getOperationResponseHeader.ts delete mode 100644 src/openApi/v3/parser/getOperationResponseHeader.ts diff --git a/src/openApi/common/parser/operation.ts b/src/openApi/common/parser/operation.ts index 386c48cce..0e06904dd 100644 --- a/src/openApi/common/parser/operation.ts +++ b/src/openApi/common/parser/operation.ts @@ -1,5 +1,6 @@ import camelCase from 'camelcase'; +import type { OperationResponse } from '../../../types/client'; import type { Config } from '../../../types/config'; import { reservedWords } from '../../../utils/reservedWords'; import { sanitizeOperationName, sanitizeOperationParameterName } from '../../../utils/sanitize'; @@ -35,3 +36,11 @@ export const getOperationParameterName = (value: string): string => { const clean = sanitizeOperationParameterName(value).trim(); return camelCase(clean).replace(reservedWords, '_$1'); }; + +export const getOperationResponseHeader = (operationResponses: OperationResponse[]): string | null => { + const header = operationResponses.find(operationResponses => operationResponses.in === 'header'); + if (header) { + return header.name; + } + return null; +}; diff --git a/src/openApi/v2/parser/getOperation.ts b/src/openApi/v2/parser/getOperation.ts index a9309f763..dda1674de 100644 --- a/src/openApi/v2/parser/getOperation.ts +++ b/src/openApi/v2/parser/getOperation.ts @@ -1,12 +1,11 @@ import type { Operation, OperationParameters } from '../../../types/client'; import type { Config } from '../../../types/config'; -import { getOperationName } from '../../common/parser/operation'; +import { getOperationName, getOperationResponseHeader } from '../../common/parser/operation'; import { toSortedByRequired } from '../../common/parser/sort'; import type { OpenApi } from '../interfaces/OpenApi'; import type { OpenApiOperation } from '../interfaces/OpenApiOperation'; import { getOperationErrors } from './getOperationErrors'; import { getOperationParameters } from './getOperationParameters'; -import { getOperationResponseHeader } from './getOperationResponseHeader'; import { getOperationResponses } from './getOperationResponses'; import { getOperationResults } from './getOperationResults'; import { getServiceName } from './getServiceName'; diff --git a/src/openApi/v2/parser/getOperationResponseHeader.ts b/src/openApi/v2/parser/getOperationResponseHeader.ts deleted file mode 100644 index 5d6a04202..000000000 --- a/src/openApi/v2/parser/getOperationResponseHeader.ts +++ /dev/null @@ -1,9 +0,0 @@ -import type { OperationResponse } from '../../../types/client'; - -export const getOperationResponseHeader = (operationResponses: OperationResponse[]): string | null => { - const header = operationResponses.find(operationResponses => operationResponses.in === 'header'); - if (header) { - return header.name; - } - return null; -}; diff --git a/src/openApi/v3/parser/getOperationResponseHeader.ts b/src/openApi/v3/parser/getOperationResponseHeader.ts deleted file mode 100644 index 5d6a04202..000000000 --- a/src/openApi/v3/parser/getOperationResponseHeader.ts +++ /dev/null @@ -1,9 +0,0 @@ -import type { OperationResponse } from '../../../types/client'; - -export const getOperationResponseHeader = (operationResponses: OperationResponse[]): string | null => { - const header = operationResponses.find(operationResponses => operationResponses.in === 'header'); - if (header) { - return header.name; - } - return null; -}; diff --git a/src/openApi/v3/parser/operation.ts b/src/openApi/v3/parser/operation.ts index 5a74348cc..59300bd2e 100644 --- a/src/openApi/v3/parser/operation.ts +++ b/src/openApi/v3/parser/operation.ts @@ -1,7 +1,7 @@ import type { Operation, OperationParameter, OperationParameters } from '../../../types/client'; import type { Config } from '../../../types/config'; import { getRef } from '../../common/parser/getRef'; -import { getOperationName } from '../../common/parser/operation'; +import { getOperationName, getOperationResponseHeader } from '../../common/parser/operation'; import { toSortedByRequired } from '../../common/parser/sort'; import type { OpenApi } from '../interfaces/OpenApi'; import type { OpenApiOperation } from '../interfaces/OpenApiOperation'; @@ -9,7 +9,6 @@ import type { OpenApiRequestBody } from '../interfaces/OpenApiRequestBody'; import { getOperationErrors } from './getOperationErrors'; import { getOperationParameters } from './getOperationParameters'; import { getOperationRequestBody } from './getOperationRequestBody'; -import { getOperationResponseHeader } from './getOperationResponseHeader'; import { getOperationResponses } from './getOperationResponses'; import { getOperationResults } from './getOperationResults'; import { getServiceName } from './service'; From 7010340fffaf463c661bc4aed7d78e4f82544a36 Mon Sep 17 00:00:00 2001 From: Jordan Shatford Date: Tue, 26 Mar 2024 12:59:06 +1100 Subject: [PATCH 5/7] chore(parser): move getOperationResponseCode to common parser --- .../common/parser/__tests__/operation.spec.ts | 16 +++++++++++++++- src/openApi/common/parser/operation.ts | 17 +++++++++++++++++ .../v2/parser/getOperationResponseCode.spec.ts | 15 --------------- .../v2/parser/getOperationResponseCode.ts | 16 ---------------- src/openApi/v2/parser/getOperationResponses.ts | 2 +- .../v3/parser/getOperationResponseCode.spec.ts | 15 --------------- .../v3/parser/getOperationResponseCode.ts | 16 ---------------- src/openApi/v3/parser/getOperationResponses.ts | 2 +- 8 files changed, 34 insertions(+), 65 deletions(-) delete mode 100644 src/openApi/v2/parser/getOperationResponseCode.spec.ts delete mode 100644 src/openApi/v2/parser/getOperationResponseCode.ts delete mode 100644 src/openApi/v3/parser/getOperationResponseCode.spec.ts delete mode 100644 src/openApi/v3/parser/getOperationResponseCode.ts diff --git a/src/openApi/common/parser/__tests__/operation.spec.ts b/src/openApi/common/parser/__tests__/operation.spec.ts index 94caff2c9..64c0c7671 100644 --- a/src/openApi/common/parser/__tests__/operation.spec.ts +++ b/src/openApi/common/parser/__tests__/operation.spec.ts @@ -1,6 +1,6 @@ import { describe, expect, it } from 'vitest'; -import { getOperationName, getOperationParameterName } from '../operation'; +import { getOperationName, getOperationParameterName, getOperationResponseCode } from '../operation'; describe('getOperationName', () => { const options1: Parameters[2] = { @@ -182,3 +182,17 @@ describe('getOperationParameterName', () => { expect(getOperationParameterName(input)).toEqual(expected); }); }); + +describe('getOperationResponseCode', () => { + it.each([ + { input: '', expected: null }, + { input: 'default', expected: 200 }, + { input: '200', expected: 200 }, + { input: '300', expected: 300 }, + { input: '400', expected: 400 }, + { input: 'abc', expected: null }, + { input: '-100', expected: 100 }, + ])('getOperationResponseCode($input) -> $expected', ({ input, expected }) => { + expect(getOperationResponseCode(input)).toEqual(expected); + }); +}); diff --git a/src/openApi/common/parser/operation.ts b/src/openApi/common/parser/operation.ts index 0e06904dd..a5f1e35ff 100644 --- a/src/openApi/common/parser/operation.ts +++ b/src/openApi/common/parser/operation.ts @@ -44,3 +44,20 @@ export const getOperationResponseHeader = (operationResponses: OperationResponse } return 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; + } + + // Check if we can parse the code and return of successful. + if (/[0-9]+/g.test(value)) { + const code = parseInt(value); + if (Number.isInteger(code)) { + return Math.abs(code); + } + } + + return null; +}; diff --git a/src/openApi/v2/parser/getOperationResponseCode.spec.ts b/src/openApi/v2/parser/getOperationResponseCode.spec.ts deleted file mode 100644 index 429e28bdd..000000000 --- a/src/openApi/v2/parser/getOperationResponseCode.spec.ts +++ /dev/null @@ -1,15 +0,0 @@ -import { describe, expect, it } from 'vitest'; - -import { getOperationResponseCode } from './getOperationResponseCode'; - -describe('getOperationResponseCode', () => { - it('should produce correct result', () => { - expect(getOperationResponseCode('')).toEqual(null); - expect(getOperationResponseCode('default')).toEqual(200); - expect(getOperationResponseCode('200')).toEqual(200); - expect(getOperationResponseCode('300')).toEqual(300); - expect(getOperationResponseCode('400')).toEqual(400); - expect(getOperationResponseCode('abc')).toEqual(null); - expect(getOperationResponseCode('-100')).toEqual(100); - }); -}); diff --git a/src/openApi/v2/parser/getOperationResponseCode.ts b/src/openApi/v2/parser/getOperationResponseCode.ts deleted file mode 100644 index f34c99b75..000000000 --- a/src/openApi/v2/parser/getOperationResponseCode.ts +++ /dev/null @@ -1,16 +0,0 @@ -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; - } - - // Check if we can parse the code and return of successful. - if (/[0-9]+/g.test(value)) { - const code = parseInt(value); - if (Number.isInteger(code)) { - return Math.abs(code); - } - } - - return null; -}; diff --git a/src/openApi/v2/parser/getOperationResponses.ts b/src/openApi/v2/parser/getOperationResponses.ts index 7c6abddcc..a50fc6767 100644 --- a/src/openApi/v2/parser/getOperationResponses.ts +++ b/src/openApi/v2/parser/getOperationResponses.ts @@ -1,10 +1,10 @@ import type { OperationResponse } from '../../../types/client'; import { getRef } from '../../common/parser/getRef'; +import { getOperationResponseCode } from '../../common/parser/operation'; import type { OpenApi } from '../interfaces/OpenApi'; import type { OpenApiResponse } from '../interfaces/OpenApiResponse'; import type { OpenApiResponses } from '../interfaces/OpenApiResponses'; import { getOperationResponse } from './getOperationResponse'; -import { getOperationResponseCode } from './getOperationResponseCode'; export const getOperationResponses = (openApi: OpenApi, responses: OpenApiResponses): OperationResponse[] => { const operationResponses: OperationResponse[] = []; diff --git a/src/openApi/v3/parser/getOperationResponseCode.spec.ts b/src/openApi/v3/parser/getOperationResponseCode.spec.ts deleted file mode 100644 index 429e28bdd..000000000 --- a/src/openApi/v3/parser/getOperationResponseCode.spec.ts +++ /dev/null @@ -1,15 +0,0 @@ -import { describe, expect, it } from 'vitest'; - -import { getOperationResponseCode } from './getOperationResponseCode'; - -describe('getOperationResponseCode', () => { - it('should produce correct result', () => { - expect(getOperationResponseCode('')).toEqual(null); - expect(getOperationResponseCode('default')).toEqual(200); - expect(getOperationResponseCode('200')).toEqual(200); - expect(getOperationResponseCode('300')).toEqual(300); - expect(getOperationResponseCode('400')).toEqual(400); - expect(getOperationResponseCode('abc')).toEqual(null); - expect(getOperationResponseCode('-100')).toEqual(100); - }); -}); diff --git a/src/openApi/v3/parser/getOperationResponseCode.ts b/src/openApi/v3/parser/getOperationResponseCode.ts deleted file mode 100644 index f34c99b75..000000000 --- a/src/openApi/v3/parser/getOperationResponseCode.ts +++ /dev/null @@ -1,16 +0,0 @@ -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; - } - - // Check if we can parse the code and return of successful. - if (/[0-9]+/g.test(value)) { - const code = parseInt(value); - if (Number.isInteger(code)) { - return Math.abs(code); - } - } - - return null; -}; diff --git a/src/openApi/v3/parser/getOperationResponses.ts b/src/openApi/v3/parser/getOperationResponses.ts index 7c6abddcc..a50fc6767 100644 --- a/src/openApi/v3/parser/getOperationResponses.ts +++ b/src/openApi/v3/parser/getOperationResponses.ts @@ -1,10 +1,10 @@ import type { OperationResponse } from '../../../types/client'; import { getRef } from '../../common/parser/getRef'; +import { getOperationResponseCode } from '../../common/parser/operation'; import type { OpenApi } from '../interfaces/OpenApi'; import type { OpenApiResponse } from '../interfaces/OpenApiResponse'; import type { OpenApiResponses } from '../interfaces/OpenApiResponses'; import { getOperationResponse } from './getOperationResponse'; -import { getOperationResponseCode } from './getOperationResponseCode'; export const getOperationResponses = (openApi: OpenApi, responses: OpenApiResponses): OperationResponse[] => { const operationResponses: OperationResponse[] = []; From f310f2b98c3786f5a64c5014edb667df1077da36 Mon Sep 17 00:00:00 2001 From: Jordan Shatford Date: Tue, 26 Mar 2024 13:02:16 +1100 Subject: [PATCH 6/7] chore(parser): move getOperationErrors to common parser --- src/openApi/common/parser/operation.ts | 10 +++++++++- src/openApi/v2/parser/getOperation.ts | 3 +-- src/openApi/v2/parser/getOperationErrors.ts | 13 ------------- src/openApi/v3/parser/getOperationErrors.ts | 9 --------- src/openApi/v3/parser/operation.ts | 3 +-- 5 files changed, 11 insertions(+), 27 deletions(-) delete mode 100644 src/openApi/v2/parser/getOperationErrors.ts delete mode 100644 src/openApi/v3/parser/getOperationErrors.ts diff --git a/src/openApi/common/parser/operation.ts b/src/openApi/common/parser/operation.ts index a5f1e35ff..db391fa29 100644 --- a/src/openApi/common/parser/operation.ts +++ b/src/openApi/common/parser/operation.ts @@ -1,6 +1,6 @@ import camelCase from 'camelcase'; -import type { OperationResponse } from '../../../types/client'; +import type { OperationError, OperationResponse } from '../../../types/client'; import type { Config } from '../../../types/config'; import { reservedWords } from '../../../utils/reservedWords'; import { sanitizeOperationName, sanitizeOperationParameterName } from '../../../utils/sanitize'; @@ -61,3 +61,11 @@ export const getOperationResponseCode = (value: string | 'default'): number | nu return null; }; + +export const getOperationErrors = (operationResponses: OperationResponse[]): OperationError[] => + operationResponses + .filter(operationResponse => operationResponse.code >= 300 && operationResponse.description) + .map(response => ({ + code: response.code, + description: response.description!, + })); diff --git a/src/openApi/v2/parser/getOperation.ts b/src/openApi/v2/parser/getOperation.ts index dda1674de..ccd30db1f 100644 --- a/src/openApi/v2/parser/getOperation.ts +++ b/src/openApi/v2/parser/getOperation.ts @@ -1,10 +1,9 @@ import type { Operation, OperationParameters } from '../../../types/client'; import type { Config } from '../../../types/config'; -import { getOperationName, getOperationResponseHeader } from '../../common/parser/operation'; +import { getOperationErrors, getOperationName, getOperationResponseHeader } from '../../common/parser/operation'; import { toSortedByRequired } from '../../common/parser/sort'; import type { OpenApi } from '../interfaces/OpenApi'; import type { OpenApiOperation } from '../interfaces/OpenApiOperation'; -import { getOperationErrors } from './getOperationErrors'; import { getOperationParameters } from './getOperationParameters'; import { getOperationResponses } from './getOperationResponses'; import { getOperationResults } from './getOperationResults'; diff --git a/src/openApi/v2/parser/getOperationErrors.ts b/src/openApi/v2/parser/getOperationErrors.ts deleted file mode 100644 index 1a5f6bfca..000000000 --- a/src/openApi/v2/parser/getOperationErrors.ts +++ /dev/null @@ -1,13 +0,0 @@ -import type { OperationError, OperationResponse } from '../../../types/client'; - -/** - * - * @param operationResponses - */ -export const getOperationErrors = (operationResponses: OperationResponse[]): OperationError[] => - operationResponses - .filter(operationResponse => operationResponse.code >= 300 && operationResponse.description) - .map(response => ({ - code: response.code, - description: response.description!, - })); diff --git a/src/openApi/v3/parser/getOperationErrors.ts b/src/openApi/v3/parser/getOperationErrors.ts deleted file mode 100644 index 52a4950c2..000000000 --- a/src/openApi/v3/parser/getOperationErrors.ts +++ /dev/null @@ -1,9 +0,0 @@ -import type { OperationError, OperationResponse } from '../../../types/client'; - -export const getOperationErrors = (operationResponses: OperationResponse[]): OperationError[] => - operationResponses - .filter(operationResponse => operationResponse.code >= 300 && operationResponse.description) - .map(response => ({ - code: response.code, - description: response.description!, - })); diff --git a/src/openApi/v3/parser/operation.ts b/src/openApi/v3/parser/operation.ts index 59300bd2e..6b084c1ce 100644 --- a/src/openApi/v3/parser/operation.ts +++ b/src/openApi/v3/parser/operation.ts @@ -1,12 +1,11 @@ import type { Operation, OperationParameter, OperationParameters } from '../../../types/client'; import type { Config } from '../../../types/config'; import { getRef } from '../../common/parser/getRef'; -import { getOperationName, getOperationResponseHeader } from '../../common/parser/operation'; +import { getOperationErrors, getOperationName, getOperationResponseHeader } from '../../common/parser/operation'; import { toSortedByRequired } from '../../common/parser/sort'; import type { OpenApi } from '../interfaces/OpenApi'; import type { OpenApiOperation } from '../interfaces/OpenApiOperation'; import type { OpenApiRequestBody } from '../interfaces/OpenApiRequestBody'; -import { getOperationErrors } from './getOperationErrors'; import { getOperationParameters } from './getOperationParameters'; import { getOperationRequestBody } from './getOperationRequestBody'; import { getOperationResponses } from './getOperationResponses'; From 72befaa7781d87aba9a1aa1a283bf7f84bc43f9a Mon Sep 17 00:00:00 2001 From: Jordan Shatford Date: Tue, 26 Mar 2024 13:14:24 +1100 Subject: [PATCH 7/7] chore(tests): move all tests to __tests__ subdirectory --- src/openApi/v2/parser/{ => __tests__}/getServer.spec.ts | 2 +- .../v2/parser/{ => __tests__}/getServiceName.spec.ts | 2 +- src/openApi/v2/parser/{ => __tests__}/getServices.spec.ts | 2 +- src/openApi/v3/parser/{ => __tests__}/getModel.spec.ts | 6 +++--- src/openApi/v3/parser/{ => __tests__}/getServer.spec.ts | 2 +- 5 files changed, 7 insertions(+), 7 deletions(-) rename src/openApi/v2/parser/{ => __tests__}/getServer.spec.ts (92%) rename src/openApi/v2/parser/{ => __tests__}/getServiceName.spec.ts (91%) rename src/openApi/v2/parser/{ => __tests__}/getServices.spec.ts (97%) rename src/openApi/v3/parser/{ => __tests__}/getModel.spec.ts (95%) rename src/openApi/v3/parser/{ => __tests__}/getServer.spec.ts (97%) diff --git a/src/openApi/v2/parser/getServer.spec.ts b/src/openApi/v2/parser/__tests__/getServer.spec.ts similarity index 92% rename from src/openApi/v2/parser/getServer.spec.ts rename to src/openApi/v2/parser/__tests__/getServer.spec.ts index 8b3772c79..3da9b20e3 100644 --- a/src/openApi/v2/parser/getServer.spec.ts +++ b/src/openApi/v2/parser/__tests__/getServer.spec.ts @@ -1,6 +1,6 @@ import { describe, expect, it } from 'vitest'; -import { getServer } from './getServer'; +import { getServer } from '../getServer'; describe('getServer', () => { it('should produce correct result', () => { diff --git a/src/openApi/v2/parser/getServiceName.spec.ts b/src/openApi/v2/parser/__tests__/getServiceName.spec.ts similarity index 91% rename from src/openApi/v2/parser/getServiceName.spec.ts rename to src/openApi/v2/parser/__tests__/getServiceName.spec.ts index c1e7782f6..8925658b1 100644 --- a/src/openApi/v2/parser/getServiceName.spec.ts +++ b/src/openApi/v2/parser/__tests__/getServiceName.spec.ts @@ -1,6 +1,6 @@ import { describe, expect, it } from 'vitest'; -import { getServiceName } from './getServiceName'; +import { getServiceName } from '../getServiceName'; describe('getServiceName', () => { it('should produce correct result', () => { diff --git a/src/openApi/v2/parser/getServices.spec.ts b/src/openApi/v2/parser/__tests__/getServices.spec.ts similarity index 97% rename from src/openApi/v2/parser/getServices.spec.ts rename to src/openApi/v2/parser/__tests__/getServices.spec.ts index 0fbc2faba..842d4b865 100644 --- a/src/openApi/v2/parser/getServices.spec.ts +++ b/src/openApi/v2/parser/__tests__/getServices.spec.ts @@ -1,6 +1,6 @@ import { describe, expect, it } from 'vitest'; -import { getServices } from './getServices'; +import { getServices } from '../getServices'; describe('getServices', () => { it('should create a unnamed service if tags are empty', () => { diff --git a/src/openApi/v3/parser/getModel.spec.ts b/src/openApi/v3/parser/__tests__/getModel.spec.ts similarity index 95% rename from src/openApi/v3/parser/getModel.spec.ts rename to src/openApi/v3/parser/__tests__/getModel.spec.ts index 21846e0e5..280f9b9e5 100644 --- a/src/openApi/v3/parser/getModel.spec.ts +++ b/src/openApi/v3/parser/__tests__/getModel.spec.ts @@ -1,8 +1,8 @@ import { describe, expect, it } from 'vitest'; -import { reservedWords } from '../../../utils/reservedWords'; -import { getType } from '../../../utils/type'; -import { getModel } from './getModel'; +import { reservedWords } from '../../../../utils/reservedWords'; +import { getType } from '../../../../utils/type'; +import { getModel } from '../getModel'; const openApi = { openapi: '3.0', diff --git a/src/openApi/v3/parser/getServer.spec.ts b/src/openApi/v3/parser/__tests__/getServer.spec.ts similarity index 97% rename from src/openApi/v3/parser/getServer.spec.ts rename to src/openApi/v3/parser/__tests__/getServer.spec.ts index 0c13ee896..e26ef7d17 100644 --- a/src/openApi/v3/parser/getServer.spec.ts +++ b/src/openApi/v3/parser/__tests__/getServer.spec.ts @@ -1,6 +1,6 @@ import { describe, expect, it } from 'vitest'; -import { getServer } from './getServer'; +import { getServer } from '../getServer'; describe('getServer', () => { it('should produce correct result', () => {