diff --git a/lib/spec/openapi/utils.js b/lib/spec/openapi/utils.js index 11863616..4b0e6871 100644 --- a/lib/spec/openapi/utils.js +++ b/lib/spec/openapi/utils.js @@ -98,6 +98,13 @@ function transformDefsToComponents (jsonSchema) { Object.keys(jsonSchema[key]).forEach(function (prop) { jsonSchema[key][prop] = transformDefsToComponents(jsonSchema[key][prop]) }) + // definitions are not allowed in openapi schema, so we mutate them to properties + } else if (key === 'definitions') { + jsonSchema.properties = { + ...transformDefsToComponents(jsonSchema[key]), + ...jsonSchema.properties + } + delete jsonSchema[key] } else if (key === '$ref') { // replace the top-lvl path jsonSchema[key] = jsonSchema[key].replace('definitions', 'components/schemas') @@ -406,29 +413,11 @@ function prepareOpenapiSchemas (schemas, ref) { .reduce((res, [name, schema]) => { const _ = { ...schema } - // 'definitions' keyword is not supported by openapi in schema item - // but we can receive it from json-schema input - if (_.definitions) { - _.properties = { - ..._.definitions, - ..._.properties - } - } - - // ref.resolve call does 3 things: - // modifies underlying cache of ref - // adds 'definitions' with resolved schema(which we don't need here anymore) - // mutates $ref to point to the resolved schema - // ($ref will be mutated again by transformDefsToComponents) const resolvedRef = ref.resolve(_, { externalSchemas: [schemas] }) // swagger doesn't accept $id on components schemas - // $ids are needed by ref.resolve to check the URI - // definitions are added by resolve, but they are not needed, as we resolve - // the $ref to already existing schemas in components.schemas using method below - // therefore, we delete both $id and definitions at the end of the process + // $ids are needed only for ref.resolve to check the URI delete resolvedRef.$id - delete resolvedRef.definitions const components = transformDefsToComponents(resolvedRef) diff --git a/test/spec/openapi/refs.js b/test/spec/openapi/refs.js index 83e2283f..242cea9b 100644 --- a/test/spec/openapi/refs.js +++ b/test/spec/openapi/refs.js @@ -283,26 +283,21 @@ test('uses examples if has property required in body', async (t) => { t.same(schema.parameters[0].in, 'query') }) -test('support schema $ref inside the json-schema definitions', async (t) => { +test('support absolute $ref inside the json-schema definitions', async (t) => { const fastify = Fastify() await fastify.register(fastifySwagger, openapiOption) fastify.register(async (instance) => { instance.addSchema({ $id: 'NestedSchema', - properties: { - id: { type: 'string' } - }, definitions: { SchemaA: { - $id: 'SchemaA', type: 'object', properties: { id: { type: 'string' } } }, SchemaB: { - $id: 'SchemaB', type: 'object', properties: { example: { $ref: 'NestedSchema#/definitions/SchemaA' } @@ -310,7 +305,7 @@ test('support schema $ref inside the json-schema definitions', async (t) => { } } }) - instance.post('/url1', { schema: { body: { $ref: 'NestedSchema#/definitions/SchemaB' }, response: { 200: { $ref: 'NestedSchema#/definitions/SchemaA' } } } }, () => {}) + instance.post('/url1/:test', { schema: { body: { $ref: 'NestedSchema#/definitions/SchemaB' }, params: { $ref: 'NestedSchema#/definitions/SchemaA' }, response: { 200: { $ref: 'NestedSchema#/definitions/SchemaA' } } } }, () => {}) }) await fastify.ready()