idio-graphql v4.0.3
idio-graphql
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
Examples
- Monolith
- Microservice
- Mini examples - Some smaller examples to help demonstrate the capability's of this package.
FAQ
- What is a node ?
- How do I integrate with my Apollo Server ?
- How do I get started with microservices ?
- Can I use Schema Directives ?
- How can my nodes talk with each other ?
- Does it support graphql files or graphql tag ?
- What is the role of the gateway ?
- 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);
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago