Subscriptions
Define Subscription fields using the @gqlkit-ts/runtime API.
Prerequisites: This guide assumes you have completed the basic setup.
Setup
Export defineSubscription from your gqlkit.ts:
import { createGqlkitApis } from "@gqlkit-ts/runtime";
import type { Context } from "./context";
export const { defineQuery, defineMutation, defineSubscription } =
createGqlkitApis<Context>();Subscription Resolvers
Use defineSubscription to define Subscription fields. The resolver is typically an async generator function:
import { defineSubscription } from "../gqlkit";
import type { Message } from "./message";
// Subscription.messageAdded(channelId: String!)
export const messageAdded = defineSubscription<
{ channelId: string },
Message
>(async function* (_root, args, ctx) {
yield* ctx.pubsub.subscribe<Message>("MESSAGE_ADDED", args.channelId);
});Generates:
type Subscription {
messageAdded(channelId: String!): Message!
}The same export name conventions apply as with Queries & Mutations:
// GraphQL field name: messageAdded
export const Subscription$messageAdded = defineSubscription<
{ channelId: string },
Message
>(async function* (_root, args, ctx) {
yield* ctx.pubsub.subscribe<Message>("MESSAGE_ADDED", args.channelId);
});NoArgs Subscriptions
For subscriptions without arguments, use NoArgs as the first type parameter — same as with defineQuery and defineMutation. See Queries & Mutations for details.
Resolver Function Signature
Subscription resolvers receive the same four arguments as Query/Mutation resolvers, but return an AsyncIterable instead of a direct value:
(root, args, ctx, info) => AsyncIterable<T> | Promise<AsyncIterable<T>>| Argument | Description |
|---|---|
root | The root value (always undefined) |
args | The arguments passed to the field |
ctx | The context object (typed via createGqlkitApis<Context>()) |
info | GraphQL resolve info |
Inline Object Arguments
Subscription arguments support the same inline object types as queries and mutations:
export const orderUpdated = defineSubscription<
{
filter: {
orderId: string | null;
status: string | null;
};
},
Order
>(async function* (_root, args, ctx) {
yield* ctx.pubsub.subscribe<Order>("ORDER_UPDATED", args.filter);
});Generates:
type Subscription {
orderUpdated(filter: OrderUpdatedFilterInput!): Order!
}
input OrderUpdatedFilterInput {
orderId: String
status: String
}Attaching Directives
Add a third type parameter to attach directives:
import { defineSubscription } from "../gqlkit";
import type { AuthDirective } from "./directives";
import type { Message } from "./message";
export const messageAdded = defineSubscription<
{ channelId: string },
Message,
[AuthDirective<{ role: ["USER"] }>]
>(async function* (_root, args, ctx) {
yield* ctx.pubsub.subscribe<Message>("MESSAGE_ADDED", args.channelId);
});Generates:
type Subscription {
messageAdded(channelId: String!): Message! @auth(role: [USER])
}See Directives for more details on defining and using custom directives.
Documentation
TSDoc comments on subscription exports are extracted as GraphQL descriptions:
/** Subscribe to new messages in a channel. */
export const messageAdded = defineSubscription<
{ channelId: string },
Message
>(async function* (_root, args, ctx) {
yield* ctx.pubsub.subscribe<Message>("MESSAGE_ADDED", args.channelId);
});
/**
* @deprecated Use messageAdded instead.
*/
export const onMessage = defineSubscription<
{ channelId: string },
Message
>(async function* (_root, args, ctx) {
yield* ctx.pubsub.subscribe<Message>("MESSAGE_ADDED", args.channelId);
});Generates:
type Subscription {
"""Subscribe to new messages in a channel."""
messageAdded(channelId: String!): Message!
onMessage(channelId: String!): Message! @deprecated(reason: "Use messageAdded instead.")
}See Documentation for more details.