@graphql-yoga/subscription 0.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,35 @@
1
+ import { Repeater } from '@repeaterjs/repeater';
2
+ import { TypedEventTarget } from './typed-event-target';
3
+ declare type PubSubPublishArgsByKey = {
4
+ [key: string]: [] | [any] | [number | string, any];
5
+ };
6
+ declare type EventAPI = {
7
+ Event: typeof Event;
8
+ EventTarget: typeof EventTarget;
9
+ };
10
+ export declare type PubSubEvent<TPubSubPublishArgsByKey extends PubSubPublishArgsByKey, TKey extends Extract<keyof TPubSubPublishArgsByKey, string>> = Event & {
11
+ data?: TPubSubPublishArgsByKey[TKey][1] extends undefined ? TPubSubPublishArgsByKey[TKey][0] : TPubSubPublishArgsByKey[TKey][1];
12
+ };
13
+ export declare type PubSubEventTarget<TPubSubPublishArgsByKey extends PubSubPublishArgsByKey> = TypedEventTarget<PubSubEvent<TPubSubPublishArgsByKey, Extract<keyof TPubSubPublishArgsByKey, string>>>;
14
+ export declare type ChannelPubSubConfig<TPubSubPublishArgsByKey extends PubSubPublishArgsByKey> = {
15
+ /**
16
+ * The event target. If not specified an (in-memory) EventTarget will be created.
17
+ * For multiple server replica or serverless environments a distributed EventTarget is recommended.
18
+ *
19
+ * An event dispatched on the event target MUST have a `data` property.
20
+ */
21
+ eventTarget?: PubSubEventTarget<TPubSubPublishArgsByKey>;
22
+ /**
23
+ * Event and EventTarget implementation.
24
+ * Providing this is mandatory for a Node.js versions below 16.
25
+ */
26
+ event?: EventAPI;
27
+ };
28
+ /**
29
+ * Utility for publishing and subscribing to events.
30
+ */
31
+ export declare const createPubSub: <TPubSubPublishArgsByKey extends PubSubPublishArgsByKey>(config?: ChannelPubSubConfig<TPubSubPublishArgsByKey> | undefined) => {
32
+ publish<TKey extends Extract<keyof TPubSubPublishArgsByKey, string>>(routingKey: TKey, ...args: TPubSubPublishArgsByKey[TKey]): void;
33
+ subscribe<TKey_1 extends Extract<keyof TPubSubPublishArgsByKey, string>>(...[routingKey, id]: TPubSubPublishArgsByKey[TKey_1][1] extends undefined ? [TKey_1] : [TKey_1, TPubSubPublishArgsByKey[TKey_1][0]]): Repeater<TPubSubPublishArgsByKey[TKey_1][1] extends undefined ? TPubSubPublishArgsByKey[TKey_1][0] : TPubSubPublishArgsByKey[TKey_1][1], any, unknown>;
34
+ };
35
+ export {};
package/index.d.ts ADDED
@@ -0,0 +1,4 @@
1
+ export { createPubSub } from './createPubSub';
2
+ export type { PubSubEventTarget, PubSubEvent } from './createPubSub';
3
+ export { map } from './operator/map';
4
+ export { filter } from './operator/filter';
package/index.js ADDED
@@ -0,0 +1,86 @@
1
+ 'use strict';
2
+
3
+ Object.defineProperty(exports, '__esModule', { value: true });
4
+
5
+ const repeater = require('@repeaterjs/repeater');
6
+
7
+ const resolveGlobalConfig = (api = globalThis) => {
8
+ if (!api.Event || !api.EventTarget) {
9
+ throw new Error(`
10
+ [@graphql-yoga/subscription] 'createPubSub' uses the Event and EventTarget APIs.
11
+
12
+ In modern JavaScript environments those are part of the global scope. However, if you are using an older version of Node.js (<= 16.x.x), those APIs must be polyfilled.
13
+ You can provide polyfills to the 'createPubSub' function:
14
+
15
+ \`\`\`
16
+ // yarn install @ungap/event @ungap/event-target
17
+ import Event from '@ungap/event'
18
+ import EventTarget from '@ungap/event-target'
19
+
20
+ const pubSub = createPubSub({
21
+ event: {
22
+ Event,
23
+ EventTarget,
24
+ }
25
+ })
26
+ \`\`\`
27
+ `);
28
+ }
29
+ return globalThis;
30
+ };
31
+ /**
32
+ * Utility for publishing and subscribing to events.
33
+ */
34
+ const createPubSub = (config) => {
35
+ var _a;
36
+ const { Event, EventTarget } = resolveGlobalConfig(config === null || config === void 0 ? void 0 : config.event);
37
+ const target = (_a = config === null || config === void 0 ? void 0 : config.eventTarget) !== null && _a !== void 0 ? _a : new EventTarget();
38
+ return {
39
+ publish(routingKey, ...args) {
40
+ const event = new Event(routingKey);
41
+ event.data = args[0];
42
+ target.dispatchEvent(event);
43
+ },
44
+ subscribe(...[routingKey, id]) {
45
+ const topic = id === undefined ? routingKey : `${routingKey}:${id}`;
46
+ return new repeater.Repeater(function subscriptionRepeater(next, stop) {
47
+ stop.then(function subscriptionRepeaterStopHandler() {
48
+ target.removeEventListener(topic, pubsubEventListener);
49
+ });
50
+ target.addEventListener(topic, pubsubEventListener);
51
+ function pubsubEventListener(event) {
52
+ next(event.data);
53
+ }
54
+ });
55
+ },
56
+ };
57
+ };
58
+
59
+ /**
60
+ * Utility for mapping an event stream.
61
+ */
62
+ const map = (mapper) => (source) => new repeater.Repeater(async (push, stop) => {
63
+ stop.then(() => {
64
+ source.return();
65
+ });
66
+ for await (const value of source) {
67
+ push(await mapper(value));
68
+ }
69
+ });
70
+
71
+ function filter(filter) {
72
+ return (source) => new repeater.Repeater(async (push, stop) => {
73
+ stop.then(() => {
74
+ source.return();
75
+ });
76
+ for await (const value of source) {
77
+ if (filter(value)) {
78
+ push(value);
79
+ }
80
+ }
81
+ });
82
+ }
83
+
84
+ exports.createPubSub = createPubSub;
85
+ exports.filter = filter;
86
+ exports.map = map;
package/index.mjs ADDED
@@ -0,0 +1,80 @@
1
+ import { Repeater } from '@repeaterjs/repeater';
2
+
3
+ const resolveGlobalConfig = (api = globalThis) => {
4
+ if (!api.Event || !api.EventTarget) {
5
+ throw new Error(`
6
+ [@graphql-yoga/subscription] 'createPubSub' uses the Event and EventTarget APIs.
7
+
8
+ In modern JavaScript environments those are part of the global scope. However, if you are using an older version of Node.js (<= 16.x.x), those APIs must be polyfilled.
9
+ You can provide polyfills to the 'createPubSub' function:
10
+
11
+ \`\`\`
12
+ // yarn install @ungap/event @ungap/event-target
13
+ import Event from '@ungap/event'
14
+ import EventTarget from '@ungap/event-target'
15
+
16
+ const pubSub = createPubSub({
17
+ event: {
18
+ Event,
19
+ EventTarget,
20
+ }
21
+ })
22
+ \`\`\`
23
+ `);
24
+ }
25
+ return globalThis;
26
+ };
27
+ /**
28
+ * Utility for publishing and subscribing to events.
29
+ */
30
+ const createPubSub = (config) => {
31
+ var _a;
32
+ const { Event, EventTarget } = resolveGlobalConfig(config === null || config === void 0 ? void 0 : config.event);
33
+ const target = (_a = config === null || config === void 0 ? void 0 : config.eventTarget) !== null && _a !== void 0 ? _a : new EventTarget();
34
+ return {
35
+ publish(routingKey, ...args) {
36
+ const event = new Event(routingKey);
37
+ event.data = args[0];
38
+ target.dispatchEvent(event);
39
+ },
40
+ subscribe(...[routingKey, id]) {
41
+ const topic = id === undefined ? routingKey : `${routingKey}:${id}`;
42
+ return new Repeater(function subscriptionRepeater(next, stop) {
43
+ stop.then(function subscriptionRepeaterStopHandler() {
44
+ target.removeEventListener(topic, pubsubEventListener);
45
+ });
46
+ target.addEventListener(topic, pubsubEventListener);
47
+ function pubsubEventListener(event) {
48
+ next(event.data);
49
+ }
50
+ });
51
+ },
52
+ };
53
+ };
54
+
55
+ /**
56
+ * Utility for mapping an event stream.
57
+ */
58
+ const map = (mapper) => (source) => new Repeater(async (push, stop) => {
59
+ stop.then(() => {
60
+ source.return();
61
+ });
62
+ for await (const value of source) {
63
+ push(await mapper(value));
64
+ }
65
+ });
66
+
67
+ function filter(filter) {
68
+ return (source) => new Repeater(async (push, stop) => {
69
+ stop.then(() => {
70
+ source.return();
71
+ });
72
+ for await (const value of source) {
73
+ if (filter(value)) {
74
+ push(value);
75
+ }
76
+ }
77
+ });
78
+ }
79
+
80
+ export { createPubSub, filter, map };
@@ -0,0 +1,6 @@
1
+ import { Repeater } from '@repeaterjs/repeater';
2
+ /**
3
+ * Utility for filtering an event stream.
4
+ */
5
+ export declare function filter<T, U extends T>(filter: (input: T) => input is U): (source: Repeater<T>) => Repeater<U, void, unknown>;
6
+ export declare function filter<T>(filter: (input: T) => boolean): (source: Repeater<T>) => Repeater<T, void, unknown>;
@@ -0,0 +1,5 @@
1
+ import { Repeater } from '@repeaterjs/repeater';
2
+ /**
3
+ * Utility for mapping an event stream.
4
+ */
5
+ export declare const map: <T, O>(mapper: (input: T) => O | Promise<O>) => (source: Repeater<T, any, unknown>) => Repeater<O, any, unknown>;
package/package.json ADDED
@@ -0,0 +1,37 @@
1
+ {
2
+ "name": "@graphql-yoga/subscription",
3
+ "version": "0.0.0",
4
+ "description": "",
5
+ "dependencies": {
6
+ "@repeaterjs/repeater": "^3.0.4"
7
+ },
8
+ "repository": {
9
+ "type": "git",
10
+ "url": "https://github.com/dotansimha/graphql-yoga.git",
11
+ "directory": "packages/subscription"
12
+ },
13
+ "keywords": [
14
+ "pubsub",
15
+ "graphql",
16
+ "event",
17
+ "subscription"
18
+ ],
19
+ "author": "Laurin Quast <laurinquast@googlemail.com>",
20
+ "license": "MIT",
21
+ "main": "index.js",
22
+ "module": "index.mjs",
23
+ "typings": "index.d.ts",
24
+ "typescript": {
25
+ "definition": "index.d.ts"
26
+ },
27
+ "exports": {
28
+ ".": {
29
+ "require": "./index.js",
30
+ "import": "./index.mjs"
31
+ },
32
+ "./*": {
33
+ "require": "./*.js",
34
+ "import": "./*.mjs"
35
+ }
36
+ }
37
+ }
@@ -0,0 +1,12 @@
1
+ export interface TypedEventListener<TEvent extends Event> extends EventListener {
2
+ (evt: TEvent): void;
3
+ }
4
+ export interface TypedEventListenerObject<TEvent extends Event> extends EventListener {
5
+ handleEvent(object: TEvent): void;
6
+ }
7
+ export declare type TypedEventListenerOrEventListenerObject<TEvent extends Event> = TypedEventListener<TEvent> | TypedEventListenerObject<TEvent> | null;
8
+ export interface TypedEventTarget<TEvent extends Event> extends EventTarget {
9
+ addEventListener(type: string, callback: TypedEventListenerOrEventListenerObject<TEvent>, options?: AddEventListenerOptions | boolean): void;
10
+ dispatchEvent(event: TEvent): boolean;
11
+ removeEventListener(type: string, callback: TypedEventListenerOrEventListenerObject<TEvent>, options?: EventListenerOptions | boolean): void;
12
+ }