Skip to content

Commit

Permalink
update docs
Browse files Browse the repository at this point in the history
  • Loading branch information
yaacovCR committed Oct 6, 2020
1 parent 59df0c6 commit 9531bfb
Show file tree
Hide file tree
Showing 3 changed files with 34 additions and 19 deletions.
6 changes: 4 additions & 2 deletions .changeset/weak-peaches-count.md
Original file line number Diff line number Diff line change
Expand Up @@ -23,16 +23,18 @@

#### Remote Schemas & Wrapping (`wrapSchema`, `makeRemoteExecutableSchema`, and `@graphql-tools/wrap`)

- `wrapSchema` and `generateProxyingResolvers` now only take a single argument consisting of a `SubschemaConfig`. Shorthand version with first argument consisting of a `GraphQLSchema` and second argument representing the transforms should be reworked as a `SubschemaConfig` object.
- `wrapSchema` and `generateProxyingResolvers` now only take a single options argument with named properties of type `SubschemaConfig`. The previously possible shorthand version with first argument consisting of a `GraphQLSchema` and second argument representing the transforms should be reworked as a `SubschemaConfig` object.

- Similarly, the `ICreateProxyingResolverOptions` interface that provides the options for the `createProxyingResolver` property of `SubschemaConfig` options has now been adjusted. The `schema` property that previously could take a `GraphQLSchema` or a `SubschemaConfig` object has been removed in favor of a `subschemaConfig` property that has to be a `SubschemaConfig` object. The `transforms` property has been removed; transforms should be included within the `SubschemaConfig` object.`
- Similarly, the `ICreateProxyingResolverOptions` interface that provides the options for the `createProxyingResolver` property of `SubschemaConfig` options has been adjusted. The `schema` property previously could be set to a `GraphQLSchema` or a `SubschemaConfig` object. This property has been removed in favor of a `subschemaConfig` property that will always be a `SubschemaConfig` object. The `transforms` property has been removed; transforms should be included within the `SubschemaConfig` object.`

- The format of the wrapping schema has solidified. All non-root fields are expected to use identical resolvers, either `defaultMergedResolver` or a custom equivalent, with root fields doing the hard work of proxying. Support for custom merged resolvers throught `createMergedResolver` has been deprecated, as custom merging resolvers conflicts when using stitching's type merging, where resolvers are expected to be identical across subschemas.

- The `WrapFields` transform's `wrappingResolver` option has been removed, as this complicates multiple wrapping layers, as well as planned functionality to wrap subscription root fields in potentially multiple layers, as the wrapping resolvers may be different in different layers. Modifying resolvers can still be performed by use of an additional transform such as `TransformRootFields` or `TransformObjectFields`.

- The `ExtendSchema` transform has been removed, as it is conceptually simpler just to use `stitchSchemas` with one subschema.

- The `ReplaceFieldsWithFragment` transform has been removed, as it is has been superseded by the `AddReplacementSelectionSets` transform.

#### Schema Stitching (`stitchSchemas` & `@graphql-tools/stitch`)

- `stitchSchemas`'s `mergeTypes` option is now true by default! This causes the `onTypeConflict` option to be ignored by default. To use `onTypeConflict` to select a specific type instead of simply merging, simply set `mergeTypes` to false.
Expand Down
6 changes: 4 additions & 2 deletions website/docs/migration-from-tools.md
Original file line number Diff line number Diff line change
Expand Up @@ -21,16 +21,18 @@ If you are using GraphQL Tools v6, there are several breaking changes to be awar

#### Remote Schemas & Wrapping (`wrapSchema`, `makeRemoteExecutableSchema`, and `@graphql-tools/wrap`)

- `wrapSchema` and `generateProxyingResolvers` now only take a single argument consisting of a `SubschemaConfig`. Shorthand version with first argument consisting of a `GraphQLSchema` and second argument representing the transforms should be reworked as a `SubschemaConfig` object.
- `wrapSchema` and `generateProxyingResolvers` now only take a single options argument with named properties of type `SubschemaConfig`. The previously possible shorthand version with first argument consisting of a `GraphQLSchema` and second argument representing the transforms should be reworked as a `SubschemaConfig` object.

- Similarly, the `ICreateProxyingResolverOptions` interface that provides the options for the `createProxyingResolver` property of `SubschemaConfig` options has now been adjusted. The `schema` property that previously could take a `GraphQLSchema` or a `SubschemaConfig` object has been removed in favor of a `subschemaConfig` property that has to be a `SubschemaConfig` object. The `transforms` property has been removed; transforms should be included within the `SubschemaConfig` object.`
- Similarly, the `ICreateProxyingResolverOptions` interface that provides the options for the `createProxyingResolver` property of `SubschemaConfig` options has been adjusted. The `schema` property previously could be set to a `GraphQLSchema` or a `SubschemaConfig` object. This property has been removed in favor of a `subschemaConfig` property that will always be a `SubschemaConfig` object. The `transforms` property has been removed; transforms should be included within the `SubschemaConfig` object.`

- The format of the wrapping schema has solidified. All non-root fields are expected to use identical resolvers, either `defaultMergedResolver` or a custom equivalent, with root fields doing the hard work of proxying. Support for custom merged resolvers throught `createMergedResolver` has been deprecated, as custom merging resolvers conflicts when using stitching's type merging, where resolvers are expected to be identical across subschemas.

