fastify / fastify-swagger

Swagger documentation generator for Fastify
MIT License
910 stars 200 forks source link

Add new option for reference component name #713

Closed imjuni closed 1 year ago

imjuni commented 1 year ago

Prerequisites

🚀 Feature Proposal

Add new option swagger reference component name generate $id instead of def-.

eg.

Generated def-

{
  "def-0": {
    "title": "IPokemonDto",
    "type": "object",
    "properties": {
      "id": {
        "type": "number",
        "description": "pokemon id"
      },
      "is_default": {
        "type": "boolean"
      },
      "base_experience": {
        "type": "number"
      },
      "height": {
        "type": "number",
        "description": "pokemon height"
      },
      "location_area_encounters": {
        "type": "string"
      },
      "name": {
        "type": "string"
      },
      "order": {
        "type": "number"
      },
      "species": {
        "$ref": "#/components/schemas/def-4"
      }
    },
    "required": [
      "id",
      "is_default",
      "base_experience",
      "height",
      "location_area_encounters",
      "name",
      "order",
      "species"
    ],
    "description": "Pokemon DTO"
  }
}
fastify.register(fastifySwagger, {
  openapi: {
      info: {
        title: 'fastify boilerplate',
        version: '0.2.0',
      },
    },
referenceNameUseId: true, // example of new option
});

generate like this,

{
  "IPokemonDto": {
    "title": "IPokemonDto",
}

Motivation

I try to use swagger-typescript-api or openapi-generator.

I apply swagger-typescript-api on my project and I found some enhance point from fastify-swagger.

Below source-code is auto generated TypeScript interface.

/**
 * IPokemonDto
 * Pokemon DTO
 */
export interface Def2 {
  /** pokemon id */
  id: number;
  is_default: boolean;
  base_experience: number;
  /** pokemon height */
  height: number;
  location_area_encounters: string;
  name: string;
  order: number;
  species: Def4;
}

I think that more useful export interface IPokemonDto { ... } then export interface Def2 { ... }.

In fastify-swagger,

// lib/mode/dynamic.js

opts = Object.assign(
    {},
    {
      exposeRoute: false,
      hiddenTag: "X-HIDDEN",
      hideUntagged: false,
      stripBasePath: true,
      openapi: null,
      swagger: {},
      transform: null,
      refResolver: {
        buildLocalReference(json, baseUri, fragment, i) {
          if (!json.title && json.$id) {
            json.title = json.$id;
          }

          // add new option
          if (opts.referenceNameUseId && json.$id) {
            return json.$id
          }

          return `def-${i}`;
        },
      },
    },
    opts
  );

Example

I create example repo.

Reproduce this issue,

git checkout https://github.com/maeumjs/maeum/tree/feature/swagger-typescript-api
cd maeum
npm install
npm run dev

Open new terminal and change directory maeum.

node scripts/api-gen.cjs

And you can found auto generated document from resources/apis/generated.

climba03003 commented 1 year ago

I would say a no here.

You can provide your custom buildLocalReference through the options. It is already dynamic enough to achieve any feature. Add another option just for it is overkill.

imjuni commented 1 year ago

@climba03003 your right. I set custom buildLocalReference and I get wished documents.

I will close this issue. Thank you 👍

arthurfiorette commented 10 months ago

Hey @climba03003, what do you think of changing the default impl of buildLocalReference? Something like:

function buildLocalReference(json: any, _: unknown, __: unknown, i: number) {|
  if (!json.title && json.$id) {
    json.title = json.$id
  }

  return json.title || json.$id || `def-${i}`
}

We already define our schema title or ID, using an auto generated def-X seems to be a bad default, specially in production systems that generates code with this spec. I know we can override the buildLocalReference, but overriding it everywhere shows it could have a better default impl.

"components": {
    "schemas": {
      "def-0": {},
      "def-1": {},
      "def-2": {},
      // ...
    }
  },

Current implementation:

https://github.com/fastify/fastify-swagger/blob/2dc46ffbb729a41ba454a845667fd6e78a29857c/lib/mode/dynamic.js#L17-L22

I'm open to do a PR :)