parent
9f01342248
commit
2de6f8971e
|
|
@ -0,0 +1,150 @@
|
|||
---
|
||||
title: subscriptionType
|
||||
codeStyle: true
|
||||
---
|
||||
|
||||
## subscriptionType
|
||||
|
||||
```ts
|
||||
subscriptionType(typeName:string, fn: SubscriptionTypeConfig): NexusSubscriptionType
|
||||
```
|
||||
|
||||
Create a GraphQL `Subscription` type.
|
||||
|
||||
A subscription type configuration field is like an object type with the following differences:
|
||||
|
||||
1. It has a `subscribe` field. You should return an async iterator here. This is called once for each subscription a client sends.
|
||||
2. The `root` param of the `resolve` field is called for each promise returned by the async iterator setup. The resolver is responsible for transforming the shape of data returned by your subscription stream into types that conform to your GraphQL schema.
|
||||
|
||||
Here is a runnable example using Apollo Server and Apollo PubSub with Express.
|
||||
|
||||
```ts
|
||||
import { ApolloServer, PubSub } from 'apollo-server-express'
|
||||
import express from 'express'
|
||||
import * as HTTP from 'http'
|
||||
import * as path from 'path'
|
||||
import {
|
||||
arg,
|
||||
inputObjectType,
|
||||
makeSchema,
|
||||
mutationType,
|
||||
objectType,
|
||||
subscriptionType,
|
||||
} from '@nexus/schema'
|
||||
|
||||
const pubsub = new PubSub()
|
||||
|
||||
const schema = makeSchema({
|
||||
shouldExitAfterGenerateArtifacts:
|
||||
process.env.NEXUS_SHOULD_EXIT_AFTER_GENERATE_ARTIFACTS === 'true',
|
||||
outputs: {
|
||||
typegen: path.join(__dirname, 'node_modules/@types/nexus-typegen/index.d.ts'),
|
||||
schema: path.join(__dirname, './api.graphql'),
|
||||
},
|
||||
types: [
|
||||
mutationType({
|
||||
definition(t) {
|
||||
t.field('createOneUser', {
|
||||
type: 'User',
|
||||
args: {
|
||||
data: arg({
|
||||
required: true,
|
||||
type: inputObjectType({
|
||||
name: 'CreateOneUserInput',
|
||||
definition(t) {
|
||||
t.string('email', { required: true })
|
||||
},
|
||||
}),
|
||||
}),
|
||||
},
|
||||
async resolve(_, args) {
|
||||
const data = args.data
|
||||
await pubsub.publish('user_added', { data })
|
||||
return data
|
||||
},
|
||||
})
|
||||
},
|
||||
}),
|
||||
subscriptionType({
|
||||
definition(t) {
|
||||
t.field('createOneUser', {
|
||||
type: 'User',
|
||||
subscribe() {
|
||||
return pubsub.asyncIterator('user_added')
|
||||
},
|
||||
async resolve(userPromise) {
|
||||
const user = await userPromise.data
|
||||
return user
|
||||
},
|
||||
})
|
||||
},
|
||||
}),
|
||||
objectType({
|
||||
name: 'User',
|
||||
definition(t) {
|
||||
t.string('email')
|
||||
},
|
||||
}),
|
||||
],
|
||||
})
|
||||
|
||||
const apollo = new ApolloServer({ schema })
|
||||
const app = express()
|
||||
const http = HTTP.createServer(app)
|
||||
|
||||
apollo.applyMiddleware({ app })
|
||||
apollo.installSubscriptionHandlers(http)
|
||||
|
||||
http.listen(4000, () => {
|
||||
console.log(`🚀 GraphQL service ready at http://localhost:4000/graphql`)
|
||||
})
|
||||
```
|
||||
|
||||
Here is a runnable example with a minimalistic schema.
|
||||
|
||||
```ts
|
||||
import { ApolloServer } from 'apollo-server-express'
|
||||
import express from 'express'
|
||||
import * as HTTP from 'http'
|
||||
import * as path from 'path'
|
||||
import { makeSchema, subscriptionType } from '@nexus/schema'
|
||||
|
||||
const schema = makeSchema({
|
||||
shouldExitAfterGenerateArtifacts:
|
||||
process.env.NEXUS_SHOULD_EXIT_AFTER_GENERATE_ARTIFACTS === 'true',
|
||||
outputs: {
|
||||
typegen: path.join(__dirname, 'node_modules/@types/nexus-typegen/index.d.ts'),
|
||||
schema: path.join(__dirname, './api.graphql'),
|
||||
},
|
||||
types: [
|
||||
subscriptionType({
|
||||
definition(t) {
|
||||
t.boolean('truths', {
|
||||
subscribe() {
|
||||
return (async function*() {
|
||||
while (true) {
|
||||
await new Promise(res => setTimeout(res, 1000))
|
||||
yield Math.random() > 0.5
|
||||
}
|
||||
})()
|
||||
},
|
||||
resolve(eventData) {
|
||||
return eventData
|
||||
},
|
||||
})
|
||||
},
|
||||
}),
|
||||
],
|
||||
})
|
||||
|
||||
const apollo = new ApolloServer({ schema })
|
||||
const app = express()
|
||||
const http = HTTP.createServer(app)
|
||||
|
||||
apollo.applyMiddleware({ app })
|
||||
apollo.installSubscriptionHandlers(http)
|
||||
|
||||
http.listen(4000, () => {
|
||||
console.log(`🚀 GraphQL service ready at http://localhost:4000/graphql`)
|
||||
})
|
||||
```
|
||||
|
|
@ -0,0 +1,29 @@
|
|||
---
|
||||
title: subscriptionField
|
||||
codeStyle: true
|
||||
---
|
||||
|
||||
## subscriptionField
|
||||
|
||||
Often times you want to split up subscription fields into different domains of your application.
|
||||
|
||||
Like `queryField` and `mutationField` except that like `subscriptionType` the `subscribe` field is required on the type configuration. Refer to [`subscriptionType`](/api/subscription-type) docs for details
|
||||
|
||||
```ts
|
||||
import { subscriptionField } from '@nexus/schema'
|
||||
|
||||
export const SubscriptionField = subscriptionField('truths', {
|
||||
type: 'Boolean',
|
||||
subscribe() {
|
||||
return (async function*() {
|
||||
while (true) {
|
||||
await new Promise(res => setTimeout(res, 1000))
|
||||
yield Math.random() > 0.5
|
||||
}
|
||||
})()
|
||||
},
|
||||
resolve(eventData) {
|
||||
return eventData
|
||||
},
|
||||
})
|
||||
```
|
||||
|
|
@ -1,5 +1,5 @@
|
|||
import { extendType } from './extendType'
|
||||
import { SubscribeFieldConfig } from './subscriptionType'
|
||||
import { SubscriptionTypeConfig } from './subscriptionType'
|
||||
|
||||
/**
|
||||
* Add one field to the Subscription type
|
||||
|
|
@ -7,8 +7,8 @@ import { SubscribeFieldConfig } from './subscriptionType'
|
|||
export function subscriptionField<FieldName extends string>(
|
||||
fieldName: FieldName,
|
||||
config:
|
||||
| SubscribeFieldConfig<'Subscription', FieldName>
|
||||
| (() => SubscribeFieldConfig<'Subscription', FieldName>)
|
||||
| SubscriptionTypeConfig<'Subscription', FieldName>
|
||||
| (() => SubscriptionTypeConfig<'Subscription', FieldName>)
|
||||
) {
|
||||
return extendType({
|
||||
type: 'Subscription',
|
||||
|
|
|
|||
|
|
@ -1,12 +1,12 @@
|
|||
import { GraphQLResolveInfo } from 'graphql'
|
||||
import { ArgsValue, GetGen, MaybePromise, MaybePromiseDeep, ResultValue } from '../typegenTypeHelpers'
|
||||
import { IsEqual } from '../utils'
|
||||
import { BaseScalars } from './_types'
|
||||
import { CommonOutputFieldConfig, NexusOutputFieldDef } from './definitionBlocks'
|
||||
import { ObjectDefinitionBuilder, objectType } from './objectType'
|
||||
import { AllNexusOutputTypeDefs } from './wrapping'
|
||||
import { BaseScalars } from './_types'
|
||||
|
||||
export interface SubscribeFieldConfigBase<FieldName extends string, Event = any> {
|
||||
export interface SubscriptionTypeConfigBase<FieldName extends string, Event = any> {
|
||||
resolve(
|
||||
root: Event,
|
||||
args: ArgsValue<'Subscription', FieldName>,
|
||||
|
|
@ -27,11 +27,11 @@ export interface SubscribeFieldConfigBase<FieldName extends string, Event = any>
|
|||
// prettier-ignore
|
||||
export type FieldShorthandConfig<FieldName extends string> =
|
||||
CommonOutputFieldConfig<'Subscription', FieldName>
|
||||
& SubscribeFieldConfigBase<FieldName>
|
||||
& SubscriptionTypeConfigBase<FieldName>
|
||||
|
||||
// prettier-ignore
|
||||
export interface SubscribeFieldConfig<TypeName extends string, FieldName extends string>
|
||||
extends SubscribeFieldConfigBase<FieldName>,
|
||||
export interface SubscriptionTypeConfig<TypeName extends string, FieldName extends string>
|
||||
extends SubscriptionTypeConfigBase<FieldName>,
|
||||
CommonOutputFieldConfig<'Subscription', FieldName>
|
||||
{
|
||||
type: GetGen<'allOutputTypes'> | AllNexusOutputTypeDefs
|
||||
|
|
@ -71,7 +71,7 @@ export class SubscriptionBuilder {
|
|||
}
|
||||
|
||||
// prettier-ignore
|
||||
field<FieldName extends string>(name: FieldName, fieldConfig: SubscribeFieldConfig<'Subscription', FieldName>) {
|
||||
field<FieldName extends string>(name: FieldName, fieldConfig: SubscriptionTypeConfig<'Subscription', FieldName>) {
|
||||
this.typeBuilder.addField(this.decorateField({ name, ...fieldConfig } as any))
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue