Custom Subscriptions
You can add subscriptions to the GraphQL schema that do not result from an Entity.
SubscriptionConfig
| Config | Type | Default | Description |
|---|---|---|---|
| type | string | the type of data the subscription sends to the client when the subscribed event happens | |
| args | {[name:string]:string} | Arguments for this subscription; can be used in the subscribe method | |
| subscribe | string | Function | Name of the Subscription | the topic of the Publish/Subscribe; this is the identifier an emitter of the Event we're subscribing must publish |
| filter | (payload:any) => boolean | return value of this method determines whether the Subscription clients will be informed about a published event | |
| resolve | (payload:any) => any | return value is sent to the Subscription clients |
You can use a shortcut and just state the type of the data instead of the SubscriptionConfig object. The rest will behave per default.
Example
In this example we define a Query "greeting" that defines one param "name" and returns a greeting using that "name". We add a Subscription that informs us any time someone calls the Query "greeting" including the "name".
import { DomainConfiguration } from "activeql-foundation";
export const domainConfiguration: DomainConfiguration = {
query: {
Greeting: {
type: "String",
args: { name: 'String!' },
resolve: (root:any, {name}, {runtime} ) => {
runtime.subscription.publish('Greeted', name );
return `Hey ${name}, have a great day`
}
}
},
subscription: {
Greeted: 'String'
}
}When we run the Subscription as follows in the GraphQL Explorer, watch the "Subscriptions" section. It should show Status: Listening
subscription Subscription {
Greeted
}Once we call the "Greeting" Query we should see the data in the "Subscriptions" section:
query{
greeting( name: "Thomas")
}// Response received at 20:02:21
{
"data": {
"Greeted": "Thomas"
}
}Custom Implementations
Instead of relying on the default implementations you can implement the methods yourself. The example from above could be written as follows with the same result.
export const domainConfiguration: DomainConfiguration = {
subscription: {
Greeted: {
type: 'String',
args: { topic: 'String' },
subscribe: (root:any, {topic}, {runtime} ) => {
return runtime.subcriptions.asyncIterator( topic )
},
filter: (payload:string) => {
return true;
},
resolve(payload) {
return payload;
},
}
}
}The only difference is that we add an argument to the args of the subscription and use its value as the topic for the subscribe/publish. So to subscribe to the "Greeted" event the subscription must be called like this:
subscription Subscription {
Greeted( topic: "Greeted" )
}subscribe
subscribe: (rootValue?: any, args?: any, context?: any, info?: any) => AsyncIterator<any>
This method must return an AsyncIterator that can be get from the Runtime.subscriptions object. The trigger parameter is the topic of the Publish/Subscribe; this is the identifier an emitter of the Event we're subscribing must publish.
filter
filter: (payload:any) => boolean
This method can determine whether a certain payload is sent to the client. The payload is published by the Emitter of the Event we're subscribing. E.g. when any emitter publishes the event like so:
runtime.subscription.publish( 'Greeted', {name: 'Thomas', age: 23} );the payload in the filter method is {name: 'Thomas', age: 23} and you can use that to determine whether subscription clients should be informed. E.g. with the following example only when the "age" property of the payload is above or equal 18 data are sent to the subscription clients.
{
filter: payload => _.get( payload, 'age', 0 ) >= 18
}resolve
resolve: (payload:any) => any
The result of the resolve method is sent to the client. Given a payload like {name: 'Thomas', age: 23} this example takes a property from the payload, converts it to upper cases and sends it to the Subscription clients:
{
resolve: payload => _.toUpper( _.get( payload, 'name' ) )
}// Response received at 20:02:21
{
"data": {
"Greeted": "THOMAS"
}
}