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

Add support for willResolveField and corresponding end handler. #3988

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
42 commits
Select commit Hold shift + click to select a range
fb99d93
Use named types for the "DidEnd" hooks.
abernix Mar 26, 2020
c3af619
Merge branch 'abernix/named-DidEnd-hooks' into abernix/graphql-extens…
abernix Apr 15, 2020
ab35c45
Add support for `willResolveField` and `didResolveField`.
abernix Mar 26, 2020
835a68d
chore: Convert `schemaHash` from `string` to a faux-paque type.
abernix Apr 15, 2020
ab3855d
Introduce a plugin test harness to facilitate testing of plugins.
abernix Apr 14, 2020
dae59a5
Allow an optional `logger` to be passed into the test harness.
abernix Apr 16, 2020
771683f
chore: Convert `schemaHash` from `string` to a faux-paque type. (#3989)
abernix Apr 16, 2020
eec87a6
Introduce an internal plugin test harness to facilitate plugin… (#3990)
abernix Apr 16, 2020
0d31d1b
Apply suggestions from code review
abernix Apr 16, 2020
4b59b02
Rejigger `ensurePluginInstantiation` to accommodate upcoming changes.
abernix Apr 16, 2020
532e80f
Merge remote-tracking branch 'origin/abernix/graphql-extensions-depre…
abernix Apr 16, 2020
6217f16
Merge branch 'abernix/fauxpaque-SchemaHash' into abernix/add-wrf
abernix Apr 16, 2020
7ca6840
Correct typo of "precidence".
abernix Apr 27, 2020
cd754b0
noop: Remove trailing line.
abernix Apr 27, 2020
11e885c
Relocate schema instrumentation to `utils/schemaInstrumentation.ts`.
abernix Apr 27, 2020
231817e
Import `PersistedQueryOptions` from private, rather than public, API.
abernix Apr 27, 2020
a03587c
Merge remote-tracking branch 'origin/master' into abernix/add-willRes…
abernix May 6, 2020
ad9fefa
noop: Fix unrelated typing error in `runQuery.test.ts`.
abernix May 6, 2020
6575625
Reintroduce genericism to `Dispatcher`.
abernix May 4, 2020
d5408ac
Correct recently added plugin types to exclude `void`.
abernix May 6, 2020
ab78e48
Introduce `BaseContext` and `DefaultContext`.
abernix May 6, 2020
9b5be32
tests: Add additional plugin API hook tests.
abernix May 6, 2020
4fa6ddd
Introduce a `callTargets` method on the `Dispatcher`.
abernix May 6, 2020
f2a7490
Switch `willResolveField` to be nested within `executionDidStart`.
abernix May 6, 2020
60cd32d
tests: Introduce a test which demonstrates `fieldResolver` behavior.
abernix May 7, 2020
129c255
tests: Add further life-cycle ordering tests for parsing and validation.
abernix May 7, 2020
66d5869
refactor(tests): Better helpers for APQ tests in intgr. testsuite.
abernix May 7, 2020
570bc4e
feat(plugins): Intro. `didResolveSource` to indicate availability of …
abernix May 7, 2020
fe971b3
docs: Add `didResolveSource` to plugin Mermaid workflow.
abernix May 8, 2020
464e4f2
noop: Add comment indicating where to find `didResolveSource` APQ tests.
abernix May 8, 2020
1356f00
Merge pull request #4076 from apollographql/abernix/add-didResolveSource
abernix May 8, 2020
1121785
chore(types): Remove `DefaultContext` and just leverage `BaseContext`.
abernix May 8, 2020
a926b7e
Use an object, rather than positional params for `willResolveField`.
abernix May 8, 2020
b7ea447
Remove unreachable code after `callTargets` decomposition.
abernix May 8, 2020
41b103e
tests: Expand on tests for `willResolveField` parameters.
abernix May 11, 2020
6564081
Attach user-defined `fieldResolver` to context.
abernix May 11, 2020
f905eb1
Condense guards in `schemaInstrumentation`.
abernix May 12, 2020
db0e378
types: Improve `Dispatcher`'s `callTargets` and `invokeHookAsync` types.
abernix May 12, 2020
52418a4
comment: Add note about typing question and reference to issue.
abernix May 12, 2020
18d95fd
comment: Leave traces/suggestions about future work.
abernix May 12, 2020
99d4fa7
Merge remote-tracking branch 'origin/master' into abernix/add-willRes…
abernix May 12, 2020
1b98f87
Merge branch 'release-2.14.0' into abernix/add-willResolveField-and-d…
abernix May 12, 2020
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
26 changes: 22 additions & 4 deletions docs/source/integrations/plugins.md
Expand Up @@ -121,17 +121,18 @@ The following diagram illustrates the sequence of events that fire for each requ

```mermaid
graph TB;
request(requestDidStart) --> parsing(parsingDidStart*);
request(requestDidStart) --> resolveSource(didResolveSource);
resolveSource --"Success"--> parsing(parsingDidStart*);
parsing --"Success"--> validation(validationDidStart*);
validation --"Success"--> resolve(didResolveOperation);
resolve --"Success"--> response(responseForOperation);
validation --"Success"--> resolveOperation(didResolveOperation);
resolveOperation --"Success"--> response(responseForOperation);
execution(executionDidStart*);
errors(didEncounterErrors);
response --"Response provided"--> send;
response --"No response provided"--> execution;
execution --"Success"--> send(willSendResponse);

execution & resolve & parsing & validation --"Failure"--> errors;
execution & resolveSource & resolveOperation & parsing & validation --"Failure"--> errors;
errors --> send;
class server,request secondary;
```
Expand Down Expand Up @@ -313,6 +314,23 @@ should not return a value.

> If you're using TypeScript to create your plugin, implement the [ `GraphQLRequestListener` interface](https://github.com/apollographql/apollo-server/blob/master/packages/apollo-server-plugin-base/src/index.ts) from the `apollo-server-plugin-base` module to define functions for request lifecycle events.

### `didResolveSource`

The `didResolveSource` event is invoked after Apollo Server has determined the
`String`-representation of the incoming operation that it will act upon. In the
event that this `String` was not directly passed in from the client, this
may be retrieved from a cache store (e.g., Automated Persisted Queries).

At this stage, there is not a guarantee that the operation is not malformed.

```typescript
didResolveSource?(
requestContext: WithRequired<
GraphQLRequestContext<TContext>, 'source' | 'logger'>,
>,
): ValueOrPromise<void>;
```

### `parsingDidStart`

The `parsingDidStart` event fires whenever Apollo Server will parse a GraphQL
Expand Down
6 changes: 3 additions & 3 deletions packages/apollo-engine-reporting/src/agent.ts
Expand Up @@ -12,7 +12,7 @@ import { fetch, RequestAgent, Response } from 'apollo-server-env';
import retry from 'async-retry';

import { EngineReportingExtension } from './extension';
import { GraphQLRequestContext, Logger } from 'apollo-server-types';
import { GraphQLRequestContext, Logger, SchemaHash } from 'apollo-server-types';
import { InMemoryLRUCache } from 'apollo-server-caching';
import { defaultEngineReportingSignature } from 'apollo-graphql';

Expand Down Expand Up @@ -250,7 +250,7 @@ export interface AddTraceArgs {
trace: Trace;
operationName: string;
queryHash: string;
schemaHash: string;
schemaHash: SchemaHash;
queryString?: string;
documentAST?: DocumentNode;
}
Expand Down Expand Up @@ -328,7 +328,7 @@ export class EngineReportingAgent<TContext = any> {
handleLegacyOptions(this.options);
}

public newExtension(schemaHash: string): EngineReportingExtension<TContext> {
public newExtension(schemaHash: SchemaHash): EngineReportingExtension<TContext> {
return new EngineReportingExtension<TContext>(
this.options,
this.addTrace.bind(this),
Expand Down
9 changes: 7 additions & 2 deletions packages/apollo-engine-reporting/src/extension.ts
@@ -1,4 +1,9 @@
import { GraphQLRequestContext, WithRequired, Logger } from 'apollo-server-types';
import {
GraphQLRequestContext,
WithRequired,
Logger,
SchemaHash,
} from 'apollo-server-types';
import { Request, Headers } from 'apollo-server-env';
import {
GraphQLResolveInfo,
Expand Down Expand Up @@ -42,7 +47,7 @@ export class EngineReportingExtension<TContext = any>
public constructor(
options: EngineReportingOptions<TContext>,
addTrace: (args: AddTraceArgs) => Promise<void>,
private schemaHash: string,
private schemaHash: SchemaHash,
) {
this.options = {
...options,
Expand Down
8 changes: 3 additions & 5 deletions packages/apollo-gateway/src/executeQueryPlan.ts
Expand Up @@ -89,11 +89,9 @@ export async function executeQueryPlan<TContext>(
},
rootValue: data,
variableValues: requestContext.request.variables,
// FIXME: GraphQL extensions currently wraps every field and creates
// a field resolver. Because of this, when using with ApolloServer
// the defaultFieldResolver isn't called. We keep this here
// because it is the correct solution and when ApolloServer removes
// GraphQLExtensions this will be how alias support is maintained
// We have a special field resolver which ensures we support aliases.
// FIXME: It's _possible_ this will change after `graphql-extensions` is
// deprecated, though not certain. See here, also: https://git.io/Jf8cS.
fieldResolver: defaultFieldResolverWithAliasSupport,
}));
} catch (error) {
Expand Down
4 changes: 4 additions & 0 deletions packages/apollo-gateway/src/index.ts
Expand Up @@ -476,6 +476,10 @@ export class ApolloGateway implements GraphQLService {

this.logger.debug('Schema loaded and ready for execution');

// FIXME: The comment below may change when `graphql-extensions` is
// removed, as it will be soon. It's not clear if this will be temporary,
// as is suggested, after that time, because we still very much need to
// do this special alias resolving. Original comment:
// this is a temporary workaround for GraphQLFieldExtensions automatic
// wrapping of all fields when using ApolloServer. Here we wrap all fields
// with support for resolving aliases as part of the root value which
Expand Down
18 changes: 11 additions & 7 deletions packages/apollo-server-core/src/ApolloServer.ts
Expand Up @@ -71,8 +71,8 @@ import {

import { Headers } from 'apollo-server-env';
import { buildServiceDefinition } from '@apollographql/apollo-tools';
import { Logger, SchemaHash } from "apollo-server-types";
import { getEngineApiKey, getEngineGraphVariant } from "apollo-engine-reporting/dist/agent";
import { Logger } from "apollo-server-types";

const NoIntrospection = (context: ValidationContext) => ({
Field(node: FieldDefinitionNode) {
Expand Down Expand Up @@ -109,7 +109,7 @@ type SchemaDerivedData = {
// on the same operation to be executed immediately.
documentStore?: InMemoryLRUCache<DocumentNode>;
schema: GraphQLSchema;
schemaHash: string;
schemaHash: SchemaHash;
extensions: Array<() => GraphQLExtension>;
};

Expand Down Expand Up @@ -759,12 +759,16 @@ export class ApolloServerBase {
return sdlFieldType.name == 'String';
}

private ensurePluginInstantiation(plugins?: PluginDefinition[]): void {
if (!plugins || !plugins.length) {
return;
}
private ensurePluginInstantiation(plugins: PluginDefinition[] = []): void {
const pluginsToInit: PluginDefinition[] = [];

// Internal plugins should be added to `pluginsToInit` here.
// User's plugins, provided as an argument to this method, will be added
// at the end of that list so they take precedence.
// A follow-up commit will actually introduce this.

this.plugins = plugins.map(plugin => {
pluginsToInit.push(...plugins);
this.plugins = pluginsToInit.map(plugin => {
if (typeof plugin === 'function') {
return plugin();
}
Expand Down