From ba45dd4a85d6715996e0a7196f906b83a1d680dc Mon Sep 17 00:00:00 2001 From: Luis Fernando Planella Gonzalez Date: Sun, 12 Nov 2023 15:43:08 -0300 Subject: [PATCH] Specific parameters should override general ones Fixes #297 --- lib/operation.ts | 31 +++++++++++++++++++++---------- lib/parameter.ts | 1 + test/all-operations.json | 7 +++++++ test/all-operations.spec.ts | 12 ++++++------ 4 files changed, 35 insertions(+), 16 deletions(-) diff --git a/lib/operation.ts b/lib/operation.ts index 6249568..c5f1574 100644 --- a/lib/operation.ts +++ b/lib/operation.ts @@ -46,10 +46,21 @@ export class Operation { this.methodName = spec['x-operation-name'] || this.id; // Add both the common and specific parameters - this.parameters = [ - ...this.collectParameters(pathSpec.parameters), - ...this.collectParameters(spec.parameters), + const allParams = [ + ...this.collectParameters(false, pathSpec.parameters), + ...this.collectParameters(true, spec.parameters), ]; + // Maybe there were duplicated parameters? In this case, let specific parameters replace the general ones + this.parameters = []; + allParams.forEach(param => { + let skip = false; + if (!param.specific) { + skip = !!allParams.find(p => p !== param && p.name === param.name && p.specific); + } + if (!skip) { + this.parameters.push(param); + } + }); if (this.parameters.find(p => p.required)) { this.parametersRequired = true; } @@ -84,11 +95,10 @@ export class Operation { return false; } - private collectParameters(params: (ParameterObject | ReferenceObject)[] | undefined): Parameter[] { + private collectParameters(specific: boolean, params: (ParameterObject | ReferenceObject)[] | undefined): Parameter[] { const result: Parameter[] = []; if (params) { for (let param of params) { - if (param.$ref) { param = resolveRef(this.openApi, param.$ref); } @@ -96,11 +106,12 @@ export class Operation { if (param.in === 'cookie') { this.logger.warn(`Ignoring cookie parameter ${this.id}.${param.name} as cookie parameters cannot be sent in XmlHttpRequests.`); - } else if (this.paramIsNotExcluded(param)) { - result.push(new Parameter(param as ParameterObject, this.options, this.openApi)); + } else if (!this.paramIsExcluded(param)) { + const parameter = new Parameter(param as ParameterObject, this.options, this.openApi); + parameter.specific = specific; + result.push(parameter); } } - } return result; } @@ -119,9 +130,9 @@ export class Operation { }); } - private paramIsNotExcluded(param: ParameterObject): boolean { + private paramIsExcluded(param: ParameterObject): boolean { const excludedParameters = this.options.excludeParameters || []; - return !excludedParameters.includes(param.name); + return excludedParameters.includes(param.name); } private collectContent(desc: ContentObject | undefined): Content[] { diff --git a/lib/parameter.ts b/lib/parameter.ts index d5febc7..283ce4d 100644 --- a/lib/parameter.ts +++ b/lib/parameter.ts @@ -17,6 +17,7 @@ export class Parameter { style?: string; explode?: boolean; parameterOptions: string; + specific = false; constructor(public spec: ParameterObject, options: Options, openApi: OpenAPIObject) { this.name = spec.name; diff --git a/test/all-operations.json b/test/all-operations.json index a6191de..6ad4b3a 100644 --- a/test/all-operations.json +++ b/test/all-operations.json @@ -68,6 +68,13 @@ ], "description": "Path 1 GET description", "parameters": [ + { + "name": "common1", + "description": "Specific common param 1", + "schema": { + "$ref": "#/components/schemas/RefString" + } + }, { "name": "get1", "description": "GET param 1", diff --git a/test/all-operations.spec.ts b/test/all-operations.spec.ts index 28d3e8d..c85ef85 100644 --- a/test/all-operations.spec.ts +++ b/test/all-operations.spec.ts @@ -204,12 +204,12 @@ describe('Generation tests using all-operations.json', () => { expect(operation.method).toBe('get'); expect(operation.parameters.length).toBe(9); // 2 shared, 7 own const params = operation.parameters; - expect(params[0].name).toBe('common1'); - expect(params[0].type).toBe('RefString'); - expect(params[0].in).toBe('query'); - expect(params[1].name).toBe('common2'); - expect(params[1].in).toBe('header'); - expect(params[1].type).toBe('RefObject'); + expect(params[0].name).toBe('common2'); + expect(params[0].in).toBe('header'); + expect(params[0].type).toBe('RefObject'); + expect(params[1].name).toBe('common1'); + expect(params[1].type).toBe('RefString'); + expect(params[1].in).toBe('query'); expect(params[2].name).toBe('get1'); expect(params[2].type).toBe('RefString'); expect(params[2].in).toBe('query');