diff --git a/lib/spec/openapi/utils.js b/lib/spec/openapi/utils.js index b3931a49..773fe930 100644 --- a/lib/spec/openapi/utils.js +++ b/lib/spec/openapi/utils.js @@ -82,7 +82,7 @@ function transformDefsToComponents (jsonSchema) { if (typeof jsonSchema === 'object' && jsonSchema !== null) { // Handle patternProperties, that is not part of OpenAPI definitions if (jsonSchema.patternProperties) { - jsonSchema.additionalProperties = Object.values(jsonSchema.patternProperties)[0]; + jsonSchema.additionalProperties = Object.values(jsonSchema.patternProperties)[0] delete jsonSchema.patternProperties } else if (jsonSchema.const) { // OAS 3.1 supports `const` but it is not supported by `swagger-ui` diff --git a/lib/util/common.js b/lib/util/common.js index 4802a254..da592534 100644 --- a/lib/util/common.js +++ b/lib/util/common.js @@ -3,6 +3,7 @@ const fs = require('fs') const path = require('path') const Ref = require('json-schema-resolver') +const cloner = require('rfdc')({ proto: true, circles: false }) const { rawRequired } = require('../symbols') const { xConsume } = require('../constants') @@ -34,7 +35,7 @@ function addHook (fastify, pluginOptions) { return { routes, Ref () { - const externalSchemas = Array.from(sharedSchemasMap.values()) + const externalSchemas = cloner(Array.from(sharedSchemasMap.values())) return Ref(Object.assign( { applicationUri: 'todo.com' }, pluginOptions.refResolver, diff --git a/package.json b/package.json index c5e1bce9..370153e4 100644 --- a/package.json +++ b/package.json @@ -62,7 +62,8 @@ "fastify-static": "^4.0.0", "js-yaml": "^4.0.0", "json-schema-resolver": "^1.3.0", - "openapi-types": "^10.0.0" + "openapi-types": "^10.0.0", + "rfdc": "^1.3.0" }, "standard": { "ignore": [ diff --git a/test/spec/openapi/refs.js b/test/spec/openapi/refs.js index 113474c5..c27ace70 100644 --- a/test/spec/openapi/refs.js +++ b/test/spec/openapi/refs.js @@ -135,6 +135,36 @@ test('support $ref in response schema', async (t) => { await Swagger.validate(openapiObject) }) +test('support $ref for enums in other schemas', async (t) => { + const fastify = Fastify() + + const enumSchema = { $id: 'order', anyOf: [{ type: 'string', const: 'foo' }, { type: 'string', const: 'bar' }] } + const enumRef = { $ref: 'order' } + const objectWithEnumSchema = { $id: 'object', type: 'object', properties: { type: enumRef }, required: ['type'] } + + await fastify.register(fastifySwagger, openapiOption) + await fastify.register(async (instance) => { + instance.addSchema(enumSchema) + instance.addSchema(objectWithEnumSchema) + instance.post('/', { schema: { body: { type: 'object', properties: { order: { $ref: 'order' } } } } }, async () => ({ result: 'OK' })) + }) + + await fastify.ready() + + const responseBeforeSwagger = await fastify.inject({ method: 'POST', url: '/', payload: { order: 'foo' } }) + + t.equal(responseBeforeSwagger.statusCode, 200) + const openapiObject = fastify.swagger() + + t.equal(typeof openapiObject, 'object') + + await Swagger.validate(openapiObject) + + const responseAfterSwagger = await fastify.inject({ method: 'POST', url: '/', payload: { order: 'foo' } }) + + t.equal(responseAfterSwagger.statusCode, 200) +}) + test('support nested $ref schema : complex case without modifying buildLocalReference', async (t) => { const fastify = Fastify() fastify.register(fastifySwagger, { openapi: {} })