[ ] Regression
[ ] Bug report
[ ] Feature request
[x] Documentation issue or request
[ ] Support request => Please do not submit support request here, instead post your question on Stack Overflow.
configure(consumer) {
const typeDefs = this.graphQLFactory.mergeTypesByPaths('./**/*.graphql');
const localSchema = this.graphQLFactory.createSchema({ typeDefs });
const delegates = this.graphQLFactory.createDelegates();
const schema = mergeSchemas({
schemas: [localSchema, chirpSchema, linkTypeDefs],
resolvers: delegates,
});
consumer
.apply(graphqlExpress(req => ({ schema, rootValue: req })))
.forRoutes('/graphql');
}
:shipit: old doc
async useFactory(graphqlFactory: GraphQLFactory) {
const link = new HttpLink({ uri: '^_^', fetch });
const anotherSchema = await introspectSchema(link);
const remoteSchema = makeRemoteExecutableSchema({ schema: anotherSchema, link });
return {
typePaths: ['src/**/*.graphql'],
schema,
mergeSchemas(localSchema => ({
schemas: [localSchema, remoteSchema, ...],
resolvers: graphQLFactory.createDelegates()
}),
...
};
}
:x: injecting graphql factory
:x: accessing local schema
schema stitching with nest@5
Nest version: 5.3.6
For Tooling issues:
- Node version: 10
- Platform:
- OS: Manjaro Linux x86_64
- Kernel: 4.14.67-1-MANJARO
Others:
Hi, is there an undocumented way of doing this currently? Wondering if I should dig deeper or wait. Thanks!
what about apollo federation schema ? (https://blog.apollographql.com/apollo-federation-f260cf525d21) , is there some documentation on how to implement it with Nestjs ? thanks!
an example of apollo federation and nest microservices would be fucking awesome.
Hi, I do have apollo federation setup, but the revolvers don't work anymore. That seems to be the issue. How to make the resolvers work.
I have same problem. It would be nice to get sample code for stitching the schema.
I did a PR guys
https://github.com/nestjs/graphql/pull/301
I'm currently putting together an example repository with kubernetes and prisma 馃榿
I had solved schema stitching problem by using transform method.
Look src/graphql.config/graphql.config.service.ts
here my code
link for the test
import { Injectable } from '@nestjs/common';
import { GqlOptionsFactory, GqlModuleOptions } from '@nestjs/graphql';
import * as ws from 'ws';
import {
makeRemoteExecutableSchema,
mergeSchemas,
introspectSchema
} from 'graphql-tools';
import { HttpLink } from 'apollo-link-http';
import nodeFetch from 'node-fetch';
import { split, from, NextLink, Observable, FetchResult, Operation } from 'apollo-link';
import { getMainDefinition } from 'apollo-utilities';
import { OperationTypeNode, buildSchema as buildSchemaGraphql, GraphQLSchema, printSchema } from 'graphql';
import { setContext } from 'apollo-link-context';
import { SubscriptionClient, ConnectionContext } from 'subscriptions-transport-ws';
import * as moment from 'moment';
import { extend } from 'lodash';
import { ConfigService } from '../config';
declare const module: any;
interface IDefinitionsParams {
operation?: OperationTypeNode;
kind: 'OperationDefinition' | 'FragmentDefinition';
}
interface IContext {
graphqlContext: {
subscriptionClient: SubscriptionClient,
};
}
@Injectable()
export class GqlConfigService implements GqlOptionsFactory {
private remoteLink: string = 'https://countries.trevorblades.com';
constructor(
private readonly config: ConfigService
) {}
async createGqlOptions(): Promise<GqlModuleOptions> {
const remoteExecutableSchema = await this.createRemoteSchema();
return {
autoSchemaFile: 'schema.gql',
transformSchema: async (schema: GraphQLSchema) => {
return mergeSchemas({
schemas: [
schema,
remoteExecutableSchema
]
});
},
debug: true,
playground: {
env: this.config.environment,
endpoint: '/graphql',
subscriptionEndpoint: '/subscriptions',
settings: {
'general.betaUpdates': false,
'editor.theme': 'dark' as any,
'editor.reuseHeaders': true,
'tracing.hideTracingResponse': true,
'editor.fontSize': 14,
// tslint:disable-next-line:quotemark
'editor.fontFamily': "'Source Code Pro', 'Consolas', 'Inconsolata', 'Droid Sans Mono', 'Monaco', monospace",
'request.credentials': 'include',
},
},
tracing: true,
installSubscriptionHandlers: true,
introspection: true,
subscriptions: {
path: '/subscriptions',
keepAlive: 10000,
onConnect: async (connectionParams, webSocket: any, context) => {
const subscriptionClient = new SubscriptionClient(this.config.get('HASURA_WS_URI'), {
connectionParams: {
...connectionParams,
...context.request.headers
},
reconnect: true,
lazy: true,
}, ws);
return {
subscriptionClient,
};
},
async onDisconnect(webSocket, context: ConnectionContext) {
const { subscriptionClient } = await context.initPromise;
if (subscriptionClient) {
subscriptionClient.close();
}
},
},
context(context) {
const contextModified: any = {
userRole: 'anonymous',
currentUTCTime: moment().utc().format()
};
if (context && context.connection && context.connection.context) {
contextModified.subscriptionClient = context.connection.context.subscriptionClient;
}
return contextModified;
},
};
}
private wsLink(operation: Operation, forward?: NextLink): Observable<FetchResult> | null {
const context = operation.getContext();
const { graphqlContext: { subscriptionClient } }: any = context;
return subscriptionClient.request(operation);
}
private async createRemoteSchema(): Promise<GraphQLSchema> {
const httpLink = new HttpLink({
uri: this.remoteLink,
fetch: nodeFetch as any,
});
const remoteIntrospectedSchema = await introspectSchema(httpLink);
const remoteSchema = printSchema(remoteIntrospectedSchema);
const link = split(
({ query }) => {
const { kind, operation }: IDefinitionsParams = getMainDefinition(query);
return kind === 'OperationDefinition' && operation === 'subscription';
},
this.wsLink,
httpLink,
);
const contextLink = setContext((request, prevContext) => {
extend(prevContext.headers, {
'X-hasura-Role': prevContext.graphqlContext.userRole,
'X-Hasura-Utc-Time': prevContext.graphqlContext.currentUTCTime,
});
return prevContext;
});
const buildedHasuraSchema = buildSchemaGraphql(remoteSchema);
const remoteExecutableSchema = makeRemoteExecutableSchema({
link: from([contextLink, link]),
schema: buildedHasuraSchema,
});
return remoteExecutableSchema;
}
}
Schema stitching is deprecated
@kamilmysliwiec Can I ask why schema stitching is deprecated? Trying to implement something and so I want to make sure I understand why it was deprecated and what should be its replacement.
Schema stitching is deprecated
I don't think it's accurate to say schema stitching is deprecated.
The graphql-tools package removed their own notice about stitching being deprecated in their 5.x release. Related issue: https://github.com/ardatan/graphql-tools/issues/1286
Although there is a lot of crossover, Schema Stitching and Apollo Federation serve different use cases. The key difference is that Apollo Federation requires modifications to the underlying schema(s), whereas Stitching does not. This allows Stitching to be used to wrap together remote schemas that you don't have the ability to modify, such as APIs operated by third parties.
I am pleased to see that transformSchema() can be successfully used with NestJS to enable stitching - please ensure this remains an option! 馃憤
It would be even better if link-level resolvers (i.e. resolvers for extended type fields that operate on the stitched schema gateway and pass down delegated queries to subschemas) could be written in the canonical NestJS style using @Resolver() decorators etc. I haven't found any way to do this, but writing them as an IResolvers map in graphql-tools style works okay.
@sgarner Bless you... This inform is super useful to keep building our apis. Thank you so much for the response!
Does this work in Nestjs 7??
transformSchema is not running?
Most helpful comment
I had solved schema stitching problem by using transform method.
Look src/graphql.config/graphql.config.service.ts
here my code
link for the test