Skip to content

Commit ae4cddc

Browse files
authored
OpenAPI bug fixes (github#18625)
1 parent 09c3acb commit ae4cddc

File tree

9 files changed

+6580
-3640
lines changed

9 files changed

+6580
-3640
lines changed

lib/rest/static/decorated/api.github.com.json

+906-525
Large diffs are not rendered by default.

lib/rest/static/decorated/ghes-2.18.json

+600-289
Large diffs are not rendered by default.

lib/rest/static/decorated/ghes-2.19.json

+876-511
Large diffs are not rendered by default.

lib/rest/static/decorated/ghes-2.20.json

+878-513
Large diffs are not rendered by default.

lib/rest/static/decorated/ghes-2.21.json

+880-515
Large diffs are not rendered by default.

lib/rest/static/decorated/ghes-2.22.json

+911-544
Large diffs are not rendered by default.

lib/rest/static/decorated/ghes-3.0.json

+739-366
Large diffs are not rendered by default.

lib/rest/static/decorated/github.ae.json

+701-365
Large diffs are not rendered by default.

script/rest/utils/operation.js

+89-12
Original file line numberDiff line numberDiff line change
@@ -166,8 +166,43 @@ module.exports = class Operation {
166166
}
167167

168168
async renderBodyParameterDescriptions () {
169-
const bodyParamsObject = get(this, 'requestBody.content.application/json.schema.properties', {})
170-
const requiredParams = get(this, 'requestBody.content.application/json.schema.required', [])
169+
let bodyParamsObject = get(this, 'requestBody.content.application/json.schema.properties', {})
170+
let requiredParams = get(this, 'requestBody.content.application/json.schema.required', [])
171+
const oneOfObject = get(this, 'requestBody.content.application/json.schema.oneOf', undefined)
172+
173+
// oneOf is an array of input parameter options, so we need to either
174+
// use the first option or munge the options together.
175+
if (oneOfObject) {
176+
const firstOneOfObject = oneOfObject[0]
177+
const allOneOfAreObjects = oneOfObject
178+
.filter(elem => elem.type === 'object')
179+
.length === oneOfObject.length
180+
181+
// TODO: Remove this check
182+
// This operation shouldn't have a oneOf in this case, it needs to be
183+
// removed from the schema in the github/github repo.
184+
if (this.operationId === 'checks/create') {
185+
delete bodyParamsObject.oneOf
186+
} else if (allOneOfAreObjects) {
187+
// When all of the oneOf objects have the `type: object` we
188+
// need to display all of the parameters.
189+
// This merges all of the properties and required values into the
190+
// first requestBody object.
191+
for (let i = 1; i < oneOfObject.length; i++) {
192+
Object.assign(firstOneOfObject.properties, oneOfObject[i].properties)
193+
requiredParams = firstOneOfObject.required
194+
.concat(oneOfObject[i].required)
195+
}
196+
bodyParamsObject = firstOneOfObject.properties
197+
} else if (oneOfObject) {
198+
// When a oneOf exists but the `type` differs, the case has historically
199+
// been that the alternate option is an array, where the first option
200+
// is the array as a property of the object. We need to ensure that the
201+
// first option listed is the most comprehensive and preferred option.
202+
bodyParamsObject = firstOneOfObject.properties
203+
requiredParams = firstOneOfObject.required
204+
}
205+
}
171206

172207
this.bodyParameters = await getBodyParams(bodyParamsObject, requiredParams)
173208
}
@@ -211,16 +246,57 @@ async function getBodyParams (paramsObject, requiredParams) {
211246
param.rawType = param.type
212247
param.rawDescription = param.description
213248

214-
// e.g. array of strings
215-
param.type = param.type === 'array'
216-
? `array of ${param.items.type}s`
217-
: param.type
249+
// Stores the types listed under the `Type` column in the `Parameters`
250+
// table in the REST API docs. When the parameter contains oneOf
251+
// there are multiple acceptable parameters that we should list.
252+
const paramArray = []
253+
254+
const oneOfArray = param.oneOf
255+
const isOneOfObjectOrArray = oneOfArray
256+
? oneOfArray.filter(elem => elem.type !== 'object' || elem.type !== 'array')
257+
: false
258+
259+
// When oneOf has the type array or object, the type is defined
260+
// in a child object
261+
if (oneOfArray && isOneOfObjectOrArray.length > 0) {
262+
// Store the defined types
263+
paramArray.push(oneOfArray
264+
.filter(elem => elem.type)
265+
.map(elem => elem.type)
266+
)
267+
268+
// If an object doesn't have a description, it is invalid
269+
const oneOfArrayWithDescription = oneOfArray.filter(elem => elem.description)
270+
271+
// Use the parent description when set, otherwise enumerate each
272+
// description in the `Description` column of the `Parameters` table.
273+
if (!param.description && oneOfArrayWithDescription.length > 1) {
274+
param.description = oneOfArray
275+
.filter(elem => elem.description)
276+
.map(elem => `**Type ${elem.type}** - ${elem.description}`)
277+
.join('\n\n')
278+
} else if (!param.description && oneOfArrayWithDescription.length === 1) {
279+
// When there is only on valid description, use that one.
280+
param.description = oneOfArrayWithDescription[0].description
281+
}
282+
}
283+
284+
// Arrays require modifying the displayed type (e.g., array of strings)
285+
if (param.type === 'array') {
286+
if (param.items.type) paramArray.push(`array of ${param.items.type}s`)
287+
if (param.items.oneOf) {
288+
paramArray.push(param.items.oneOf
289+
.map(elem => `array of ${elem.type}s`)
290+
)
291+
}
292+
} else if (param.type) {
293+
paramArray.push(param.type)
294+
}
218295

219-
// e.g. object or null
220-
param.type = param.nullable
221-
? `${param.type} or null`
222-
: param.type
296+
if (param.nullable) paramArray.push('nullable')
223297

298+
param.type = paramArray.flat().join(' or ')
299+
param.description = param.description || ''
224300
const isRequired = requiredParams && requiredParams.includes(param.name)
225301
const requiredString = isRequired ? '**Required**. ' : ''
226302
param.description = await renderContent(requiredString + param.description)
@@ -245,8 +321,9 @@ async function getBodyParams (paramsObject, requiredParams) {
245321
}
246322

247323
async function getChildParamsGroup (param) {
248-
// only objects and arrays of objects ever have child params
249-
if (!(param.rawType === 'array' || param.rawType === 'object')) return
324+
// only objects, arrays of objects, anyOf, allOf, and oneOf have child params
325+
if (!(param.rawType === 'array' || param.rawType === 'object' || param.oneOf)) return
326+
if (param.oneOf && !param.oneOf.filter(param => param.type === 'object' || param.type === 'array')) return
250327
if (param.items && param.items.type !== 'object') return
251328

252329
const childParamsObject = param.rawType === 'array' ? param.items.properties : param.properties

0 commit comments

Comments
 (0)