graphql-subscriptions
Advanced tools
Comparing version 2.0.0 to 3.0.0
# Changelog | ||
### 3.0.0 | ||
- **[BREAKING]** Replace `iterall` use with native `Symbol.asyncIterator`. `PubSubEngine.asyncIterator` is now `PubSubEngine.asyncIterableIterator`. <br/> | ||
[@n1ru4l](https://github.com/n1ru4l) in [#232](https://github.com/apollographql/graphql-subscriptions/pull/232) | ||
- Add an optional generic type map to `PubSub`. <br/> | ||
[@cursorsdottsx](https://github.com/cursorsdottsx) in [#245](https://github.com/apollographql/graphql-subscriptions/pull/245) | ||
- Support `readonly` arrays of event names. <br/> | ||
[@rh389](https://github.com/rh389) in [#234](https://github.com/apollographql/graphql-subscriptions/pull/234) | ||
- Support returning a Promise of an `AsyncIterator` as the `withFilter` resolver function. <br/> | ||
[@maclockard](https://github.com/maclockard) in [#220](https://github.com/apollographql/graphql-subscriptions/pull/220) | ||
- `withFilter` TypeScript improvements. <br/> | ||
[@HofmannZ](https://github.com/HofmannZ) in [#230](https://github.com/apollographql/graphql-subscriptions/pull/230) | ||
- `withFilter` returns `AsyncIterableIterator` for compatibility with Apollo Server subscriptions. <br/> | ||
[@tninesling](https://github.com/tninesling) in [#276](https://github.com/apollographql/graphql-subscriptions/pull/276) | ||
### 2.0.0 | ||
@@ -23,21 +38,25 @@ | ||
- BREAKING CHANGE: Changed return type of `publish`. <br/> | ||
- BREAKING CHANGE: Changed return type of `publish`. <br/> | ||
[@grantwwu](https://github.com/grantwwu) in [#162](https://github.com/apollographql/graphql-subscriptions/pull/162) | ||
- Bump versions of various devDependencies to fix security issues, use | ||
newer tslint config. <br/> | ||
newer tslint config. <br/> | ||
[@grantwwu](https://github.com/grantwwu) in [#163](https://github.com/apollographql/graphql-subscriptions/pull/163) | ||
- Allows `graphql` 14 as a peer dep, forces `graphql` 14 as a dev dep, and | ||
has been updated to use `@types/graphql` 14. <br/> | ||
has been updated to use `@types/graphql` 14. <br/> | ||
[@hwillson](https://github.com/hwillson) in [#172](https://github.com/apollographql/graphql-subscriptions/pull/172) | ||
### 0.5.8 | ||
- Bump iterall version | ||
### 0.5.7 | ||
- Add `graphql@0.13` to `peerDependencies`. | ||
### 0.5.6 | ||
- Add `graphql@0.12` to `peerDependencies`. | ||
### 0.5.5 | ||
- FilterFn can return a Promise<boolean> | ||
@@ -47,8 +66,11 @@ - Allow passing in a custom `EventEmitter` to `PubSub` | ||
### 0.5.4 | ||
- Better define `withFilter` return type [PR #111](https://github.com/apollographql/graphql-subscriptions/pull/111) | ||
### 0.5.3 | ||
- Require iterall ^1.1.3 to address unhandled exceptions | ||
### 0.5.2 | ||
- Require iterall ^1.1.2 to address memory leak [Issue #97] (https://github.com/apollographql/graphql-subscriptions/issues/97) | ||
@@ -58,5 +80,7 @@ - Remove `@types/graphql` dependency. [PR #105] (https://github.com/apollographql/graphql-subscriptions/pull/105) | ||
### 0.5.1 | ||
- `withFilter` now called with `(rootValue, args, context, info)` [PR #103] (https://github.com/apollographql/graphql-subscriptions/pull/103) | ||
### 0.5.0 | ||
- BREAKING CHANGE: Removed deprecated code. [PR #104] (https://github.com/apollographql/graphql-subscriptions/pull/104) | ||
@@ -66,14 +90,19 @@ - BREAKING CHANGE: Minimum GraphQL version bumped to 0.10.X. [PR #104] (https://github.com/apollographql/graphql-subscriptions/pull/104) | ||
### 0.4.4 | ||
- Avoid infinite loop after the last consumer unsubscribes, [Issue #81](https://github.com/apollographql/graphql-subscriptions/issues/81) [PR #84](https://github.com/apollographql/graphql-subscriptions/pull/84) | ||
### 0.4.3 | ||
- Properly propagate return() and throw() through withFilter [PR #74](https://github.com/apollographql/graphql-subscriptions/pull/74) | ||
### 0.4.2 | ||
- Fixed issue with `withFilter` causing to use the same iterator [PR #69](https://github.com/apollographql/graphql-subscriptions/pull/69) | ||
### 0.4.1 | ||
- Fixed exports issue with TypeScript [PR #65](https://github.com/apollographql/graphql-subscriptions/pull/65) | ||
### 0.4.0 | ||
- Added `asyncIterator(channelName: string)` to `PubSub` implementation [PR #60](https://github.com/apollographql/graphql-subscriptions/pull/60) | ||
@@ -85,5 +114,7 @@ - Added `withFilter` to allow `AsyncIterator` filtering [PR #60](https://github.com/apollographql/graphql-subscriptions/pull/60) | ||
### 0.3.1 | ||
- Add support for `defaultValue`, fixes [#49](https://github.com/apollographql/graphql-subscriptions/issues/49) (https://github.com/apollographql/graphql-subscriptions/pull/50) | ||
### 0.3.0 | ||
- Allow `setupFunctions` to be async (return `Promise`) (https://github.com/apollographql/graphql-subscriptions/pull/41) | ||
@@ -95,8 +126,11 @@ - Refactor promise chaining in pubsub engine (https://github.com/apollographql/graphql-subscriptions/pull/41) | ||
### 0.2.3 | ||
- update `graphql` dependency to 0.9.0 | ||
### 0.2.2 | ||
- made `graphql` a peer dependency and updated it to 0.8.2 | ||
### v 0.2.1 | ||
- Fixed a bug that caused subscriptions without operationName to fail |
export { PubSubEngine } from './pubsub-engine'; | ||
export { PubSub, PubSubOptions } from './pubsub'; | ||
export { withFilter, ResolverFn, FilterFn } from './with-filter'; | ||
export { withFilter, ResolverFn, FilterFn, IterableResolverFn } from './with-filter'; |
@@ -0,1 +1,2 @@ | ||
import { PubSubAsyncIterableIterator } from './pubsub-async-iterable-iterator'; | ||
export declare abstract class PubSubEngine { | ||
@@ -5,3 +6,3 @@ abstract publish(triggerName: string, payload: any): Promise<void>; | ||
abstract unsubscribe(subId: number): any; | ||
asyncIterator<T>(triggers: string | string[]): AsyncIterator<T>; | ||
asyncIterableIterator<T>(triggers: string | readonly string[]): PubSubAsyncIterableIterator<T>; | ||
} |
"use strict"; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
exports.PubSubEngine = void 0; | ||
var pubsub_async_iterator_1 = require("./pubsub-async-iterator"); | ||
var pubsub_async_iterable_iterator_1 = require("./pubsub-async-iterable-iterator"); | ||
var PubSubEngine = (function () { | ||
function PubSubEngine() { | ||
} | ||
PubSubEngine.prototype.asyncIterator = function (triggers) { | ||
return new pubsub_async_iterator_1.PubSubAsyncIterator(this, triggers); | ||
PubSubEngine.prototype.asyncIterableIterator = function (triggers) { | ||
return new pubsub_async_iterable_iterator_1.PubSubAsyncIterableIterator(this, triggers); | ||
}; | ||
@@ -11,0 +11,0 @@ return PubSubEngine; |
@@ -7,3 +7,5 @@ /// <reference types="node" /> | ||
} | ||
export declare class PubSub extends PubSubEngine { | ||
export declare class PubSub<Events extends { | ||
[event: string]: unknown; | ||
} = Record<string, never>> extends PubSubEngine { | ||
protected ee: EventEmitter; | ||
@@ -13,5 +15,5 @@ private subscriptions; | ||
constructor(options?: PubSubOptions); | ||
publish(triggerName: string, payload: any): Promise<void>; | ||
subscribe(triggerName: string, onMessage: (...args: any[]) => void): Promise<number>; | ||
publish<K extends keyof Events>(triggerName: K & string, payload: Events[K] extends never ? any : Events[K]): Promise<void>; | ||
subscribe<K extends keyof Events>(triggerName: K & string, onMessage: (...args: any[]) => void): Promise<number>; | ||
unsubscribe(subId: number): void; | ||
} |
@@ -1,3 +0,5 @@ | ||
export declare type FilterFn = (rootValue?: any, args?: any, context?: any, info?: any) => boolean | Promise<boolean>; | ||
export declare type ResolverFn = (rootValue?: any, args?: any, context?: any, info?: any) => AsyncIterator<any>; | ||
export declare const withFilter: (asyncIteratorFn: ResolverFn, filterFn: FilterFn) => ResolverFn; | ||
export type FilterFn<TSource = any, TArgs = any, TContext = any> = (rootValue?: TSource, args?: TArgs, context?: TContext, info?: any) => boolean | Promise<boolean>; | ||
export type ResolverFn<TSource = any, TArgs = any, TContext = any> = (rootValue?: TSource, args?: TArgs, context?: TContext, info?: any) => AsyncIterator<any> | Promise<AsyncIterator<any>>; | ||
export type IterableResolverFn<TSource = any, TArgs = any, TContext = any> = (rootValue?: TSource, args?: TArgs, context?: TContext, info?: any) => AsyncIterableIterator<any> | Promise<AsyncIterableIterator<any>>; | ||
export type WithFilter<TSource = any, TArgs = any, TContext = any> = (asyncIteratorFn: ResolverFn<TSource, TArgs, TContext>, filterFn: FilterFn<TSource, TArgs, TContext>) => IterableResolverFn<TSource, TArgs, TContext>; | ||
export declare function withFilter<TSource = any, TArgs = any, TContext = any>(asyncIteratorFn: ResolverFn<TSource, TArgs, TContext>, filterFn: FilterFn<TSource, TArgs, TContext>): IterableResolverFn<TSource, TArgs, TContext>; |
"use strict"; | ||
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { | ||
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } | ||
return new (P || (P = Promise))(function (resolve, reject) { | ||
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } | ||
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } | ||
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } | ||
step((generator = generator.apply(thisArg, _arguments || [])).next()); | ||
}); | ||
}; | ||
var __generator = (this && this.__generator) || function (thisArg, body) { | ||
var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g; | ||
return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g; | ||
function verb(n) { return function (v) { return step([n, v]); }; } | ||
function step(op) { | ||
if (f) throw new TypeError("Generator is already executing."); | ||
while (g && (g = 0, op[0] && (_ = 0)), _) try { | ||
if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t; | ||
if (y = 0, t) op = [op[0] & 2, t.value]; | ||
switch (op[0]) { | ||
case 0: case 1: t = op; break; | ||
case 4: _.label++; return { value: op[1], done: false }; | ||
case 5: _.label++; y = op[1]; op = [0]; continue; | ||
case 7: op = _.ops.pop(); _.trys.pop(); continue; | ||
default: | ||
if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; } | ||
if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; } | ||
if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; } | ||
if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; } | ||
if (t[2]) _.ops.pop(); | ||
_.trys.pop(); continue; | ||
} | ||
op = body.call(thisArg, _); | ||
} catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; } | ||
if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true }; | ||
} | ||
}; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
exports.withFilter = void 0; | ||
var iterall_1 = require("iterall"); | ||
var withFilter = function (asyncIteratorFn, filterFn) { | ||
return function (rootValue, args, context, info) { | ||
function withFilter(asyncIteratorFn, filterFn) { | ||
var _this = this; | ||
return function (rootValue, args, context, info) { return __awaiter(_this, void 0, void 0, function () { | ||
var asyncIterator, getNextPromise, asyncIterator2; | ||
var _a; | ||
var asyncIterator = asyncIteratorFn(rootValue, args, context, info); | ||
var getNextPromise = function () { | ||
return new Promise(function (resolve, reject) { | ||
var inner = function () { | ||
asyncIterator | ||
.next() | ||
.then(function (payload) { | ||
if (payload.done === true) { | ||
resolve(payload); | ||
return; | ||
} | ||
Promise.resolve(filterFn(payload.value, args, context, info)) | ||
.catch(function () { return false; }) | ||
.then(function (filterResult) { | ||
if (filterResult === true) { | ||
resolve(payload); | ||
return; | ||
} | ||
return __generator(this, function (_b) { | ||
switch (_b.label) { | ||
case 0: return [4, asyncIteratorFn(rootValue, args, context, info)]; | ||
case 1: | ||
asyncIterator = _b.sent(); | ||
getNextPromise = function () { | ||
return new Promise(function (resolve, reject) { | ||
var inner = function () { | ||
asyncIterator | ||
.next() | ||
.then(function (payload) { | ||
if (payload.done === true) { | ||
resolve(payload); | ||
return; | ||
} | ||
Promise.resolve(filterFn(payload.value, args, context, info)) | ||
.catch(function () { return false; }) | ||
.then(function (filterResult) { | ||
if (filterResult === true) { | ||
resolve(payload); | ||
return; | ||
} | ||
inner(); | ||
return; | ||
}); | ||
}) | ||
.catch(function (err) { | ||
reject(err); | ||
return; | ||
}); | ||
}; | ||
inner(); | ||
return; | ||
}); | ||
}) | ||
.catch(function (err) { | ||
reject(err); | ||
return; | ||
}); | ||
}; | ||
inner(); | ||
}); | ||
}; | ||
var asyncIterator2 = (_a = { | ||
next: function () { | ||
return getNextPromise(); | ||
}, | ||
return: function () { | ||
return asyncIterator.return(); | ||
}, | ||
throw: function (error) { | ||
return asyncIterator.throw(error); | ||
} | ||
}, | ||
_a[iterall_1.$$asyncIterator] = function () { | ||
return this; | ||
}, | ||
_a); | ||
return asyncIterator2; | ||
}; | ||
}; | ||
}; | ||
asyncIterator2 = (_a = { | ||
next: function () { | ||
return getNextPromise(); | ||
}, | ||
return: function () { | ||
return asyncIterator.return(); | ||
}, | ||
throw: function (error) { | ||
return asyncIterator.throw(error); | ||
} | ||
}, | ||
_a[Symbol.asyncIterator] = function () { | ||
return this; | ||
}, | ||
_a); | ||
return [2, asyncIterator2]; | ||
} | ||
}); | ||
}); }; | ||
} | ||
exports.withFilter = withFilter; | ||
; | ||
//# sourceMappingURL=with-filter.js.map |
{ | ||
"name": "graphql-subscriptions", | ||
"version": "2.0.0", | ||
"version": "3.0.0", | ||
"description": "GraphQL subscriptions for node.js", | ||
@@ -8,7 +8,5 @@ "main": "dist/index.js", | ||
"type": "git", | ||
"url": "https://github.com/apollostack/graphql-subscriptions.git" | ||
"url": "git+https://github.com/apollographql/graphql-subscriptions.git" | ||
}, | ||
"dependencies": { | ||
"iterall": "^1.3.0" | ||
}, | ||
"dependencies": {}, | ||
"peerDependencies": { | ||
@@ -31,19 +29,19 @@ "graphql": "^15.7.2 || ^16.0.0" | ||
"devDependencies": { | ||
"@types/chai-as-promised": "^7.1.3", | ||
"@types/chai-as-promised": "^7.1.4", | ||
"@types/graphql": "^14.5.0", | ||
"@types/mocha": "^8.0.0", | ||
"@types/node": "^14.0.23", | ||
"@types/sinon": "9.0.4", | ||
"@types/sinon-chai": "^3.2.4", | ||
"chai": "^4.2.0", | ||
"@types/mocha": "^9.0.0", | ||
"@types/node": "^16.11.9", | ||
"@types/sinon": "10.0.6", | ||
"@types/sinon-chai": "^3.2.5", | ||
"chai": "^4.3.4", | ||
"chai-as-promised": "^7.1.1", | ||
"graphql": "^16.0.0", | ||
"istanbul": "^1.0.0-alpha.2", | ||
"mocha": "^8.0.1", | ||
"istanbul": "^1.1.0-alpha.1", | ||
"mocha": "^9.1.3", | ||
"remap-istanbul": "^0.13.0", | ||
"rimraf": "^3.0.2", | ||
"sinon": "^9.0.2", | ||
"sinon-chai": "^3.5.0", | ||
"sinon": "^12.0.1", | ||
"sinon-chai": "^3.7.0", | ||
"tslint": "^6.1.2", | ||
"typescript": "^4.4.4" | ||
"typescript": "^4.5.2" | ||
}, | ||
@@ -50,0 +48,0 @@ "typings": "dist/index.d.ts", |
139
README.md
@@ -19,4 +19,4 @@ [![npm version](https://badge.fury.io/js/graphql-subscriptions.svg)](https://badge.fury.io/js/graphql-subscriptions) [![GitHub license](https://img.shields.io/github/license/apollostack/graphql-subscriptions.svg)](https://github.com/apollographql/graphql-subscriptions/blob/master/LICENSE) | ||
* ensure that your `tsconfig.json` `lib` definition includes `"esnext.asynciterable"` | ||
* `npm install @types/graphql` or `yarn add @types/graphql` | ||
- ensure that your `tsconfig.json` `lib` definition includes `"es2018.asynciterable"` | ||
- `npm install @types/graphql` or `yarn add @types/graphql` | ||
@@ -29,7 +29,7 @@ ### Getting started with your first subscription | ||
type Subscription { | ||
somethingChanged: Result | ||
somethingChanged: Result | ||
} | ||
type Result { | ||
id: String | ||
id: String | ||
} | ||
@@ -52,3 +52,3 @@ ``` | ||
```js | ||
import { PubSub } from 'graphql-subscriptions'; | ||
import { PubSub } from "graphql-subscriptions"; | ||
@@ -58,6 +58,26 @@ export const pubsub = new PubSub(); | ||
Now, implement your Subscriptions type resolver, using the `pubsub.asyncIterator` to map the event you need: | ||
If you're using TypeScript you can use the optional generic parameter for added type-safety: | ||
```ts | ||
import { PubSub } from "graphql-subscriptions"; | ||
const pubsub = new PubSub<{ | ||
EVENT_ONE: { data: number }; | ||
EVENT_TWO: { data: string }; | ||
}>(); | ||
pubsub.publish("EVENT_ONE", { data: 42 }); | ||
pubsub.publish("EVENTONE", { data: 42 }); // ! ERROR | ||
pubsub.publish("EVENT_ONE", { data: "42" }); // ! ERROR | ||
pubsub.publish("EVENT_TWO", { data: "hello" }); | ||
pubsub.subscribe("EVENT_ONE", () => {}); | ||
pubsub.subscribe("EVENTONE", () => {}); // ! ERROR | ||
pubsub.subscribe("EVENT_TWO", () => {}); | ||
``` | ||
Next implement your Subscriptions type resolver using the `pubsub.asyncIterableIterator` to map the event you need: | ||
```js | ||
const SOMETHING_CHANGED_TOPIC = 'something_changed'; | ||
const SOMETHING_CHANGED_TOPIC = "something_changed"; | ||
@@ -67,6 +87,6 @@ export const resolvers = { | ||
somethingChanged: { | ||
subscribe: () => pubsub.asyncIterator(SOMETHING_CHANGED_TOPIC), | ||
subscribe: () => pubsub.asyncIterableIterator(SOMETHING_CHANGED_TOPIC), | ||
}, | ||
}, | ||
} | ||
}; | ||
``` | ||
@@ -76,6 +96,6 @@ | ||
Now, the GraphQL engine knows that `somethingChanged` is a subscription, and every time we use `pubsub.publish` over this topic - it will publish it using the transport we use: | ||
The GraphQL engine now knows that `somethingChanged` is a subscription, and every time we use `pubsub.publish` it will publish content using our chosen transport layer: | ||
```js | ||
pubsub.publish(SOMETHING_CHANGED_TOPIC, { somethingChanged: { id: "123" }}); | ||
pubsub.publish(SOMETHING_CHANGED_TOPIC, { somethingChanged: { id: "123" } }); | ||
``` | ||
@@ -93,3 +113,4 @@ | ||
`withFilter` API: | ||
- `asyncIteratorFn: (rootValue, args, context, info) => AsyncIterator<any>` : A function that returns `AsyncIterator` you got from your `pubsub.asyncIterator`. | ||
- `asyncIteratorFn: (rootValue, args, context, info) => AsyncIterator<any>` : A function that returns `AsyncIterator` you got from your `pubsub.asyncIterableIterator`. | ||
- `filterFn: (payload, variables, context, info) => boolean | Promise<boolean>` - A filter function, executed with the payload (the published value), variables, context and operation info, must return `boolean` or `Promise<boolean>` indicating if the payload should pass to the subscriber. | ||
@@ -100,5 +121,5 @@ | ||
```js | ||
import { withFilter } from 'graphql-subscriptions'; | ||
import { withFilter } from "graphql-subscriptions"; | ||
const SOMETHING_CHANGED_TOPIC = 'something_changed'; | ||
const SOMETHING_CHANGED_TOPIC = "something_changed"; | ||
@@ -108,8 +129,11 @@ export const resolvers = { | ||
somethingChanged: { | ||
subscribe: withFilter(() => pubsub.asyncIterator(SOMETHING_CHANGED_TOPIC), (payload, variables) => { | ||
return payload.somethingChanged.id === variables.relevantId; | ||
}), | ||
subscribe: withFilter( | ||
() => pubsub.asyncIterableIterator(SOMETHING_CHANGED_TOPIC), | ||
(payload, variables) => { | ||
return payload.somethingChanged.id === variables.relevantId; | ||
} | ||
), | ||
}, | ||
}, | ||
} | ||
}; | ||
``` | ||
@@ -124,5 +148,5 @@ | ||
```js | ||
const SOMETHING_UPDATED = 'something_updated'; | ||
const SOMETHING_CREATED = 'something_created'; | ||
const SOMETHING_REMOVED = 'something_removed'; | ||
const SOMETHING_UPDATED = "something_updated"; | ||
const SOMETHING_CREATED = "something_created"; | ||
const SOMETHING_REMOVED = "something_removed"; | ||
@@ -132,7 +156,12 @@ export const resolvers = { | ||
somethingChanged: { | ||
subscribe: () => pubsub.asyncIterator([ SOMETHING_UPDATED, SOMETHING_CREATED, SOMETHING_REMOVED ]), | ||
subscribe: () => | ||
pubsub.asyncIterableIterator([ | ||
SOMETHING_UPDATED, | ||
SOMETHING_CREATED, | ||
SOMETHING_REMOVED, | ||
]), | ||
}, | ||
}, | ||
} | ||
```` | ||
}; | ||
``` | ||
@@ -144,3 +173,3 @@ ### Payload Manipulation | ||
```js | ||
const SOMETHING_UPDATED = 'something_updated'; | ||
const SOMETHING_UPDATED = "something_updated"; | ||
@@ -154,8 +183,10 @@ export const resolvers = { | ||
}, | ||
subscribe: () => pubsub.asyncIterator(SOMETHING_UPDATED), | ||
subscribe: () => pubsub.asyncIterableIterator(SOMETHING_UPDATED), | ||
}, | ||
}, | ||
} | ||
```` | ||
}; | ||
``` | ||
Note that `resolve` methods execute _after_ `subscribe`, so if the code in `subscribe` depends on a manipulated payload field, you will need to factor out the manipulation and call it from both `subscribe` and `resolve`. | ||
### Usage with callback listeners | ||
@@ -165,11 +196,11 @@ | ||
```JS | ||
```js | ||
const listenToNewMessages = (callback) => { | ||
return db.table('messages').listen(newMessage => callback(newMessage)); | ||
} | ||
return db.table("messages").listen((newMessage) => callback(newMessage)); | ||
}; | ||
// Kick off the listener | ||
listenToNewMessages(message => { | ||
listenToNewMessages((message) => { | ||
console.log(message); | ||
}) | ||
}); | ||
``` | ||
@@ -182,3 +213,3 @@ | ||
```js | ||
import asyncify from 'callback-to-async-iterator'; | ||
import asyncify from "callback-to-async-iterator"; | ||
@@ -191,19 +222,24 @@ export const resolvers = { | ||
}, | ||
} | ||
```` | ||
}; | ||
``` | ||
### Custom `AsyncIterator` Wrappers | ||
The value you should return from your `subscribe` resolver must be an `AsyncIterator`. | ||
The value you should return from your `subscribe` resolver must be an `AsyncIterable`. | ||
You can use this value and wrap it with another `AsyncIterator` to implement custom logic over your subscriptions. | ||
You can wrap an `AsyncIterator` with custom logic for your subscriptions. For compatibility with APIs that require `AsyncIterator` or `AsyncIterable`, your wrapper can return an `AsyncIterableIterator` to comply with both. | ||
For example, the following implementation manipulate the payload by adding some static fields: | ||
For example, the following implementation manipulates the payload by adding some static fields: | ||
```typescript | ||
import { $$asyncIterator } from 'iterall'; | ||
export const withStaticFields = (asyncIterator: AsyncIterator<any>, staticFields: Object): Function => { | ||
return (rootValue: any, args: any, context: any, info: any): AsyncIterator<any> => { | ||
export const withStaticFields = ( | ||
asyncIterator: AsyncIterator<any>, | ||
staticFields: Object | ||
): Function => { | ||
return ( | ||
rootValue: any, | ||
args: any, | ||
context: any, | ||
info: any | ||
): AsyncIterableIterator<any> => { | ||
return { | ||
@@ -227,3 +263,3 @@ next() { | ||
}, | ||
[$$asyncIterator]() { | ||
[Symbol.asyncIterator]() { | ||
return this; | ||
@@ -238,19 +274,20 @@ }, | ||
For more information about `AsyncIterator`: | ||
- [TC39 Proposal](https://github.com/tc39/proposal-async-iteration) | ||
- [iterall](https://github.com/leebyron/iterall) | ||
- [IxJS](https://github.com/ReactiveX/IxJS) | ||
### PubSub Implementations | ||
It can be easily replaced with some other implementations of [PubSubEngine abstract class](https://github.com/apollographql/graphql-subscriptions/blob/master/src/pubsub-engine.ts). Here are a few of them: | ||
- Use Redis with https://github.com/davidyaha/graphql-redis-subscriptions | ||
- Use Google PubSub with https://github.com/axelspringer/graphql-google-pubsub | ||
- Use MQTT enabled broker with https://github.com/davidyaha/graphql-mqtt-subscriptions | ||
- Use MQTT enabled broker with https://github.com/aerogear/graphql-mqtt-subscriptions | ||
- Use RabbitMQ with https://github.com/cdmbase/graphql-rabbitmq-subscriptions | ||
- Use AMQP (RabbitMQ) with https://github.com/Surnet/graphql-amqp-subscriptions | ||
- Use Kafka with https://github.com/ancashoria/graphql-kafka-subscriptions | ||
- Use Kafka (using [Kafkajs](https://www.npmjs.com/package/kafkajs)) with https://github.com/tomasAlabes/graphql-kafkajs-subscriptions | ||
- Use Postgres with https://github.com/GraphQLCollege/graphql-postgres-subscriptions | ||
- Use NATS with https://github.com/moonwalker/graphql-nats-subscriptions | ||
- Use Mongoose (MongoDB) with https://github.com/Nickolasmv/graphql-mongoose-subscriptions | ||
- Use multiple backends with https://github.com/jcoreio/graphql-multiplex-subscriptions | ||
- Use Ably for multi-protocol support with https://github.com/ably-labs/graphql-ably-pubsub | ||
- Use Google Firestore with https://github.com/m19c/graphql-firestore-subscriptions | ||
- Use Amazon's Simple Notification Service (SNS) and Simple Queue Service (SQS) with https://github.com/sagahead-io/graphql-snssqs-subscriptions | ||
- [Add your implementation...](https://github.com/apollographql/graphql-subscriptions/pull/new/master) | ||
@@ -257,0 +294,0 @@ |
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
Major refactor
Supply chain riskPackage has recently undergone a major refactor. It may be unstable or indicate significant internal changes. Use caution when updating to versions that include significant changes.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
61019
1
27
380
284
1
- Removediterall@^1.3.0
- Removediterall@1.3.0(transitive)