Seamlessly migrate to Postgraphile (multiple ApolloClient instances)

991 Views Asked by At

Postgraphile seems very handy tool, but I've already have tens of queries and mutations on client and server side.

Is there any way to integrate Postgraphile piece by piece, having my old GraphQL schema, described by hands working?

So, now I have following initialization code:

function createApolloLink(){
  return createHttpLink({
    uri: '/graphql',
    credentials: 'same-origin'
  });
}

function create(){
  return new ApolloClient({
    link: createApolloLink(),
    ssrMode: !process.browser, // eslint-disable-line
    cache: new InMemoryCache(),
    connectToDevTools: process.browser
  });
}

How to utilize one normalised storage (client side) and connect to second API point, driven by Postgraphile, e.g. /graphql2?

1

There are 1 best solutions below

0
On

Typically your GraphQL client shouldn't have to think about this - it should be handled on the server side.

There's a number of techniques you can use to address this on the server side:

Schema Stitching

Schema stitching is a straight-forward approach for your issue - take your old schema and merge it with your PostGraphile schema; that way when clients communicate with /graphql they have access to both schemas. You can then mark everything in your old schema as deprecated and slowly phase out usage. However, if you can, I'd instead recommend that you use a PostGraphile plugin...

PostGraphile Plugin

PostGraphile is built around a plugin system, and you can use something like the makeExtendSchemaPlugin to mix your old GraphQL schema into the PostGraphile one. This is documented here: https://www.graphile.org/postgraphile/make-extend-schema-plugin/ but if your old types/resolvers are implemented via something like graphql-tools this is probably the easiest way to get started:

const { makeExtendSchemaPlugin, gql } = require('graphile-utils');

const typeDefs = gql`\
type OldType1 {
  field1: Int!
  field2: String
}
extend type Query {
  oldField1: OldType1
  oldField2: OldType2
}
`;

const resolvers = {
  Query: {
    oldField1(/*...*/) {
      /* old logic here */
    },
    //...
  },
};

const AddOldSchemaPlugin = makeExtendSchemaPlugin(
  build => ({
    typeDefs,
    resolvers,
  })
);

module.exports = AddOldSchemaPlugin;

This will also lead to the best performance as there should be no added latency, and you can again mark the legacy fields/mutations as deprecated.

Schema Delegation

Using this approach you write your own new GraphQL schema which then "delegates" to the other GraphQL schemas (the legacy one, and the one generated by PostGraphile). This adds a little latency but gives you much more control over the final shape of your GraphQL schema, though with this power comes great responsibility - if you make a typo then you're going to have to maintain that typo for a long time! Personally, I prefer the generated schema approach used by PostGraphile.


However, to answer your question as-asked, Apollo Link has "context" functionality that allows you to change how the query is executed. Typically this is used to add headers but you can also use it to override the URI to determine where the query can go. I've never done this myself, but I wouldn't be surprised if there was an Apollo Link that you can use that will switch automatically based on a client directive or even on the field name.

https://github.com/apollographql/apollo-link/tree/master/packages/apollo-link-http#context