- The `WrapFields` transform's `wrappingResolver` option has been removed, as this complicates multiple wrapping layers, as well as planned functionality to wrap subscription root fields in potentially multiple layers, as the wrapping resolvers may be different in different layers. Modifying resolvers can still be performed by use of an additional transform such as `TransformRootFields` or `TransformObjectFields`.

- The `ExtendSchema` transform has been removed, as it is conceptually simpler just to use `stitchSchemas` with one subschema.

- The `ReplaceFieldsWithFragment` transform has been removed, as it is has been superseded by the `AddReplacementSelectionSets` transform.

#### Schema Stitching (`stitchSchemas` & `@graphql-tools/stitch`)

- `stitchSchemas`'s `mergeTypes` option is now true by default! This causes the `onTypeConflict` option to be ignored by default. To use `onTypeConflict` to select a specific type instead of simply merging, simply set `mergeTypes` to false.
Expand Down
41 changes: 26 additions & 15 deletions website/docs/schema-wrapping.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,14 +10,6 @@ Schema wrapping can be useful when building GraphQL gateways that combine multip

Schema wrapping works by wrapping the original schema in a new 'gateway' schema that simply delegates all operations to the original subschema. A series of 'transforms' are applied to modify the schema after the initial wrapping is complete. Each transform includes a schema transformation function that changes the gateway schema. It may also include operation transforms, i.e. functions that either modify the operation prior to delegation or modify the result prior to its return.

```ts
interface Transform = {
transformSchema?: (schema: GraphQLSchema) => GraphQLSchema;
transformRequest?: (request: Request) => Request;
transformResult?: (result: ExecutionResult) => ExecutionResult;
};
```

For example, let's consider changing the name of the type in a simple schema. Imagine we've written a function that takes a `GraphQLSchema` and replaces all instances of type `Test` with `NewTest`.

```graphql
Expand Down Expand Up @@ -82,11 +74,29 @@ By the same reasoning, we also need a `transformResult` function, because any re
### Transform

```ts
interface Transform = {
transformSchema?: (schema: GraphQLSchema) => GraphQLSchema;
transformRequest?: (request: Request) => Request;
transformResult?: (result: ExecutionResult) => ExecutionResult;
};
export interface Transform<T = Record<string, any>> {
transformSchema?: SchemaTransform;
transformRequest?: RequestTransform<T>;
transformResult?: ResultTransform<T>;
}

export type SchemaTransform = (
originalWrappingSchema: GraphQLSchema,
subschemaConfig: SubschemaConfig,
transformedSchema?: GraphQLSchema
) => GraphQLSchema;

export type RequestTransform<T = Record<string, any>> = (
originalRequest: Request,
delegationContext: DelegationContext,
transformationContext: T
) => Request;

export type ResultTransform<T = Record<string, any>> = (
originalResult: ExecutionResult,
delegationContext: DelegationContext,
transformationContext: T
) => ExecutionResult;

type Request = {
document: DocumentNode;
Expand All @@ -97,12 +107,14 @@ type Request = {

### wrapSchema

Given a `GraphQLSchema` and an array of `Transform` objects, `wrapSchema` produces a new schema with those transforms applied.
Given a `GraphQLSchema` and an array of `Transform` objects, `wrapSchema` produces a new schema with the `transformSchema` methods applied.

Delegating resolvers are generated to map from new schema root fields to old schema root fields. These automatic resolvers should be sufficient, so you don't have to implement your own.

The delegating resolvers will apply the operation transforms defined by the `Transform` objects. Each provided `transformRequest` functions will be applies in reverse order, until the request matches the original schema. The `tranformResult` functions will be applied in the opposite order until the result matches the final gateway schema.

In advanced cases, transforms may wish to create additional delegating root resolvers (for example, when hoisting a field into a root type). This is also possible. The wrapping schema is actually generated twice -- the first run results in a possibly non-executable version, while the second execution also includes the result of the first one within the `transformedSchema` argument so that an executable version with any new proxying resolvers can be created.

Remote schemas can also be wrapped! In fact, this is the primary use case. See documentation regarding [remote schemas](/docs/remote-schemas/) for further details about remote schemas. Note that as explained there, when wrapping remote schemas, you will be wrapping a subschema config object, and the array of transforms should be defined on that object rather than as a second argument to `wrapSchema`.

## Built-in transforms
Expand Down Expand Up @@ -306,4 +318,3 @@ By passing a custom `transforms` array to `delegateToSchema`, it's possible to r
* `AddReplacementSelectionSets(schema: GraphQLSchema, mapping: ReplacementSelectionSetMapping)`: `stitchSchemas` adds selection sets on outgoing requests from the gateway, enabling delegation from fields specified on the gateway using fields obtained from the original requests. The selection sets can be added depending on the presence of fields within the request using the `selectionSet` option within the resolver map. `stitchSchemas` creates the mapping at gateway startup. Selection sets are used instead of fragments as the selections are added prior to transformation in case type names are changed, obviating the need for the fragment name.
* `AddMergedTypeSelectionSets(schema: GraphQLSchema, mapping: Record<string, MergedTypeInfo>)`: `stitchSchemas` adds selection sets on outgoing requests from the gateway, enabling type merging from the initial result using any fields initially obtained. The mapping is created at gateway startup.
* Deprecated: `ReplaceFieldWithFragment(targetSchema: GraphQLSchema, fragments: Array<{ field: string; fragment: string; }>)`: Replace the given fields with an inline fragment. Used by original `stitchSchemas` to add prespecified fragments to root fields, enabling delegation `fragment` option. Array was parsed at each delegation.

0 comments on commit 9531bfb

Please sign in to comment.