graphile / crystal

🔮 Graphile's Crystal Monorepo; home to Grafast, PostGraphile, pg-introspection, pg-sql2 and much more!
https://graphile.org/
Other
12.63k stars 572 forks source link

Nest.js server support in grafserv? #2254

Open dourkk opened 4 days ago

dourkk commented 4 days ago

Summary

Hi, we are using Nestjs, and we would like to migrate from v4 to v5, but we were not able to find info about postgraphileMiddleware.graphqlRouteHandler is it still supported or what is the new way to achieve the following?

Additional context

Here are our postgraphile.middleware.ts config

import { postgraphile } from 'postgraphile';
import ConnectionFilterPlugin from 'postgraphile-plugin-connection-filter';
import PgAggregatesPlugin from '@graphile/pg-aggregates';
import { getConfig } from '../config';

const postgraphileMiddleware = postgraphile(
  `postgres://${process.env.SVC_USERNAME}:${process.env.SVC_PASSWORD}@${process.env.DB_HOST ?? getConfig('database_url')}:5432/${process.env.DB_DATABASE}`,
  getConfig('schema'),
  {
    graphiql: true,
    enhanceGraphiql: true,
    graphqlRoute: '/api/graphql',
    graphiqlRoute: '/api/graphiql',
    retryOnInitFail: true,
    appendPlugins: [ConnectionFilterPlugin, PgAggregatesPlugin],
    watchPg: true,
    ownerConnectionString: `postgres://${process.env.ROOT_USERNAME}:${process.env.ROOT_PASSWORD}@${process.env.DB_HOST ?? getConfig('database_url')}:5432/${process.env.DB_DATABASE}`,
  },
);

export default postgraphileMiddleware;

Here is our postgraphile.controller.ts controller

import { Controller, Post, Get, Req, Next, Res } from '@nestjs/common';
import { Request, Response, NextFunction } from 'express';
import { PostGraphileResponseNode } from 'postgraphile';
import postgraphileMiddleware from './postgraphile.middleware';
import { RequiredPermissions } from '../guards/authorization.guard';
import { USER_ROLE } from '../guards/token-roles';
import { ApiBearerAuth } from '@nestjs/swagger';

@RequiredPermissions({ role: USER_ROLE })
@ApiBearerAuth()
@Controller('/')
export class PostGraphileController {
  @Get('graphiql')
  graphiql(@Req() request: Request, @Res() response: Response, @Next() next: NextFunction) {
    return postgraphileMiddleware.graphiqlRouteHandler!(
      new PostGraphileResponseNode(request, response, next),
    );
  }

  @Post('graphql')
  graphql(@Req() request: Request, @Res() response: Response, @Next() next: NextFunction) {
    return postgraphileMiddleware.graphqlRouteHandler(
      new PostGraphileResponseNode(request, response, next),
    );
  }
}
benjie commented 3 days ago

Hello! Ideally someone would build a Nest.js optimized server adaptor for Grafserv, like these: https://github.com/graphile/crystal/tree/main/grafast/grafserv/src/servers

But given you had it working in V4 it's likely you can hack something together using the node adaptor; see

https://postgraphile.org/postgraphile/next/usage-library

and

https://grafast.org/grafserv/servers/node

But rather than doing serv.addTo(server) you can use serv's handlers directly:

Doing so will mean that certain plugin middlewares won't be called, so be aware of that. If you want to submit a Nest.js adaptor I'd be happy to pair program with you for a couple of hours to help develop it if you want; the session would be public and recorded to help future adaptors be written.

If you're going alone or taking the hack approach, use TypeScript to guide you and/or read the source starting here: https://github.com/graphile/crystal/blob/ae2bf43f4b3ccc0c545f52addbdd4e4e1db40206/grafast/grafserv/src/servers/node/index.ts#L295

dourkk commented 3 days ago

Thanks for the answer @benjie 🙏

For context we wanted to do the migration, because we were getting this error recently in our logs

 Error: Cannot use GraphQLSchema "{ __validationErrors: [], description: undefined, extensions: {}, ast │
│                                                                                                        │
│ Ensure that there is only one instance of "graphql" in the node_modules                                │
│ directory. If different versions of "graphql" are the dependencies of other                            │
│ relied on modules, use "resolutions" to ensure only one version is installed.                          │
│                                                                                                        │
│ https://yarnpkg.com/en/docs/selective-version-resolutions                                              │
│                                                                                                        │
│ Duplicate "graphql" modules cannot be used at the same time since different                            │
│ versions may have different capabilities and behavior. The data from one                               │
│ version used in the function from another could produce confusing and                                  │
│ spurious results.                                                                                      │
│     at instanceOf (/usr/src/app/node_modules/postgraphile/node_modules/graphql/jsutils/instanceOf.js:3 │
│     at isSchema (/usr/src/app/node_modules/postgraphile/node_modules/graphql/type/schema.js:42:34)     │
│     at assertSchema (/usr/src/app/node_modules/postgraphile/node_modules/graphql/type/schema.js:46:8)  │
│     at validateSchema (/usr/src/app/node_modules/postgraphile/node_modules/graphql/type/validate.js:42 │
│     at assertValidSchema (/usr/src/app/node_modules/postgraphile/node_modules/graphql/type/validate.js │
│     at Object.validate (/usr/src/app/node_modules/postgraphile/node_modules/graphql/validation/validat │
│     at parseQuery (/usr/src/app/node_modules/postgraphile/build/postgraphile/http/createPostGraphileHt │
│     at /usr/src/app/node_modules/postgraphile/build/postgraphile/http/createPostGraphileHttpRequestHan │
│     at Array.map (<anonymous>)                                                                         │
│     at graphqlRouteHandler (/usr/src/app/node_modules/postgraphile/build/postgraphile/http/createPostG │
│ Stream canceled read tcp some_ip:60935->some_ip:443: use of closed network connection for  │

We tried to resolve the graphql dependency to 15.9.0, but still getting the same issue 🥲

IMG_0239

  "resolutions": {
    "graphql": "15.9.0"
  }
benjie commented 2 days ago

Try also adding an explicit dependency on graphql@15.x, and consider downgrading msw so it uses graphql@15.x too.