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

Plugins: no server; interface contravariant; no factory functions #6814

Merged
merged 1 commit into from Aug 15, 2022

Conversation

glasser
Copy link
Member

@glasser glasser commented Aug 15, 2022

Previously on version-4, we had made ApolloServerPlugin<TContext>
"invariant" in TContext via the new in out annotation. That's
because we had added a server field to GraphQLRequestContext and
GraphQLServerContext.

The issue here is that because you can invoke
server.executeOperation(op, contextValue), then a
ApolloServerPlugin<BaseContext> was not assignable to
ApolloServerPlugin<SomeSpecificContext>, because the former was able
to call requestContext.executeOperation(op, {}), and a server whose
context has additional required fields could not load this plugin. This
essentially meant that you couldn't have a single object (not created by
a generic function or generic class) that was a plugin that works with
any server, even if it doesn't actually care about context values at
all.

When trying to dogfood AS4 it became clear that this was annoying. So
let's fix it by removing server from those objects and making
ApolloServerPlugin "contravariant" instead. This means that plugins
can only receive contextValue, not send it. And so
ApolloServerPlugin<BaseContext> (a plugin that doesn't bother to read
any fields from contextValue) can be assigned to
ApolloServerPlugin<SpecificContext> (a plugin that is permitted to
read specific fields on contextValue, though it may choose not to).

After removing server, restore logger (now readonly) and cache
to GraphQLRequestContext and GraphQLServerContext (cache is
actually new to GraphQLServerContext in AS4). They had previously been
removed for redundancy.

This un-does the fix to #6264. If your plugin needs access to the
server object, you can just pass it to your plugin's
constructor/factory yourself. This wasn't an option in AS3 because there
was no server.addPlugin method... or actually, you could do it with
the plugin factory feature.

Note that we do leave ApolloServer<TContext> as invariant in
TContext, for the reasons described in a comment above the class.

While we're at it, remove the unnecessary ability to specify plugins as
factory functions. As far as we know, the main use case for this feature
is to refer to the ApolloServer itself in the expression creating the
plugin, but the new addPlugin method lets you do the same thing.
Reducing the number of ways to specify constructor options helps keep
type errors simpler.

@netlify
Copy link

netlify bot commented Aug 15, 2022

Deploy Preview for apollo-server-docs ready!

Name Link
🔨 Latest commit f5b4133
🔍 Latest deploy log https://app.netlify.com/sites/apollo-server-docs/deploys/62fab5d5bd4d3d0008dd8e91
😎 Deploy Preview https://deploy-preview-6814--apollo-server-docs.netlify.app
📱 Preview on mobile
Toggle QR Code...

QR Code

Use your smartphone camera to open QR code link.

To edit notification comments on pull requests, go to your Netlify site settings.

@glasser glasser changed the base branch from main to version-4 August 15, 2022 18:17
@codesandbox-ci
Copy link

codesandbox-ci bot commented Aug 15, 2022

This pull request is automatically built and testable in CodeSandbox.

To see build info of the built libraries, click here or the icon next to each commit SHA.

Latest deployment of this branch, based on commit f5b4133:

Sandbox Source
Apollo Server Typescript Configuration
Apollo Server Configuration

@glasser glasser force-pushed the glasser/apollo-server-plugin-contravariant branch from b2611d5 to 5015fe0 Compare August 15, 2022 21:01
Previously on `version-4`, we had made `ApolloServerPlugin<TContext>`
"invariant" in `TContext` via the new `in out` annotation. That's
because we had added a `server` field to `GraphQLRequestContext` and
`GraphQLServerContext`.

The issue here is that because you can invoke
`server.executeOperation(op, contextValue)`, then a
`ApolloServerPlugin<BaseContext>` was not assignable to
`ApolloServerPlugin<SomeSpecificContext>`, because the former was able
to call `requestContext.executeOperation(op, {})`, and a server whose
context has additional required fields could not load this plugin. This
essentially meant that you couldn't have a single object (not created by
a generic function or generic class) that was a plugin that works with
any server, even if it doesn't actually care about context values at
all.

When trying to dogfood AS4 it became clear that this was annoying. So
let's fix it by removing `server` from those objects and making
`ApolloServerPlugin` "contravariant" instead. This means that plugins
can only *receive* `contextValue`, not *send* it. And so
`ApolloServerPlugin<BaseContext>` (a plugin that doesn't bother to read
any fields from `contextValue`) can be assigned to
`ApolloServerPlugin<SpecificContext>` (a plugin that is permitted to
read specific fields on `contextValue`, though it may choose not to).

After removing `server`, restore `logger` (now `readonly`) and `cache`
to `GraphQLRequestContext` and `GraphQLServerContext` (`cache` is
actually new to `GraphQLServerContext` in AS4). They had previously been
removed for redundancy.

This un-does the fix to #6264. If your plugin needs access to the
`server` object, you can just pass it to your plugin's
constructor/factory yourself. This wasn't an option in AS3 because there
was no `server.addPlugin` method... or actually, you could do it with
the plugin factory feature.

Note that we do leave `ApolloServer<TContext>` as invariant in
`TContext`, for the reasons described in a comment above the class.

While we're at it, remove the unnecessary ability to specify plugins as
factory functions. As far as we know, the main use case for this feature
is to refer to the `ApolloServer` itself in the expression creating the
plugin, but the new `addPlugin` method lets you do the same thing.
Reducing the number of ways to specify constructor options helps keep
type errors simpler.
@glasser glasser force-pushed the glasser/apollo-server-plugin-contravariant branch from 5015fe0 to f5b4133 Compare August 15, 2022 21:08
@glasser glasser changed the title Glasser/apollo server plugin contravariant Plugins: no server; interface contravariant; no factory functions Aug 15, 2022
@glasser glasser marked this pull request as ready for review August 15, 2022 21:09
@glasser
Copy link
Member Author

glasser commented Aug 15, 2022

Going to merge this without full review so that I can make another alpha and move forward, but happy to make big changes or even revert after feedback.

@glasser glasser merged commit cf0fcf4 into version-4 Aug 15, 2022
@glasser glasser deleted the glasser/apollo-server-plugin-contravariant branch August 15, 2022 21:24
@github-actions github-actions bot mentioned this pull request Oct 10, 2022
@github-actions github-actions bot locked as resolved and limited conversation to collaborators Apr 20, 2023
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

1 participant