Skip to content

Korzun/nexus-federation-plugin

Repository files navigation

Nexus Federation Plugin

npm version

A Nexus plugin integrating Apollo Federation 2.0

Installation

yarn add @korzun/nexus-federation-plugin
or
npm i @korzun/nexus-federation-plugin

Note you must also add nexus. The plugin pins to it as a peer dependency.

Setup

import { plugin as federationPlugin } from '@korzun/nexus-federation-plugin';
import { makeSchema, objectType } from 'nexus';

// Create example User Type
const User = objectType({
  name: 'User',
  keys: ['id'],
  definition(t) {
    t.id('id');
    t.string('name');
  },
});

// Build Nexus Schema
const schema = makeSchema({
  types: [User],
  plugins: [
    federationPlugin(),
  ]
});

With Apollo Server

import { ApolloServer, gql } from 'apollo-server-core';
import { buildSubgraphSchema } from '@apollo/subgraph';
import { getResolversFromSchema } from '@graphql-tools/utils';

// Create Subgraph Schema from Nexus Schema
const resolvers = getResolversFromSchema(nexusSchema);
const typeDefs = gql.(printSchema(nexusSchema));
//@ts-expect-error buildSubgraphSchema doesn't recognize the IResolvers type
const subgraphSchema = buildSubgraphSchema({ typeDefs, resolvers });

// Start Apollo Server
const server = new GraphQLServer({ schema })
server.listen().then(({ url }) => {
  console.log(`🚀  Server ready at ${url}`);
});

Examples

External

objectType({
  name: 'User',
  definition: (t) => {
    t.string('email', { external: true });
    t.string.field('review', { type: 'Review' });
  },
});

Keys

objectType({
  name: 'User',
  keys: ['id'],
  definition(t) {
    t.id('id');
    t.string('name');
  },
});

Override

objectType({
  name: 'User',
  keyFields: ['id'],
  definition: (t) => {
    t.id('id');
    t.nullable.string('name', override: 'SubgraphA');
  },
});

Provides

objectType({
  name: 'Review',
  keyFields: ['id'],
  definition: (t) => {
    t.field('product', { type: 'Product', provides: ['name'] });
  },
});

Requires

objectType({
  name: 'User',
  keyFields: ['id'],
  definition: (t) => {
    t.id('id', { external: true });
    t.nullable.string('email', { external: true });
    t.list.field('reviews', { type: 'Review', requires: ['email'] });
  },
});

Sharable

Sharable Field

objectType({
  name: 'Product',
  keyFields: ['upc'],
  definition: (t) => 
  {
    t.field('upc', { type: 'UPC' });              // shareable, upc is a key field
    t.string('name');                             // non-shareable
    t.string('description', { shareable: true }); // shareable
  }
});

Sharable Object Type

objectType({
  name: 'User',
  shareable: true,
  definition: (t) => {
    t.string('name');  // shareable, User is marked shareable
    t.string('email'); // shareable, User is marked shareable
  },
});