Skip to content

Commit

Permalink
feat(parser): move sort by required to common parsing
Browse files Browse the repository at this point in the history
  • Loading branch information
jordanshatford committed Mar 21, 2024
1 parent c32eb39 commit 34b3ddb
Show file tree
Hide file tree
Showing 4 changed files with 53 additions and 19 deletions.
34 changes: 34 additions & 0 deletions src/openApi/common/parser/__tests__/sort.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
import { describe, expect, it } from 'vitest';

import { toSortedByRequired } from '../sort';

describe('sort', () => {
it.each([
{
input: [
{ id: 'test', isRequired: false },
{ id: 'test2', isRequired: true },
{ id: 'test3', isRequired: true },
],
expected: [
{ id: 'test2', isRequired: true },
{ id: 'test3', isRequired: true },
{ id: 'test', isRequired: false },
],
},
{
input: [
{ id: 'test', isRequired: false },
{ id: 'test2', isRequired: false },
{ id: 'test3', isRequired: true, default: 'something' },
],
expected: [
{ id: 'test', isRequired: false },
{ id: 'test2', isRequired: false },
{ id: 'test3', isRequired: true, default: 'something' },
],
},
])('should sort $input by required to produce $expected', ({ input, expected }) => {
expect(toSortedByRequired(input)).toEqual(expected);
});
});
13 changes: 13 additions & 0 deletions src/openApi/common/parser/sort.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
/**
* Sort list of values and ensure that required parameters are first so that we do not generate
* invalid types. Optional parameters cannot be positioned after required ones.
*/
export function toSortedByRequired<T extends { isRequired: boolean; default?: string }>(values: T[]): T[] {
return values.sort((a, b) => {
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;
});
}
13 changes: 3 additions & 10 deletions src/openApi/v2/parser/getOperation.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import type { Operation, OperationParameter, OperationParameters } from '../../../types/client';
import type { Operation, OperationParameters } from '../../../types/client';
import type { Config } from '../../../types/config';
import { getOperationName } from '../../../utils/operation';
import { toSortedByRequired } from '../../common/parser/sort';
import type { OpenApi } from '../interfaces/OpenApi';
import type { OpenApiOperation } from '../interfaces/OpenApiOperation';
import { getOperationErrors } from './getOperationErrors';
Expand All @@ -10,14 +11,6 @@ import { getOperationResponses } from './getOperationResponses';
import { getOperationResults } from './getOperationResults';
import { getServiceName } from './getServiceName';

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

export const getOperation = (
openApi: OpenApi,
url: string,
Expand Down Expand Up @@ -79,7 +72,7 @@ export const getOperation = (
});
}

operation.parameters = operation.parameters.sort(sortByRequired);
operation.parameters = toSortedByRequired(operation.parameters);

return operation;
};
12 changes: 3 additions & 9 deletions src/openApi/v3/parser/operation.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import type { Operation, OperationParameter, OperationParameters } from '../../.
import type { Config } from '../../../types/config';
import { getOperationName } from '../../../utils/operation';
import { getRef } from '../../common/parser/getRef';
import { toSortedByRequired } from '../../common/parser/sort';
import type { OpenApi } from '../interfaces/OpenApi';
import type { OpenApiOperation } from '../interfaces/OpenApiOperation';
import type { OpenApiRequestBody } from '../interfaces/OpenApiRequestBody';
Expand Down Expand Up @@ -109,15 +110,8 @@ export const getOperation = (
operation.parametersPath = mergeParameters(operation.parametersPath, pathParams.parametersPath);
operation.parametersQuery = mergeParameters(operation.parametersQuery, pathParams.parametersQuery);

// place required parameters first so we don't generate invalid types since
// optional parameters cannot be positioned before required ones
operation.parameters = operation.parameters.sort((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;
});
// Sort by required
operation.parameters = toSortedByRequired(operation.parameters);

return operation;
};

0 comments on commit 34b3ddb

Please sign in to comment.