idio-graphql
TypeScript icon, indicating that this package has built-in type declarations

4.0.3 • Public • Published

idio-graphql

Node.js CI LICENSE npm version TypeScript Compatible Gitter GitHub stars

This package is inspired by; Apollo Federation, GraphQL Modules & Moleculer.

About

Node.js library for splitting SDL first GraphQL schemas into composable & idiomatic chunks.

Installation

$ npm install idio-graphql

graphql is a peerDependency you may need to install this too.

$ npm install graphql

Usage

const User = new GraphQLNode({
    name: "User",
    typeDefs: `
        type User {
            id: ID
            name: String
            age: Int
        }
 
        type Query {
            user(id: ID!): User
        }
    `,
    resolvers: { 
        Query: {
            user: () => ...
        }    
    }
});
 
const { typeDefs, resolvers } = combineNodes([ User ]);
 
const server = new ApolloServer({ typeDefs, resolvers });

Index

  1. About
  2. Examples
  3. FAQ
  4. Quick Start
  5. Guides
  6. API

Examples

  1. Monolith
  2. Microservice
  3. Mini examples - Some smaller examples to help demonstrate the capability's of this package.

FAQ

  1. What is a node ?
  2. How do I integrate with my Apollo Server ?
  3. How do I get started with microservices ?
  4. Can I use Schema Directives ?
  5. How can my nodes talk with each other ?
  6. Does it support graphql files or graphql tag ?
  7. What is the role of the gateway ?
  8. Does it support subscriptions ?

What is a node ?

A Node is designed to modularize a ObjectTypeDefinition together with its related resolvers & properties. You can think of a node as a module.

const User = new GraphQLNode({
    name: "User",
    typeDefs: `
        type User ...
 
        type Query {
            getUser: User
        }
    `,
    resolvers: {
        Query: {
            getUser: (root, args, ctx) => { ... }
        }
    }
});

You can compose nodes

const Comment = new GraphQLNode({
    name: "Comment",
    ...
});
 
const Post = new GraphQLNode({
    name: "Post",
    nodes: [ Comment ],
    ...
});
 
const User = new GraphQLNode({
    name: "User",
    nodes: [ Post ]
    ...
});

Is it all about nodes ? There are plenty of classes to help you construct your GraphQL schema start reading about schemaAppliances here.

How do I integrate with my Apollo Server ?

The result of makeExecutableSchema is returned from combineNodes & GraphQLSchema.

Using combineNodes

const { typeDefs, resolvers } = combineNodes(nodes);
 
const apolloServer = new ApolloServer({ typeDefs, resolvers });

Using GraphQLGateway

const gateway = new GraphQLGateway(
    {
        services: {
            nodes: ["User"]
        }
    },
    {
        transporter: "redis://localhost",
        nodeID: "gateway"
    }
);
 
const { typeDefs, resolvers } = await gateway.start();
 
const apolloServer = new ApolloServer({ typeDefs, resolvers });

How do I get started with microservices ?

Watch tutorial here

This package builds its microservices features on top of a package Molecular, this means you can integrate with Moleculer's features. Learn more about using microservices here.

Molecular is a optional dependency

const User = new GraphQLNode({
    name: "User"
});
 
await User.serve({
    transporter: "nats://localhost"
});

Do not forget to create your gateway

Gradual Adoption

You don't need have to have all your nodes as a service. You can have some nodes hosted on the same instance as the gateway. Use locals & services in GraphQLGateway to merge all nodes together. Read more about gradual adoption here.

Can I use Schema Directives ?

You can use a IdioDirective and apply it at combineNodes or GraphQLGateway.

const MyDirective = new IdioDirective({
    name: "...",
    typeDefs: ` ... `,
    resolver: SchemaDirectiveVisitor
});
 
const { typeDefs, resolvers, schemaDirectives } = combineNodes(nodes, { directives: [MyDirective] });

How can my nodes talk with each other ?

