Skip to content

Commit ab6c5df

Browse files
authored
fix(openapi): keep required query flag for params (#910)
1 parent 99b9b43 commit ab6c5df

2 files changed

Lines changed: 48 additions & 4 deletions

File tree

lib/spec/openapi/utils.js

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -134,17 +134,18 @@ function convertExamplesArrayToObject (examples) {
134134
// For supported keys read:
135135
// https://swagger.io/docs/specification/describing-parameters/
136136
function plainJsonObjectToOpenapi3 (opts, container, jsonSchema, externalSchemas, securityIgnores = []) {
137-
const obj = convertJsonSchemaToOpenapi3(opts, resolveLocalRef(jsonSchema, externalSchemas))
137+
const localJsonSchema = resolveLocalRef(jsonSchema, externalSchemas)
138+
const obj = convertJsonSchemaToOpenapi3(opts, localJsonSchema)
138139
let toOpenapiProp
139140
switch (container) {
140141
case 'cookie':
141142
case 'header':
142143
case 'query':
143-
toOpenapiProp = function (propertyName, jsonSchemaElement) {
144+
toOpenapiProp = function (propertyName, jsonSchemaElement, required) {
144145
let result = {
145146
in: container,
146147
name: propertyName,
147-
required: jsonSchemaElement.required
148+
required
148149
}
149150

150151
const media = schemaToMedia(jsonSchemaElement)
@@ -194,7 +195,7 @@ function plainJsonObjectToOpenapi3 (opts, container, jsonSchema, externalSchemas
194195
return Object.keys(obj)
195196
.filter((propKey) => (!securityIgnores.includes(propKey)))
196197
.map((propKey) => {
197-
const jsonSchema = toOpenapiProp(propKey, obj[propKey])
198+
const jsonSchema = toOpenapiProp(propKey, obj[propKey], localJsonSchema[propKey]?.required)
198199
if (jsonSchema.schema) {
199200
// it is needed as required in schema is invalid prop - delete only if needed
200201
if (jsonSchema.schema.required !== undefined) delete jsonSchema.schema.required

test/spec/openapi/refs.test.js

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -308,6 +308,49 @@ test('uses examples if has property required in body', async (t) => {
308308
t.assert.deepStrictEqual(schema.parameters[0].in, 'query')
309309
})
310310

311+
test('renders required query parameter when property is a $ref', async (t) => {
312+
const fastify = Fastify()
313+
await fastify.register(fastifySwagger, { openapi: {} })
314+
315+
fastify.addSchema({
316+
$id: 'CoringUploadTypeApiModel',
317+
type: 'string',
318+
enum: ['health_safety', 'coring']
319+
})
320+
321+
fastify.get('/some-route', {
322+
schema: {
323+
query: {
324+
type: 'object',
325+
required: ['thing'],
326+
properties: {
327+
thing: { $ref: 'CoringUploadTypeApiModel' },
328+
other: { type: 'string' }
329+
}
330+
},
331+
response: {
332+
200: {
333+
type: 'object',
334+
properties: {
335+
hello: { type: 'string' }
336+
}
337+
}
338+
}
339+
}
340+
}, () => ({ hello: 'world' }))
341+
342+
await fastify.ready()
343+
344+
const openapiObject = fastify.swagger()
345+
await Swagger.validate(openapiObject)
346+
347+
const thingQueryParam = openapiObject.paths['/some-route'].get.parameters.find(parameter => parameter.name === 'thing')
348+
const otherQueryParam = openapiObject.paths['/some-route'].get.parameters.find(parameter => parameter.name === 'other')
349+
350+
t.assert.strictEqual(thingQueryParam.required, true)
351+
t.assert.strictEqual(otherQueryParam.required, false)
352+
})
353+
311354
test('renders $ref schema with enum in headers', async (t) => {
312355
const fastify = Fastify()
313356
await fastify.register(fastifySwagger, { openapi: {} })

0 commit comments

Comments
 (0)