|
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