Domain configuration
More
Custom subscriptions

Custom Subscriptions

You can add subscriptions to the GraphQL schema that do not result from an Entity.

SubscriptionConfig

ConfigTypeDefault Description
typestringthe 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
subscribestring | FunctionName of the Subscriptionthe topic of the Publish/Subscribe; this is the identifier an emitter of the Event we're subscribing must publish
filter(payload:any) => booleanreturn value of this method determines whether the Subscription clients will be informed about a published event
resolve(payload:any) => anyreturn 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"
  }
}