Skip to content

Commit

Permalink
Subscriptions (#36)
Browse files Browse the repository at this point in the history
* subscriptions

* subs docs
  • Loading branch information
zth authored Aug 26, 2024
1 parent 9e2717d commit a111892
Show file tree
Hide file tree
Showing 14 changed files with 852 additions and 571 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
## main

- Disallow inferring input objects. It's not worth the complexity right now.
- Add support for subscriptions.

## 0.12.0

Expand Down
4 changes: 2 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -121,7 +121,7 @@ ResGraph lets you build _implementation first_ GraphQL servers, where your types

- [x] Query
- [x] Mutations
- [ ] Subscriptions
- [x] Subscriptions
- [x] Context
- [x] Object types
- [x] Input types
Expand All @@ -130,7 +130,7 @@ ResGraph lets you build _implementation first_ GraphQL servers, where your types
- [x] Unions
- [x] Custom scalars (including custom serializers/parsers)
- [ ] Directives
- [ ] Relay helpers (coming very soon)
- [x] Relay helpers (coming very soon)

## Development notes

Expand Down
43 changes: 42 additions & 1 deletion docs/docs/subscriptions.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,4 +4,45 @@ sidebar_position: 9

# Subscriptions

Subscriptions are not yet a thing in ResGraph, but they will be eventually.
You can add a subscription to your schema by defining a `subscription` type and then attaching resolvers to it. All subscription resolvers _must return an [`AsyncIterator.t`](https://rescript-lang.org/docs/manual/latest/api/core/asynciterator)_ with a valid GraphQL type.

Let's look at an example:

```rescript
// Define the subscription type
@gql.type
type subscription
let wait = ms => {
Promise.make((resolve, _) => {
let _ = setTimeout(() => resolve(), ms)
})
}
@gql.field
let countdown = (_: subscription, ~from: int) => {
let countdown = ref(from)
let iterator = AsyncIterator.make(async () => {
await wait(500)
let current = countdown.contents
countdown := current - 1
if current > 0 {
AsyncIterator.value(current)
} else {
AsyncIterator.done(~finalValue=current)
}
})
iterator
}
```

This would produce the following schema:

```graphql
type Subscription {
countdown(from: Int!): Int!
}
```
44 changes: 44 additions & 0 deletions example/src/schema/GraphQLSchema.res
Original file line number Diff line number Diff line change
Expand Up @@ -63,3 +63,47 @@ let shop = (_: query, ~input: findShopInput) => {
| ByCoordinates(_) => Some("Coordinates")
}
}

@gql.type
type subscription

let wait = ms => {
Promise.make((resolve, _) => {
let _ = setTimeout(() => resolve(), ms)
})
}

let makeAsyncIterator: (unit => promise<AsyncIterator.value<'value>>) => AsyncIterator.t<
'value,
> = %raw(`function makeAsyncIterator(next) {
return {
next,
[Symbol.asyncIterator]() {
return this;
}
}
}`)

@gql.field
let countdown = (_: subscription) => {
let countdown = ref(10)
let iterator = makeAsyncIterator(async () => {
await wait(500)
let current = countdown.contents
countdown := current - 1

if current > 0 {
{
AsyncIterator.done: false,
value: Some(current),
}
} else {
{
AsyncIterator.done: true,
value: Some(current),
}
}
})

iterator
}
38 changes: 36 additions & 2 deletions example/src/schema/__generated__/ResGraphSchema.res

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 4 additions & 0 deletions example/src/schema/__generated__/schema.graphql

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Loading

0 comments on commit a111892

Please sign in to comment.