|
5 | 5 | OpenAPI3Paths,
|
6 | 6 | OpenAPI3SchemaObject,
|
7 | 7 | OpenAPI3Schemas,
|
| 8 | + OpenAPI3Operation, |
| 9 | + Parameter, |
8 | 10 | SwaggerToTSOptions,
|
9 | 11 | } from "./types";
|
10 | 12 | import {
|
@@ -156,100 +158,117 @@ export default function generateTypesV3(
|
156 | 158 | return output;
|
157 | 159 | }
|
158 | 160 |
|
| 161 | + function transformParameters(parameters: Parameter[]): string { |
| 162 | + const allParameters: Record< |
| 163 | + string, |
| 164 | + Record<string, OpenAPI3Parameter | string> |
| 165 | + > = {}; |
| 166 | + |
| 167 | + let output = `parameters: {\n`; |
| 168 | + |
| 169 | + parameters.forEach((p) => { |
| 170 | + if ("$ref" in p) { |
| 171 | + const referencedValue = (p.$ref |
| 172 | + .substr(2) |
| 173 | + .split("/") |
| 174 | + .reduce( |
| 175 | + (value, property) => value[property], |
| 176 | + input |
| 177 | + ) as unknown) as OpenAPI3Parameter; |
| 178 | + |
| 179 | + if (!allParameters[referencedValue.in]) |
| 180 | + allParameters[referencedValue.in] = {}; |
| 181 | + |
| 182 | + allParameters[referencedValue.in][referencedValue.name] = transformRef( |
| 183 | + p.$ref |
| 184 | + ); |
| 185 | + return; |
| 186 | + } |
| 187 | + |
| 188 | + if (!allParameters[p.in]) allParameters[p.in] = {}; |
| 189 | + allParameters[p.in][p.name] = p; |
| 190 | + }); |
| 191 | + |
| 192 | + Object.entries(allParameters).forEach(([loc, locParams]) => { |
| 193 | + output += `"${loc}": {\n`; |
| 194 | + Object.entries(locParams).forEach(([paramName, paramProps]) => { |
| 195 | + if (typeof paramProps === "string") { |
| 196 | + output += `"${paramName}": ${paramProps}\n`; |
| 197 | + return; |
| 198 | + } |
| 199 | + if (paramProps.description) output += comment(paramProps.description); |
| 200 | + output += `"${paramName}"${ |
| 201 | + paramProps.required === true ? "" : "?" |
| 202 | + }: ${transform(paramProps.schema)};\n`; |
| 203 | + }); |
| 204 | + output += `}\n`; |
| 205 | + }); |
| 206 | + output += `}\n`; |
| 207 | + |
| 208 | + return output; |
| 209 | + } |
| 210 | + |
159 | 211 | function transformPaths(paths: OpenAPI3Paths): string {
|
160 | 212 | let output = "";
|
161 | 213 | Object.entries(paths).forEach(([path, methods]) => {
|
162 | 214 | output += `"${path}": {\n`;
|
163 |
| - Object.entries(methods).forEach(([method, operation]) => { |
164 |
| - if (operation.description) output += comment(operation.description); |
165 |
| - output += `"${method}": {\n`; |
166 |
| - |
167 |
| - // handle parameters |
168 |
| - if (operation.parameters) { |
169 |
| - output += `parameters: {\n`; |
170 |
| - const allParameters: Record< |
171 |
| - string, |
172 |
| - Record<string, OpenAPI3Parameter | string> |
173 |
| - > = {}; |
174 |
| - operation.parameters.forEach((p) => { |
175 |
| - if ("$ref" in p) { |
176 |
| - const referencedValue = (p.$ref |
177 |
| - .substr(2) |
178 |
| - .split("/") |
179 |
| - .reduce( |
180 |
| - (value, property) => value[property], |
181 |
| - input |
182 |
| - ) as unknown) as OpenAPI3Parameter; |
183 |
| - |
184 |
| - if (!allParameters[referencedValue.in]) |
185 |
| - allParameters[referencedValue.in] = {}; |
186 |
| - |
187 |
| - allParameters[referencedValue.in][ |
188 |
| - referencedValue.name |
189 |
| - ] = transformRef(p.$ref); |
190 |
| - return; |
191 |
| - } |
192 | 215 |
|
193 |
| - if (!allParameters[p.in]) allParameters[p.in] = {}; |
194 |
| - allParameters[p.in][p.name] = p; |
195 |
| - }); |
| 216 | + Object.entries(methods).forEach(([method, operation]) => { |
| 217 | + // skip the parameters "method" for shared parameters - we'll handle it later |
| 218 | + if (method !== "parameters") { |
| 219 | + operation = operation as OpenAPI3Operation; |
| 220 | + if (operation.description) output += comment(operation.description); |
| 221 | + output += `"${method}": {\n`; |
| 222 | + |
| 223 | + // handle operation parameters |
| 224 | + if (operation.parameters) { |
| 225 | + output += transformParameters(operation.parameters); |
| 226 | + } |
196 | 227 |
|
197 |
| - Object.entries(allParameters).forEach(([loc, locParams]) => { |
198 |
| - output += `"${loc}": {\n`; |
199 |
| - Object.entries(locParams).forEach(([paramName, paramProps]) => { |
200 |
| - if (typeof paramProps === "string") { |
201 |
| - output += `"${paramName}": ${paramProps}\n`; |
202 |
| - return; |
| 228 | + // handle requestBody |
| 229 | + if (operation.requestBody) { |
| 230 | + output += `requestBody: {\n`; |
| 231 | + Object.entries(operation.requestBody.content).forEach( |
| 232 | + ([contentType, { schema }]) => { |
| 233 | + output += `"${contentType}": ${transform(schema)};\n`; |
203 | 234 | }
|
204 |
| - if (paramProps.description) |
205 |
| - output += comment(paramProps.description); |
206 |
| - output += `"${paramName}"${ |
207 |
| - paramProps.required === true ? "" : "?" |
208 |
| - }: ${transform(paramProps.schema)};\n`; |
209 |
| - }); |
| 235 | + ); |
210 | 236 | output += `}\n`;
|
211 |
| - }); |
212 |
| - output += `}\n`; |
213 |
| - } |
| 237 | + } |
214 | 238 |
|
215 |
| - // handle requestBody |
216 |
| - if (operation.requestBody) { |
217 |
| - output += `requestBody: {\n`; |
218 |
| - Object.entries(operation.requestBody.content).forEach( |
219 |
| - ([contentType, { schema }]) => { |
220 |
| - output += `"${contentType}": ${transform(schema)};\n`; |
| 239 | + // handle responses |
| 240 | + output += `responses: {\n`; |
| 241 | + Object.entries(operation.responses).forEach( |
| 242 | + ([statusCode, response]) => { |
| 243 | + if (response.description) output += comment(response.description); |
| 244 | + if (!response.content || !Object.keys(response.content).length) { |
| 245 | + const type = |
| 246 | + statusCode === "204" || Math.floor(+statusCode / 100) === 3 |
| 247 | + ? "never" |
| 248 | + : "unknown"; |
| 249 | + output += `"${statusCode}": ${type};\n`; |
| 250 | + return; |
| 251 | + } |
| 252 | + output += `"${statusCode}": {\n`; |
| 253 | + Object.entries(response.content).forEach( |
| 254 | + ([contentType, encodedResponse]) => { |
| 255 | + output += `"${contentType}": ${transform( |
| 256 | + encodedResponse.schema |
| 257 | + )};\n`; |
| 258 | + } |
| 259 | + ); |
| 260 | + output += `}\n`; |
221 | 261 | }
|
222 | 262 | );
|
223 | 263 | output += `}\n`;
|
| 264 | + output += `}\n`; |
224 | 265 | }
|
225 |
| - |
226 |
| - // handle responses |
227 |
| - output += `responses: {\n`; |
228 |
| - Object.entries(operation.responses).forEach( |
229 |
| - ([statusCode, response]) => { |
230 |
| - if (response.description) output += comment(response.description); |
231 |
| - if (!response.content || !Object.keys(response.content).length) { |
232 |
| - const type = |
233 |
| - statusCode === "204" || Math.floor(+statusCode / 100) === 3 |
234 |
| - ? "never" |
235 |
| - : "unknown"; |
236 |
| - output += `"${statusCode}": ${type};\n`; |
237 |
| - return; |
238 |
| - } |
239 |
| - output += `"${statusCode}": {\n`; |
240 |
| - Object.entries(response.content).forEach( |
241 |
| - ([contentType, encodedResponse]) => { |
242 |
| - output += `"${contentType}": ${transform( |
243 |
| - encodedResponse.schema |
244 |
| - )};\n`; |
245 |
| - } |
246 |
| - ); |
247 |
| - output += `}\n`; |
248 |
| - } |
249 |
| - ); |
250 |
| - output += `}\n`; |
251 |
| - output += `}\n`; |
252 | 266 | });
|
| 267 | + |
| 268 | + if (methods.parameters) { |
| 269 | + // Handle shared parameters |
| 270 | + output += transformParameters(methods.parameters as Parameter[]); |
| 271 | + } |
253 | 272 | output += `}\n`;
|
254 | 273 | });
|
255 | 274 | return output;
|
|
0 commit comments