UNPKG

8.48 kBMarkdownView Raw
1# GraphQL Hive Client
2
3[GraphQL Hive](https://graphql-hive.com) is a GraphQL schemas registry where you can host, manage and collaborate on all your GraphQL schemas and operations, compatible with all architecture: schema stitching, federation, or just a good old monolith.
4
5GraphQL Hive is currently available as a hosted service to be used by all.
6We take care of the heavy lifting behind the scenes be managing the registry, scaling it for your needs, to free your time to focus on the most important things at hand.
7
8## Installation
9
10```
11npm install @graphql-hive/client
12```
13
14## Basic Usage
15
16Hive Client comes with generic client and plugins for [Envelop](https://envelop.dev) and [Apollo Server](https://github.com/apollographql/apollo-server)
17
18### With GraphQL Yoga
19
20[GraphQL Yoga](https://www.the-guild.dev/graphql/yoga-server) is a cross-platform GraphQL sever built on top of the envelop engine.
21
22```ts
23import { createYoga } from '@graphql-yoga/node'
24import { useHive } from '@graphql-hive/client'
25
26const server = createYoga({
27 plugins: [
28 useHive({
29 enabled: true, // Enable/Disable Hive Client
30 debug: true, // Debugging mode
31 token: 'YOUR-TOKEN',
32 // Schema reporting
33 reporting: {
34 // feel free to set dummy values here
35 author: 'Author of the schema version',
36 commit: 'git sha or any identifier'
37 },
38 usage: true // Collects schema usage based on operations
39 })
40 ]
41})
42
43server.start()
44```
45
46### With Envelop
47
48If you're not familiar with Envelop - in "short" it's a lightweight JavaScript library for wrapping GraphQL execution layer and flow, allowing developers to develop, share and collaborate on GraphQL-related plugins, while filling the missing pieces in GraphQL implementations.
49
50Here's [more](https://github.com/dotansimha/envelop#envelop) on that topic.
51
52```ts
53import { envelop } from '@envelop/core'
54import { useHive } from '@graphql-hive/client'
55
56const envelopProxy = envelop({
57 plugins: [
58 useHive({
59 enabled: true, // Enable/Disable Hive Client
60 debug: true, // Debugging mode
61 token: 'YOUR-TOKEN',
62 // Schema reporting
63 reporting: {
64 // feel free to set dummy values here
65 author: 'Author of the schema version',
66 commit: 'git sha or any identifier'
67 },
68 usage: true // Collects schema usage based on operations
69 })
70 ]
71})
72```
73
74### With Apollo Server
75
76Thanks to the plugin system it's a matter of adding hiveApollo plugin to ApolloServer instance:
77
78```ts
79import { ApolloServer } from 'apollo-server'
80import { hiveApollo } from '@graphql-hive/client'
81
82const server = new ApolloServer({
83 typeDefs,
84 resolvers,
85 plugins: [
86 hiveApollo({
87 enabled: true, // Enable/Disable Hive Client
88 debug: true, // Debugging mode
89 token: 'YOUR-TOKEN',
90 reporting: {
91 // feel free to set dummy values here
92 author: 'Author of the latest change',
93 commit: 'git sha or any identifier'
94 },
95 usage: true // Collects schema usage based on operations
96 })
97 ]
98})
99```
100
101### With Other Servers
102
103First you need to instantiate the Hive Client.
104
105The `collectUsage` method accepts the same arguments as execute function of graphql-js and returns a function that expects the execution result object.
106
107- `collectUsage(args)` - should be called when a GraphQL execution starts.
108- `finish(result)` (function returned by `collectUsage(args)`) - has to be invoked right after execution finishes.
109
110```ts
111import express from 'express'
112import { graphqlHTTP } from 'express-graphql'
113import { createHive } from '@graphql-hive/client'
114
115const app = express()
116const hive = createHive({
117 enabled: true, // Enable/Disable Hive Client
118 debug: true, // Debugging mode
119 token: 'YOUR-TOKEN',
120 reporting: {
121 // feel free to set dummy values here
122 author: 'Author of the latest change',
123 commit: 'git sha or any identifier'
124 },
125 usage: true // Collects schema usage based operations
126})
127
128// Report Schema
129hive.reportSchema({ schema: yourSchema })
130
131app.post(
132 '/graphql',
133 graphqlHTTP({
134 schema: yourSchema,
135 async customExecuteFn(args) {
136 // Collecting usage
137 const finish = hive.collectUsage(args)
138 const result = await execute(args)
139 finish(result)
140 return result
141 }
142 })
143)
144```
145
146### Using the registry when Stitching
147
148Stitching could be done in many ways, that's why `@graphql-hive/client` provide generic functions, not something dedicated for stitching. Unfortunately the implementation of gateway + polling is up to you.
149
150Prerequisites:
151
152- `HIVE_CDN_ENDPOINT` - the endpoint Hive generated for you in the previous step
153- `HIVE_CDN_KEY` - the access key
154
155The `createServicesFetcher` factory function returns another function that is responsible for fetching a list of services from Hive's high-availability endpoint.
156
157```ts
158import { createServicesFetcher } from '@graphql-hive/client'
159
160const fetchServices = createServicesFetcher({
161 endpoint: process.env.HIVE_CDN_ENDPOINT,
162 key: process.env.HIVE_CDN_KEY
163})
164
165// This is your GraphQL gateway with built-in polling mechanism, in which the `stitchServices` method is called every 10 seconds.
166startMyGraphQLGateway({
167 // a function that resolves a list of services to stitch them together
168 async stitchServices() {
169 const services = await fetchServices()
170
171 return services.map(service => {
172 return {
173 sdl: service.sdl,
174 url: service.url,
175 checksum: service.id // to check if service's schema was modified
176 }
177 })
178 },
179 pollingInSec: 10 // every 10s
180})
181```
182
183### Using the registry with Apollo Gateway
184
185You can connect your Apollo Gateway with Hive client.
186
187- `HIVE_CDN_ENDPOINT` - the endpoint Hive generated for you in the previous step
188- `HIVE_CDN_KEY` - the access
189
190```ts
191import { createSupergraphManager } from '@graphql-hive/client'
192import { ApolloGateway } from '@apollo/gateway'
193import { ApolloServer } from 'apollo-server'
194
195const gateway = new ApolloGateway({
196 // Apollo Gateway will fetch Supergraph from GraphQL Hive CDN
197 supergraphSdl: createSupergraphManager({
198 endpoint: HIVE_CDN_ENDPOINT,
199 key: HIVE_CDN_KEY,
200 pollIntervalInMs: 15_000
201 })
202})
203
204const server = new ApolloServer({
205 gateway
206})
207
208server.listen().then(({ url }) => {
209 console.log(`🚀 Server ready at ${url}`)
210})
211```
212
213## Usage Reporting configuration
214
215### Client Info
216
217The schema usage operation information can be enriched with meta information that will be displayed on the Hive dashboard in order to get a better understanding of the origin of an executed GraphQL operation.
218
219### GraphQL Yoga Example
220
221```ts
222import { createYoga } from '@graphql-yoga/node'
223import { useHive } from '@graphql-hive/client'
224
225const server = createYoga({
226 plugins: [
227 useHive({
228 enabled: true, // Enable/Disable Hive Client
229 token: 'YOUR-TOKEN',
230 usage: {
231 clientInfo(ctx: { req: Request }) {
232 const name = ctx.req.headers.get('x-graphql-client-name')
233 const version = ctx.req.headers.get('x-graphql-client-version') ?? 'missing'
234
235 if (name) {
236 return { name, version }
237 }
238
239 return null
240 }
241 }
242 })
243 ]
244})
245
246server.start()
247```
248
249#### Envelop Example
250
251```ts
252import { envelop } from '@envelop/core'
253import { useHive } from '@graphql-hive/client'
254
255const envelopProxy = envelop({
256 plugins: [
257 useHive({
258 enabled: true, // Enable/Disable Hive Client
259 token: 'YOUR-TOKEN',
260 usage: {
261 clientInfo(ctx: { req: Request }) {
262 const name = ctx.req.headers.get('x-graphql-client-name')
263 const version = ctx.req.headers.get('x-graphql-client-version') ?? 'missing'
264
265 if (name) {
266 return { name, version }
267 }
268
269 return null
270 }
271 }
272 })
273 ]
274})
275```
276
277#### Apollo Server Example
278
279```ts
280import { ApolloServer } from 'apollo-server'
281import { hiveApollo } from '@graphql-hive/client'
282import type { IncomingMessage } from 'http'
283
284const server = new ApolloServer({
285 typeDefs,
286 resolvers,
287 plugins: [
288 hiveApollo({
289 enabled: true, // Enable/Disable Hive Client
290 token: 'YOUR-TOKEN',
291 usage: {
292 clientInfo(ctx: { req: IncomingMessage }) {
293 const name = ctx.req.headers['x-graphql-client-name']
294 const version = ctx.req.headers['x-graphql-client-version'] ?? 'missing'
295
296 if (name) {
297 return { name, version }
298 }
299
300 return null
301 }
302 }
303 })
304 ]
305})
306```