Skip to content

Commit

Permalink
feat: merge operation and path level parameters (#184)
Browse files Browse the repository at this point in the history
* refactor: minor internal improvements

* feat: merge operation and path level path params
  • Loading branch information
toomuchdesign authored Mar 3, 2024
1 parent 00bcd6a commit 8ce3621
Show file tree
Hide file tree
Showing 8 changed files with 71 additions and 31 deletions.
5 changes: 5 additions & 0 deletions .changeset/sweet-hats-enjoy.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"openapi-ts-json-schema": minor
---

Merge operation and path level path parameters
5 changes: 2 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -145,11 +145,10 @@ Read [plugins documentation 📖](./docs/plugins.md).

## Todo

- Consider merging "operation" and "path" parameters definition
- Consider removing required `definitionPathsToGenerateFrom` option in favour of exporting the whole OpenAPI definitions based on the structure defined in specs
- Consider adding a way to customize the values of the generated JSON schema ids. This could be beneficial even in case of multiple schemas being merged with plugins
- Improve external `#ref`s handling (currently being inlined and duplicated)
- Find a way to merge multiple different OpenApi definitions consistently
- Improve external `#ref`s handling
- Consider adding a way to customize the values of the generated JSON schema ids. This could be beneficial even in case of multiple schemas being merged with plugins
- Consider implementing an option to inline circular $refs with a configurable nesting level

[ci-badge]: https://github.com/toomuchdesign/openapi-ts-json-schema/actions/workflows/ci.yml/badge.svg
Expand Down
4 changes: 2 additions & 2 deletions src/openapiToTsJsonSchema.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import {
makeTsJsonSchemaFiles,
REF_SYMBOL,
convertOpenApiToJsonSchema,
convertOpenApiParameters,
convertOpenApiPathsParameters,
addSchemaToMetaData,
pathToRef,
formatTypeScript,
Expand Down Expand Up @@ -108,7 +108,7 @@ export async function openapiToTsJsonSchema({
},
);

const jsonSchema = convertOpenApiParameters(dereferencedJsonSchema);
const jsonSchema = convertOpenApiPathsParameters(dereferencedJsonSchema);
const schemaMetaDataMap: SchemaMetaDataMap = new Map();

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import {
import type { JSONSchema } from '../types';

type OpenAPIParameters = Parameters<typeof _convertParametersToJSONSchema>[0];

function convertParametersToJSONSchema(
openApiParameters: OpenAPIParameters,
): OpenAPIParametersAsJSONSchema {
Expand All @@ -22,35 +23,45 @@ function convertParametersToJSONSchema(
}

/**
* Parameters field can only be found in:
* Paths parameters field can only be found in:
* - paths[path].parameters
* - paths[path][operation].parameters
*
* https://swagger.io/docs/specification/describing-parameters/
*
* @NOTE The schema must be dereferenced since openapi-jsonschema-parameters
* doesn't handle $refs
*/
export function convertOpenApiParameters(schema: JSONSchema): JSONSchema {
export function convertOpenApiPathsParameters(schema: JSONSchema): JSONSchema {
if ('paths' in schema) {
for (const path in schema.paths) {
const pathSchema = schema.paths[path];

/**
* Path level parameters
* These could be merged with operation params:
* https://swagger.io/docs/specification/describing-parameters/#common
* Common path parameters
* https://swagger.io/docs/specification/describing-parameters/#common-for-path
*/
if ('parameters' in pathSchema) {
const pathParameters =
'parameters' in pathSchema ? pathSchema.parameters : [];

if (pathParameters.length) {
pathSchema.parameters = convertParametersToJSONSchema(
pathSchema.parameters,
);
}

// Operation level parameters
/**
* Operation path parameters
* https://swagger.io/docs/specification/describing-parameters/#path-parameters
*/
for (const operation in pathSchema) {
const operationSchema = pathSchema[operation];
if ('parameters' in operationSchema) {
operationSchema.parameters = convertParametersToJSONSchema(
operationSchema.parameters,
);
// Merge operation and common path parameters
operationSchema.parameters = convertParametersToJSONSchema([
...pathParameters,
...operationSchema.parameters,
]);
}
}
}
Expand Down
2 changes: 1 addition & 1 deletion src/utils/convertOpenApiToJsonSchema.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import type { OpenApiSchema } from '../types';
export function convertOpenApiToJsonSchema(schema: OpenApiSchema) {
/**
* @openapi-contrib/openapi-schema-to-json-schema doesn't convert definitions by default,
* Here we convert all direct children of components
* Here we convert all direct children of components object:
* https://swagger.io/specification/#components-object
* https://github.com/openapi-contrib/openapi-schema-to-json-schema#definitionkeywords-array
*/
Expand Down
2 changes: 1 addition & 1 deletion src/utils/index.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
export { patchJsonSchema } from './makeTsJsonSchema/patchJsonSchema';
export { makeTsJsonSchema } from './makeTsJsonSchema';
export { convertOpenApiParameters } from './convertOpenApiParameters';
export { convertOpenApiPathsParameters } from './convertOpenApiPathsParameters';
export { convertOpenApiToJsonSchema } from './convertOpenApiToJsonSchema';
export { makeTsJsonSchemaFiles } from './makeTsJsonSchemaFiles';
export { refToPath } from './refToPath';
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,23 +17,35 @@ paths:
- schema:
type: string
in: header
name: path-headers-param-1
name: path-header-param
required: true
description: path-headers-param-1 description
description: path-header-param description
- schema:
type: string
in: header
name: path-header-param-overridden-at-operation-level
description: path-header-param-overridden-at-operation-level description
get:
parameters:
# Header
- schema:
type: string
in: header
name: headers-param-1
name: header-param-1
required: true
description: headers-param-1 description
description: header-param-1 description
- schema:
$ref: '#/components/schemas/Answer'
in: header
name: headers-param-2
name: header-param-2
required: true
description: headers-param-2 description
description: header-param-2 description
- schema:
type: number
in: header
name: path-header-param-overridden-at-operation-level
description: path-header-param-overridden-at-operation-level description
# Body
- schema:
type: string
enum:
Expand All @@ -42,12 +54,14 @@ paths:
in: body
required: true
description: Body param description
# Path
- schema:
type: string
in: path
name: path-param-1
required: true
description: Path param description
# Query
- schema:
type: string
in: query
Expand Down
27 changes: 19 additions & 8 deletions test/parameters.test.ts → test/paths-parameters.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,10 @@ import { describe, it, expect } from 'vitest';
import { fixtures, makeTestOutputPath } from './test-utils';
import { openapiToTsJsonSchema } from '../src';

describe('OpenAPI parameters', () => {
it('Transforms parameters array into a JSON schema record', async () => {
describe('OpenAPI paths parameters', () => {
it('Transforms parameters array into valid JSON schema', async () => {
const { outputPath } = await openapiToTsJsonSchema({
openApiSchema: path.resolve(fixtures, 'parameters/specs.yaml'),
openApiSchema: path.resolve(fixtures, 'paths-parameters/specs.yaml'),
outputPath: makeTestOutputPath('parameters'),
definitionPathsToGenerateFrom: ['paths'],
silent: true,
Expand All @@ -20,9 +20,12 @@ describe('OpenAPI parameters', () => {
parameters: {
headers: {
type: 'object',
required: ['path-headers-param-1'],
required: ['path-header-param'],
properties: {
'path-headers-param-1': {
'path-header-param': {
type: 'string',
},
'path-header-param-overridden-at-operation-level': {
type: 'string',
},
},
Expand All @@ -33,15 +36,23 @@ describe('OpenAPI parameters', () => {
headers: {
type: 'object',
properties: {
'headers-param-1': {
'header-param-1': {
type: 'string',
},
'headers-param-2': {
'header-param-2': {
type: 'string',
enum: ['yes', 'no'],
},
// Merges path level parameters
'path-header-param': {
type: 'string',
},
// Overrides path level parameters
'path-header-param-overridden-at-operation-level': {
type: 'number',
},
},
required: ['headers-param-1', 'headers-param-2'],
required: ['path-header-param', 'header-param-1', 'header-param-2'],
},
body: { type: 'string', enum: ['foo', 'bar'] },
path: {
Expand Down

0 comments on commit 8ce3621

Please sign in to comment.