Skip to content

Commit 38b9097

Browse files
henhaldrwpow
andauthored
Inherit parameters from path item to its operations. (#530)
* Inherit parameters from path item to its operations. A path item may declare common parameters to all operations outside of the operation map. If this is the case, all operations should inherit those parameters and merge them with any operation specific parameters. In case of conflicting parameters, the one defined in the operation has precedence over path item parameters. * Removing ?. operator * Remove lingering .only on operation tests * Fix rebase error, update tests Co-authored-by: Drew Powers <[email protected]>
1 parent 6537a31 commit 38b9097

File tree

5 files changed

+136
-10
lines changed

5 files changed

+136
-10
lines changed

src/transform/index.ts

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { OperationObject } from "../types";
1+
import { OperationObject, PathItemObject } from "../types";
22
import { comment, tsReadonly } from "../utils";
33
import { transformHeaderObjMap } from "./headers";
44
import { transformOperationObj } from "./operation";
@@ -17,7 +17,7 @@ export function transformAll(schema: any, { immutableTypes, rawSchema, version }
1717

1818
let output = "";
1919

20-
let operations: Record<string, OperationObject> = {};
20+
let operations: Record<string, { operation: OperationObject; pathItem: PathItemObject }> = {};
2121

2222
// --raw-schema mode
2323
if (rawSchema) {
@@ -128,9 +128,10 @@ export function transformAll(schema: any, { immutableTypes, rawSchema, version }
128128

129129
output += `export interface operations {\n`; // open operations
130130
if (Object.keys(operations).length) {
131-
Object.entries(operations).forEach(([operationId, operation]) => {
131+
Object.entries(operations).forEach(([operationId, { operation, pathItem }]) => {
132132
if (operation.description) output += comment(operation.description); // handle comment
133133
output += ` ${readonly}"${operationId}": {\n ${transformOperationObj(operation, {
134+
pathItem,
134135
globalParameters: (schema.components && schema.components.parameters) || schema.parameters,
135136
immutableTypes,
136137
version,

src/transform/operation.ts

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { OperationObject, ParameterObject, RequestBody } from "../types";
1+
import { OperationObject, ParameterObject, PathItemObject, RequestBody } from "../types";
22
import { comment, isRef, transformRef, tsReadonly } from "../utils";
33
import { transformParametersArray } from "./parameters";
44
import { transformResponsesObj } from "./responses";
@@ -9,8 +9,10 @@ export function transformOperationObj(
99
{
1010
globalParameters,
1111
immutableTypes,
12+
pathItem = {},
1213
version,
1314
}: {
15+
pathItem?: PathItemObject;
1416
globalParameters?: Record<string, ParameterObject>;
1517
immutableTypes: boolean;
1618
version: number;
@@ -20,8 +22,9 @@ export function transformOperationObj(
2022

2123
let output = "";
2224

23-
if (operation.parameters) {
24-
output += ` ${readonly}parameters: {\n ${transformParametersArray(operation.parameters, {
25+
if (operation.parameters || pathItem.parameters) {
26+
const parameters = (pathItem.parameters || []).concat(operation.parameters || []);
27+
output += ` ${readonly}parameters: {\n ${transformParametersArray(parameters, {
2528
globalParameters,
2629
immutableTypes,
2730
version,

src/transform/paths.ts

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ import { transformParametersArray } from "./parameters";
66
interface TransformPathsObjOption {
77
globalParameters: Record<string, ParameterObject>;
88
immutableTypes: boolean;
9-
operations: Record<string, OperationObject>;
9+
operations: Record<string, { operation: OperationObject; pathItem: PathItemObject }>;
1010
version: number;
1111
}
1212

@@ -39,15 +39,15 @@ export function transformPathsObj(
3939

4040
// if operation has operationId, abstract into top-level operations object
4141
if (operation.operationId) {
42-
output += ` ${readonly}"${method}": operations["${operation.operationId}"];\n`;
43-
operations[operation.operationId] = operation;
42+
operations[operation.operationId] = { operation, pathItem };
43+
output += ` ${readonly}"${method}": operations["${operation.operationId}"];\n`;
4444
return;
4545
}
46-
4746
// otherwise, inline operation
4847
output += ` ${readonly}"${method}": {\n ${transformOperationObj(operation, {
4948
globalParameters,
5049
immutableTypes,
50+
pathItem,
5151
version,
5252
})}\n }\n`;
5353
});

tests/operation.test.ts

Lines changed: 112 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -118,3 +118,115 @@ describe("requestBodies", () => {
118118
);
119119
});
120120
});
121+
122+
describe("parameters", () => {
123+
it("operation parameters only", () => {
124+
expect(
125+
transformOperationObj(
126+
{
127+
parameters: [
128+
{
129+
in: "path",
130+
name: "p1",
131+
schema: {
132+
type: "string",
133+
},
134+
},
135+
],
136+
},
137+
{
138+
version: 3,
139+
immutableTypes: false,
140+
pathItem: {},
141+
}
142+
).trim()
143+
).toBe(`parameters: {
144+
path: {
145+
"p1"?: string;
146+
}
147+
148+
}`);
149+
});
150+
151+
it("inherited path parameters only", () => {
152+
expect(
153+
transformOperationObj(
154+
{},
155+
{
156+
version: 3,
157+
immutableTypes: false,
158+
pathItem: {
159+
parameters: [
160+
{
161+
in: "path",
162+
name: "p1",
163+
schema: {
164+
type: "string",
165+
},
166+
},
167+
],
168+
},
169+
}
170+
).trim()
171+
).toBe(`parameters: {
172+
path: {
173+
"p1"?: string;
174+
}
175+
176+
}`);
177+
});
178+
179+
it("inherited path parameters and operation parameters", () => {
180+
expect(
181+
transformOperationObj(
182+
{
183+
parameters: [
184+
{
185+
in: "path",
186+
name: "p1",
187+
schema: {
188+
type: "string",
189+
},
190+
},
191+
{
192+
in: "path",
193+
name: "p2",
194+
schema: {
195+
type: "number",
196+
},
197+
},
198+
],
199+
},
200+
{
201+
version: 3,
202+
immutableTypes: false,
203+
pathItem: {
204+
parameters: [
205+
{
206+
in: "path",
207+
name: "p2",
208+
schema: {
209+
type: "string",
210+
},
211+
},
212+
{
213+
in: "path",
214+
name: "p3",
215+
schema: {
216+
type: "string",
217+
},
218+
},
219+
],
220+
},
221+
}
222+
).trim()
223+
).toBe(`parameters: {
224+
path: {
225+
"p2"?: number;
226+
"p3"?: string;
227+
"p1"?: string;
228+
}
229+
230+
}`);
231+
});
232+
});

tests/paths.test.ts

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -442,6 +442,11 @@ describe("transformPathsObj", () => {
442442
expect(transform(parametersSchema)).toBe(`export interface paths {
443443
"/{example}": {
444444
get: {
445+
parameters: {
446+
path: {
447+
example: string;
448+
};
449+
};
445450
responses: {};
446451
};
447452
parameters: {
@@ -455,6 +460,11 @@ describe("transformPathsObj", () => {
455460
expect(transform(parametersSchema, { immutableTypes: true })).toBe(`export interface paths {
456461
readonly "/{example}": {
457462
readonly get: {
463+
readonly parameters: {
464+
readonly path: {
465+
readonly example: string;
466+
};
467+
};
458468
readonly responses: {};
459469
};
460470
readonly parameters: {

0 commit comments

Comments
 (0)