Inter-Schema Execution can be used to make GraphQL powered Queries & Mutations against your own or specified schema.

Inter-Schema Execution works with your served nodes, this will allow you to accomplish GraphQL powered service-service communication.

const Post = new GraphQLNode({
    name: "Post",
    typeDefs: `
        type Post {
            title: String
        }
        
        type Query {
            posts: [Post]
        }
    `,
    resolvers: { ... }
});
 
const User = new GraphQLNode({
    name: "User",
    typeDefs: `
        type User {
            posts: [Post]
        }
    `,
    resolvers: {
        Fields: {
            posts: async (root, args, { injections }) => {
                const { data, errors } = await injections.execute(
                    `
                        query {
                            posts {
                                title
                            }
                        }
                    `
                );
 
                return data.posts;
            }
        }
    }
});

Does it support graphql files or graphql tag ?

When specifying typedefs You can use; strings, graphql-tag or file paths

What is the role of the gateway ?

Remember the initial schema & keep track of services with the corresponding names. Produce a Graphql schema after introspecting each supplied service.

GraphQLGateway acts as a reverse proxy when using Inter-Schema execution.

Your gateway will;

  1. Not throw if it loses connection to a service
  2. Allow unlimited services, with the same name, to join the swarm
  3. Load balance requests to each service
  4. Not start until all services are connected
  5. Ensure no other gateway has the same name but different schema

You can spawn multiple instances of the same gateway

Does it support subscriptions ?

You can setup subscriptions in a node. Subscriptions will work with microservices.

const User = new GraphQLNode({
    name: "User",
    typeDefs: `
        type User ...
 
        type Subscription {
            userUpdate: User
        }
    `,
    resolvers: {
        Subscription: {
            userUpdate: {
                subscribe: async function* (){} // AsyncGenerator
            }
        }
    }
});

Subscriptions will not work service-service communication.

Quick Start

$ npm install idio-graphql apollo-server graphql-tag
const {
    combineNodes,
    GraphQLNode 
= require("idio-graphql");
 
const { ApolloServer } = require("apollo-server");
const gql = require("graphql-tag");
 
const User = new GraphQLNode({
    name: "User",
    typeDefs: gql`
        type User {
            id: ID
            name: String
            age: Int
        }
 
        type Query {
            user(id: ID!): User
        }
    `,
    resolvers: {
        Query: {
            user: (parent, { id }) => { ... }
        }
    }
});
 
async function main() {
    const { typeDefs, resolvers } = combineNodes([ User ]);
 
    const server = new ApolloServer({ typeDefs, resolvers });
 
    await server.listen(4000);
 
    console.log(`http://localhost:4000/graphql`);
}
 
main();

Microservices Quick Start

Requires nats-server @ nats://localhost:4222

$ npm install idio-graphql apollo-server graphql-tag moleculer nats

User Service

const gql = require("graphql-tag");
const { GraphQLNode } = require("idio-graphql");
 
const User = new GraphQLNode({
    name: "User",
    typeDefs: gql`
        type User {
            id: String
            name: String
            age: Int
        }
 
        type Query {
            user(id: String!): User
        }
    `,
    resolvers: {
        Query: {
            user: (root, { id }) => { ... }
        }
    }
});
 
await User.serve({
    gateway: "gateway",
    transporter: "NATS"
});

Gateway Service

const { ApolloServer } = require("apollo-server");
const { GraphQLGateway } = require("idio-graphql");
 
const gateway = new GraphQLGateway(
    { services: { nodes: ["User"] } },
    {
        transporter: "NATS",
        nodeID: "gateway"
    }
);
 
const { typeDefs, resolvers } = await gateway.start();
 
const server = new ApolloServer({
    typeDefs,
    resolvers
});
 
await server.listen(4000);

Package Sidebar

Install

npm i idio-graphql

Weekly Downloads

4

Version

4.0.3

License

MIT

Unpacked Size

123 kB

Total Files

60

Last publish

Collaborators

  • danstarns