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

Issue with codegenMercurius Function Triggering fastify-swagger Error #820

Open
luthfi-hh opened this issue Feb 19, 2024 · 0 comments
Open

Comments

@luthfi-hh
Copy link

luthfi-hh commented Feb 19, 2024

I encountered an error with the codegenMercurius function that seems to be causing a problem with fastify-swagger.
When I include the codegenMercurius function in my code, it triggers an error in swagger-ui.
However, upon removing the codegenMercurius function, the fastify-swagger functionality resumes working as expected.
This issue is affecting my workflow, and I would appreciate any insights or solutions to resolve it. Thank you.

Errors:

ERROR (37310): .swagger() must be called after .ready()
Screenshot 2024-02-19 at 17 56 32 Screenshot 2024-02-19 at 17 51 24

My Code (app.ts):

import { join } from 'path';
import FastifyEnv from '@fastify/env';
import FastifyCors from '@fastify/cors';
import FastifyAutoLoad, { AutoloadPluginOptions } from '@fastify/autoload';
import FastifySwagger from '@fastify/swagger';
import FastifySwaggerUI from '@fastify/swagger-ui';
import { FastifyPluginAsync, FastifyReply, FastifyRequest, FastifyServerOptions } from 'fastify';
import Mercurius from 'mercurius';
import { codegenMercurius } from 'mercurius-codegen'
import { resolvers } from './graphql/resolvers';
import { schema } from './graphql/schema';

export interface AppOptions extends FastifyServerOptions, Partial<AutoloadPluginOptions> {
}

// Pass --options via CLI arguments in command to enable these options.
const options: AppOptions = {
}

const buildContext = async (req: FastifyRequest, _reply: FastifyReply) => {
  return {
    authorization: req.headers.authorization
  }
}

type PromiseType<T> = T extends PromiseLike<infer U> ? U : T

declare module 'mercurius' {
  interface MercuriusContext extends PromiseType<ReturnType<typeof buildContext>> { }
}

const app: FastifyPluginAsync<AppOptions> = async (
  fastify,
  opts
): Promise<void> => {
  // This loads the .env file in the root directory.
  void fastify.register(FastifyEnv, {
    dotenv: true,
    schema: {
      type: 'object',
      required: [
        'NODE_ENV',
        'OPENSEARCH_NODE',
        'OPENSEARCH_USER',
        'OPENSEARCH_PASSWORD',
        'MYSQL_HOST',
        'MYSQL_PORT',
        'MYSQL_USER',
        'MYSQL_PASSWORD',
        'MYSQL_DATABASE',
        'MYSQL_CONNECTION_LIMIT',
      ],
    }
  })

  // This loads the CORS plugin.
  void fastify.register(FastifyCors, {
    origin: '*',
    methods: ['GET', 'PUT', 'POST', 'DELETE', 'OPTIONS', 'PATCH'],
  })

  // This loads fastify-swagger plugin.
  void fastify.register(FastifySwagger, {
    swagger: {
      info: {
        title: 'HH Search API',
        description: 'API for HH Search using OpenSearch',
        version: '0.1.0'
      },
      externalDocs: {
        url: 'https://swagger.io',
        description: 'Find more info here'
      },
      host: 'localhost:3003',
      schemes: ['http', 'https'],
      consumes: ['application/json'],
      produces: ['application/json'],
      tags: [
        { name: 'client', description: 'Client related end-points' },
        { name: 'server', description: 'Server related end-points' }
      ],
      definitions: {
        User: {
          type: 'object',
          required: ['id', 'email'],
          properties: {
            id: { type: 'string', format: 'uuid' },
            firstName: { type: 'string' },
            lastName: { type: 'string' },
            email: { type: 'string', format: 'email' }
          }
        }
      },
      securityDefinitions: {
        apiKey: {
          type: 'apiKey',
          name: 'apiKey',
          in: 'header'
        }
      }
    }
  })

  // This loads fastify-swagger-ui plugin.
  void fastify.register(FastifySwaggerUI, {
    routePrefix: '/docs',
    uiConfig: {
      docExpansion: 'full',
      deepLinking: false
    },
    uiHooks: {
      onRequest: function (request: any, reply: any, next: any) { next() },
      preHandler: function (request: any, reply: any, next: any) { next() }
    },
    staticCSP: true,
    transformStaticCSP: (header: any) => header,
    transformSpecification: (swaggerObject: any, request: any, reply: any) => { return swaggerObject },
    transformSpecificationClone: true
  })

  // This loads the mercurius plugin (GraphQL).
  void fastify.register(Mercurius, {
    schema,
    resolvers,
    jit: 1,
    graphiql: 'graphiql',
    context: buildContext
  })
  
  // This code causing fastify-swagger Errror
  codegenMercurius(fastify, {
    targetPath: './src/graphql/generated.ts',
    operationsGlob: './src/graphql/operations/*.gql',
    codegenConfig: {
      loadersCustomParentTypes: {
        Human: 'never',
      },
    },
  }).catch(console.error)

  
  // Do not touch the following lines

  // This loads all plugins defined in plugins
  // those should be support plugins that are reused
  // through your application
  void fastify.register(FastifyAutoLoad, {
    dir: join(__dirname, 'plugins'),
    options: opts
  })

  // This loads all plugins defined in routes
  // define your routes in one of these
  void fastify.register(FastifyAutoLoad, {
    dir: join(__dirname, 'routes'),
    options: opts
  })
};

export default app;
export { app, options }
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

1 participant