graphql-firestore-subscriptions
v1.0.1
Published
A simple & powerful package to broadcast events from Cloud Firestore over an AsyncIterator to your GraphQL Subscription Resolver.
Downloads
383
Maintainers
Readme
graphql-firestore-subscriptions
graphql-firestore-subscriptions implements the PubSubEngine
interface from the graphql-subscriptions package.
Unlike other databases, Goole's Firestore comes across with real time updates. Therefore, it is not required to publish events to a queue or a pub-sub. However, there is still something to do to get the data to the clients. In graphql-firestore-subscriptions thus tasks are called handlers. They are subscribing a specific topic and broadcast whatever you want over an AsyncIterator which is compatible with graphql-subscriptions.
Usage
First of all, you have to install the graphql-firestore-subscriptions package using yarn or npm by calling either yarn add graphql-firestore-subscriptions
or npm i --save graphql-firestore-subscriptions
.
Create a new graphql-firestore-subscription instance
import PubSub from 'graphql-firestore-subscriptions';
const ps = new PubSub();
Adding handlers
A handler gets two arguments:
- The
broadcast
function itself to send new data - An object with options
Note, that the handler MUST return a unsubscribe function.
ps.registerHandler(() => {
// subscribe to a topic
return () => {
// unsubscribe
};
});
The unsubscribe function can either return void or a boolean value. If a boolean value is returned by the unsubscribe function, the PubSubEngine
will throw an error if the return value is falsey.
Advanced handlers
Unlike other graphql-subscriptions, graphql-firestore-subscriptions
requires a handler for each topic you are about to subscribe.
To make the handler-creation as easy as possibile graphql-firestore-subscriptions comes across with a bunch of utility functions.
The following example shows a simple fall-through handler which takes document changes of a collection to broadcast this changes immediately.
import PubSub, { createFallThroughHandler } from 'graphql-firestore-subscriptions';
import db from '../path/to/firestore/conenction';
// ...
enum Topic {
NEW_COMMENT = 'NEW_COMMENT',
}
ps.registerHandler(
...createFallThroughHandler(db, {
topic: Topic.NEW_COMMENT,
collection: 'comment',
filter: ['added'],
})
);
You can also create multiple fall-through handlers at once:
import PubSub, { createFallThroughHandlerFromMap } from 'graphql-firestore-subscriptions';
import db from '../path/to/firestore/conenction';
// ...
enum Topic {
NEW_COMMENT = 'NEW_COMMENT',
UPDATE_COMMENT = 'UPDATE_COMMENT',
}
createFallThroughHandlerFromMap(db, {
[Topic.NEW_COMMENT]: {
collection: 'comment',
filter: ['added'],
},
[Topic.UPDATE_COMMENT]: {
collection: 'comment',
filter: ['modified'],
},
}).forEach((topic, handler) => ps.registerHandler(topic, handler));
See API for additional information about how createFallThroughHandlerFromMap
/ createFallThroughHandler
work.
Full example
import PubSub from 'graphql-firestore-subscriptions';
import db from '../path/to/firestore/conenction';
enum Topic {
NEW_COMMENT = 'NEW_COMMENT',
}
const ps = new PubSub();
ps.registerHandler(Topic.NEW_COMMENT, broadcast =>
// Note, that `onSnapshot` returns a unsubscribe function which
// returns void.
db.collection('comments').onSnapshot(snapshot => {
snapshot
.docChanges()
.filter(change => change.type === 'added')
.map(item => broadcast(item.data()));
})
);
const iterator = ps.asyncIterator(Topic.NEW_COMMENT);
const addedComment = await iterator.next();
// ...
With apollo-server-graphql
Define a GraphQL schema with a Subscription
type.
schema {
query: Query
mutation: Mutation
subscription: Subscription
}
type Subscription {
newComment: Comment
}
type Comment {
message: String
}
Now, implement the resolver:
export const resolvers = {
Subscription: {
newComment: {
subscribe: () => ps.asyncIterator(Topic.NEW_COMMENT),
},
},
};
Calling asyncIterator(topics: string | string[])
will subscribe to the given topics and will return an AsyncIterator binded to the PubSubEngine
of graphql-firestore-subscriptions.
Everytime, a handler calls the obtained broadcast
-function, the PubSubEngine
of graphql-firestore-subscriptions will publish the event.
API
createFallThroughHandler
function createFallThroughHandler(
fs: Firestore,
overwriteOptions: FallThroughHandlerOptions
): [string, Handler];
Options
| Name | Type | Description |
| -------------- | ----------------------------------------------------- | ------------------------------------------------------------- |
| topic
* | string
| - |
| collection
* | string
| The firebase collection |
| transform
| TransformStrategy | (change: DocumentChange) => any
| Called to transform the broadcast-payload |
| filter
| (change: DocumentChange) => boolean
| Called to filter document changes before they are broadcasted |
* required
createFallThroughHandlerFromMap
function createFallThroughHandlerFromMap(
fs: Firestore,
options: FallThroughHandlerFromMapOptions
): [string, Handler][];
Options
| Name | Type | Description |
| ----- | ------------------------- | ------------------------------------------------------------ |
| topic | [topic: string]: Object
| See createFallThroughHandler#Options for a complete overview |
Contribute
Something is broken? The documentation is incorrect? You're missing a feature? ...and you wanna help? That's great.
The following steps are describing the way from an idea / bug / ... to a pull-request.
- Fork this repository
- Apply the changes
- Write tests (you can execute the current tests by calling
npm run test:unit
ORnpm run test:unit:watch
) - If necessary, update the documentation
- Open a pull-request
- :tada: