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

Apollo 4 support #2270

Open
dev-mich opened this issue Oct 18, 2022 · 9 comments · May be fixed by #2444
Open

Apollo 4 support #2270

dev-mich opened this issue Oct 18, 2022 · 9 comments · May be fixed by #2444

Comments

@dev-mich
Copy link

Is your feature request related to a problem? Please describe.

Hi guys, is there any plan to support the latest apollo server version 4?

tried this morning to have things working with @apollo/server 4.0.1 and graphql-modules 2.1.0 with no luck

@lewisgj
Copy link

lewisgj commented Dec 22, 2022

createSchemaForApollo is marked as deprecated but it works for me. It would still be nice to know what the 'official' / intended solution might be.

Example code:

const application = createApplication({
  modules: [echoModule]
});

const server = new ApolloServer(
  {
    schema: application.createSchemaForApollo()
  });

To elaborate on a specific problem I bumped into:

The Apollo Server 4 migration instructions suggest that gateway can be used where custom executors were previously passed to the constructor.

It's not enough to work by itself though and the Apollo Server type definitions forbid passing more than gateway.

@ardatan
Copy link
Collaborator

ardatan commented Dec 22, 2022

Then it should work like;

const application = createApplication({
  modules: [echoModule]
});
new ApolloServer({
  gateway: {
    async load() {
      return { executor: application.createApolloExecutor() };
    },
    onSchemaLoadOrUpdate() {
      return () => {};
    },
    async stop() {},
  },
});

@lewisgj
Copy link

lewisgj commented Dec 22, 2022

I agree - that's what I expected to work, but it didn't in practice. Here's my minimal example - hopefully it's reproducible enough!
https://github.com/lewisgj/graphql-modules-apollo-4

@ardatan
Copy link
Collaborator

ardatan commented Dec 26, 2022

Could you try the following code;

const server = new ApolloServer({
    // schema: application.createSchemaForApollo() // graphql-modules has marked this deprecated, but works with Apollo Server 4.
    // Recommended approach is to use gateway:
    gateway: {
        async load() {
            return { executor: application.createApolloExecutor() };
        },
        onSchemaLoadOrUpdate(callback) {
            callback({ apiSchema: application.schema } as any);
            return () => {};
        },
        async stop() {},
    },
});

@lewisgj
Copy link

lewisgj commented Dec 29, 2022

This does work, thanks - I try to write Typescript as strict as possible so it's not 100% ideal to have any there, but it'd be enough for me to link back to this issue as justification for either approach I think.

Without the any I get:

TS2345: Argument of type '{ apiSchema: GraphQLSchema; }' is not assignable to parameter of type '{ apiSchema: GraphQLSchema; coreSupergraphSdl: string; }'.   Property 'coreSupergraphSdl' is missing in type '{ apiSchema: GraphQLSchema; }' but required in type '{ apiSchema: GraphQLSchema; coreSupergraphSdl: string; }

but I guess it's more of a question for Apollo and what that field is supposed to do / whether the typing should be as strict.

@amochuko
Copy link

@ardatan I had to drill into the source code to get understand that Gateway Interface.

Thanks for that.

@ajzozakiewicz
Copy link

ajzozakiewicz commented Jan 11, 2023

It seems like there is still an issue, the apollo-server error functions do not like something about the gateway config setup.

Here is my code:

const server = new ApolloServer({
      // See this issue for more info on this solution: https://github.com/Urigo/graphql-modules/issues/2270
      // schema: application.createSchemaForApollo() // graphql-modules has marked this deprecated, but works with Apollo Server 4.
      // Recommended approach is to use gateway:
      gateway: {
        async load() {
          return { executor: moduleApp.createApolloExecutor() }
        },
        onSchemaLoadOrUpdate(callback) {
          const apiSchema = { apiSchema: moduleApp.schema } as any
          callback(apiSchema)
          return () => {}
        },
        async stop() {}
      },
      formatError: (formattedError: GraphQLFormattedError, error: any) => {
        console.log('FORMATTED ERROR -----> ', formattedError)
        console.log('ERROR -----> ', error)
        return formattedError
      }      
})

await server.start()

app.use(`${basePath}/graphql`, expressMiddleware(server))

It never seems to make it to the formatError function before blowing up when an error occurs. With the above setup you can simply query for a field that does not exist to generate the below errors...

I receive the following errors:

Unexpected error processing request: TypeError: Cannot assign to read only property 'name' of object 'GraphQLError

Followed by:

TypeError: Cannot read property 'code' of undefined
    at enrichError (/node_modules/@apollo/server/dist/cjs/errorNormalize.js:34:43)
    at /node_modules/@apollo/server/dist/cjs/errorNormalize.js:19:28
    at Array.map (<anonymous>)
    at normalizeAndFormatErrors (/node_modules/@apollo/server/dist/cjs/errorNormalize.js:13:33)
    at ApolloServer.errorResponse (/node_modules/@apollo/server/dist/cjs/ApolloServer.js:542:102)
    at ApolloServer.executeHTTPGraphQLRequest (node_modules/@apollo/server/dist/cjs/ApolloServer.js:538:25)
    at processTicksAndRejections (internal/process/task_queues.js:95:5)
^[[1;2C

any ideas?

@Urigo
Copy link
Owner

Urigo commented Feb 6, 2023

We would love to accept a PR to fix that, thank you!

@MatamandoKalilani
Copy link

Could you try the following code;

const server = new ApolloServer({
    // schema: application.createSchemaForApollo() // graphql-modules has marked this deprecated, but works with Apollo Server 4.
    // Recommended approach is to use gateway:
    gateway: {
        async load() {
            return { executor: application.createApolloExecutor() };
        },
        onSchemaLoadOrUpdate(callback) {
            callback({ apiSchema: application.schema } as any);
            return () => {};
        },
        async stop() {},
    },
});

This works for Queries and Mutations. But I'm still getting this error when trying subscriptions

"Cannot read properties of undefined (reading 'ɵgetModuleContext')"

any help with implementing subscriptions with this gateway implementation.

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

Successfully merging a pull request may close this issue.

7 participants