Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

$refs in arrays don't work #612

Open
2 tasks done
kyc3 opened this issue Jun 8, 2022 · 6 comments
Open
2 tasks done

$refs in arrays don't work #612

kyc3 opened this issue Jun 8, 2022 · 6 comments

Comments

@kyc3
Copy link

kyc3 commented Jun 8, 2022

Prerequisites

  • I have written a descriptive issue title
  • I have searched existing issues to ensure the bug has not already been reported

Fastify version

3.29.0

Plugin version

6.1.0

Node.js version

v16.13.0

Operating system

macOS

Operating system version (i.e. 20.04, 11.3, 10)

12.3.1

Description

Hello everyone,

I was trying to reference my array items to an existing definition in the same schema when I got this error:

Could not resolve reference: Could not resolve pointer: /definitions/<name>

However, the reference does exist, as it works when I reference it as an object instead of an array.

I have the following (artificial) scenario: I have an object in the following format:

{
id: string
}

I want to be able to expose this as a single object and in an array. If I reference to that, only the object one works.
If you look at the below image, you see that SingleId works exactly as it's supposed to, while ListOfIds only shows "string". In addition, you see the error on top.

image

See the steps to reproduce below.

Steps to Reproduce


  const swaggerConfig = {
    routePrefix: 'swagger',
    swagger: {
      info: {
        title: 'Test swagger',
        description: 'Testing the Fastify swagger API!',
        version: '0.1.0',
      },
      externalDocs: {
        url: 'https://swagger.io',
        description: 'Find more info here',
      },
      tags: [{ name: 'user', description: 'User related end-points' }],
    },

    uiConfig: {
      docExpansion: 'full',
      deepLinking: false,
    },
    hideUntagged: false,
    staticCSP: true,
    exposeRoute: true,
  };


  const userSchema = {
    $id: 'user',
    title: 'User',
    type: 'object',
    $schema: 'http://json-schema.org/draft-07/schema#',
    properties: {
      ListOfIds: {
        $ref: '#/definitions/ListOfIds',
      },
      SingleId: {
        $ref: '#/definitions/SingleId',
      },
    },
    definitions: {
      id: {
        type: 'number',
        description: 'user id',
      },
      ListOfIds: {
        type: 'array',
        title: 'ListOfIds',
        items: {
          $ref: '#/definitions/id',
        },
      },
      SingleId: {
        type: 'object',
        title: 'SingleId',
        properties: {
          id: { $ref: '#/definitions/id' },
        },
      },
    },
  };

  fastify.addSchema(userSchema);

  await fastify.register(FastifyPlugin(FastifySwagger), {
    ...swaggerConfig,

    refResolver: {
      buildLocalReference(json, _baseUri, _fragment, _i) {
        return `${json.$id}`;
      },
    },
  });



  fastify.get(
    '/userList',
    {
      schema: {
        description: 'Get the list of ids',
        tags: ['user'],
        summary: 'Returns the list of ids',
        response: {
          '200': {
            description: 'Successful response',
            $ref: 'user#',
          },
        },
      },
    },
    () => {}
  );

  fastify.ready(() => {
    fastify.swagger();
  });


Expected Behavior

I would expect that I can reference to model in an array (by doing so as mentioned above - putting a $ref in items).

@mcollina
Copy link
Member

@climba03003 wdyt?

@climba03003
Copy link
Member

I think it would be something related to json-schema-resolver.
Schema $ref resolution really a pain part inside this plugin.

@jluczak
Copy link

jluczak commented Jul 7, 2022

Having exactly the same issue 🥲

@promisetochi
Copy link

Had this issue for over a day, thought I was doing something wrong.

Eventually had to dereference with https://github.com/APIDevTools/json-schema-ref-parser

@sittingbool
Copy link

sittingbool commented Aug 30, 2022

Hey, works for me. But I need to give the $ref as the exact same string as the $id was.

fastify.addSchema({
        $id: 'User',
        type: 'object',
        description: 'User basic data',
        properties: UserSchema,
        required: omitOptional(Object.keys(UserSchema)),
    });
    const AcceptedInvitationsSchema = {
      ...
      users: { type: 'array', $ref: 'User' }
    }

@toomuchdesign
Copy link

Since fastify-swagger by default generates OpenAPI components as def-${counter}, and this breaks internal relative $ref path resolution. Eg:

components:
  schemas:
    def-0:
      type: object
      required:
        - name
      properties:
        name:
          type: string
      title: /components/schemas/Pet
    def-1:
      type: array
      maxItems: 100
      items:
        # "Pet" component is defined as "#/components/def-0/Pet" above
        # OpenAPI will try to resolve at "#/components/schemas/Pet", instead
        $ref: "#/components/schemas/Pet"
      title: /components/schemas/Pets

In order to let OpenAPI resolve $ref paths I had to configure fastify-swagger's refResolver options to generate OpenAPI components.schema definition as expected:

/**
 * This is needed since Fastify by default names components as "def-${i}"
 * https://github.com/fastify/fastify-swagger?tab=readme-ov-file#managing-your-refs
 */
refResolver: {
  buildLocalReference: (json, baseUri, fragment, i) => {
    const OPEN_API_COMPONENTS_SCHEMAS_PATH = '/components/schemas/';
    if (
      typeof json.$id === 'string' &&
      json.$id.startsWith(OPEN_API_COMPONENTS_SCHEMAS_PATH)
    ) {
      const name = json.$id.replace(OPEN_API_COMPONENTS_SCHEMAS_PATH, '');
      if (name) {
        return name;
      }
    }

    // @TODO Support naming component schemas different than "components.schema"
    return `def-${i}`;
  },
},

The implementation should be adjusted based on the actual registered schemas.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

7 participants