Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

chore: cleanup files #140

Merged
merged 8 commits into from
Mar 26, 2024
198 changes: 198 additions & 0 deletions src/openApi/common/parser/__tests__/operation.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,198 @@
import { describe, expect, it } from 'vitest';

import { getOperationName, getOperationParameterName, getOperationResponseCode } from '../operation';

describe('getOperationName', () => {
const options1: Parameters<typeof getOperationName>[2] = {
operationId: true,
};

const options2: Parameters<typeof getOperationName>[2] = {
operationId: false,
};

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);
});
});

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);
});
});
71 changes: 71 additions & 0 deletions src/openApi/common/parser/operation.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
import camelCase from 'camelcase';

import type { OperationError, OperationResponse } from '../../../types/client';
import type { Config } from '../../../types/config';
import { reservedWords } from '../../../utils/reservedWords';
import { sanitizeOperationName, sanitizeOperationParameterName } from '../../../utils/sanitize';

/**
* Convert the input value to a correct operation (method) classname.
* This will use the operation ID - if available - and otherwise fallback
* on a generated name from the URL
*/
export const getOperationName = (
url: string,
method: string,
options: Pick<Config, 'operationId'>,
operationId?: string
): string => {
if (options.operationId && operationId) {
return camelCase(sanitizeOperationName(operationId).trim());
}

const urlWithoutPlaceholders = url
.replace(/[^/]*?{api-version}.*?\//g, '')
.replace(/{(.*?)}/g, 'by-$1')
.replace(/\//g, '-');

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');
};

export const getOperationResponseHeader = (operationResponses: OperationResponse[]): string | null => {
const header = operationResponses.find(operationResponses => operationResponses.in === 'header');
if (header) {
return header.name;
}
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;
};

export const getOperationErrors = (operationResponses: OperationResponse[]): OperationError[] =>
operationResponses
.filter(operationResponse => operationResponse.code >= 300 && operationResponse.description)
.map(response => ({
code: response.code,
description: response.description!,
}));
Original file line number Diff line number Diff line change
@@ -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', () => {
Expand Down
Original file line number Diff line number Diff line change
@@ -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', () => {
Expand Down
Original file line number Diff line number Diff line change
@@ -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', () => {
Expand Down
4 changes: 1 addition & 3 deletions src/openApi/v2/parser/getOperation.ts
Original file line number Diff line number Diff line change
@@ -1,12 +1,10 @@
import type { Operation, OperationParameters } from '../../../types/client';
import type { Config } from '../../../types/config';
import { getOperationName } from '../../../utils/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 { getOperationResponseHeader } from './getOperationResponseHeader';
import { getOperationResponses } from './getOperationResponses';
import { getOperationResults } from './getOperationResults';
import { getServiceName } from './getServiceName';
Expand Down
13 changes: 0 additions & 13 deletions src/openApi/v2/parser/getOperationErrors.ts

This file was deleted.

2 changes: 1 addition & 1 deletion src/openApi/v2/parser/getOperationParameter.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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 = {
Expand Down
19 changes: 0 additions & 19 deletions src/openApi/v2/parser/getOperationParameterName.spec.ts

This file was deleted.

13 changes: 0 additions & 13 deletions src/openApi/v2/parser/getOperationParameterName.ts

This file was deleted.

15 changes: 0 additions & 15 deletions src/openApi/v2/parser/getOperationResponseCode.spec.ts

This file was deleted.

Loading