@graphql-yoga/subscription 2.0.0 → 2.1.0-canary-80e0902.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.
- package/cjs/createPubSub.js +67 -0
- package/cjs/createPubSub.spec.js +90 -0
- package/cjs/index.js +14 -0
- package/cjs/operator/filter.js +22 -0
- package/cjs/operator/filter.spec.js +25 -0
- package/cjs/operator/map.js +21 -0
- package/cjs/operator/map.spec.js +25 -0
- package/cjs/package.json +1 -0
- package/cjs/typed-event-target.js +4 -0
- package/cjs/utils/pipe.js +33 -0
- package/{index.mjs → esm/createPubSub.js} +2 -67
- package/esm/createPubSub.spec.js +88 -0
- package/esm/index.js +6 -0
- package/esm/operator/filter.js +18 -0
- package/esm/operator/filter.spec.js +23 -0
- package/esm/operator/map.js +17 -0
- package/esm/operator/map.spec.js +23 -0
- package/esm/typed-event-target.js +3 -0
- package/esm/utils/pipe.js +29 -0
- package/package.json +31 -10
- package/{createPubSub.d.ts → typings/createPubSub.d.ts} +1 -1
- package/{createPubSub.spec.d.ts → typings/createPubSub.spec.d.ts} +0 -0
- package/typings/index.d.ts +6 -0
- package/{operator → typings/operator}/filter.d.ts +0 -0
- package/{operator → typings/operator}/filter.spec.d.ts +0 -0
- package/{operator → typings/operator}/map.d.ts +0 -0
- package/{operator → typings/operator}/map.spec.d.ts +0 -0
- package/{typed-event-target.d.ts → typings/typed-event-target.d.ts} +0 -0
- package/{utils → typings/utils}/pipe.d.ts +0 -0
- package/index.d.ts +0 -6
- package/index.js +0 -140
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.createPubSub = void 0;
|
|
4
|
+
const repeater_1 = require("@repeaterjs/repeater");
|
|
5
|
+
const resolveGlobalConfig = (api = globalThis) => {
|
|
6
|
+
if (!api.Event || !api.EventTarget) {
|
|
7
|
+
throw new Error(`
|
|
8
|
+
[@graphql-yoga/subscription] 'createPubSub' uses the Event and EventTarget APIs.
|
|
9
|
+
|
|
10
|
+
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.
|
|
11
|
+
You can provide polyfills to the 'createPubSub' function:
|
|
12
|
+
|
|
13
|
+
\`\`\`
|
|
14
|
+
// yarn install --exact event-target-polyfill@0.0.3
|
|
15
|
+
import 'event-target-polyfill'
|
|
16
|
+
|
|
17
|
+
const pubSub = createPubSub()
|
|
18
|
+
\`\`\`
|
|
19
|
+
|
|
20
|
+
Alternatively, you can provide your own custom implementation.
|
|
21
|
+
|
|
22
|
+
\`\`\`
|
|
23
|
+
const pubSub = createPubSub({
|
|
24
|
+
event: {
|
|
25
|
+
Event,
|
|
26
|
+
EventTarget,
|
|
27
|
+
}
|
|
28
|
+
})
|
|
29
|
+
\`\`\`
|
|
30
|
+
`);
|
|
31
|
+
}
|
|
32
|
+
return globalThis;
|
|
33
|
+
};
|
|
34
|
+
/**
|
|
35
|
+
* Utility for publishing and subscribing to events.
|
|
36
|
+
*/
|
|
37
|
+
const createPubSub = (config) => {
|
|
38
|
+
var _a;
|
|
39
|
+
const { Event, EventTarget } = resolveGlobalConfig(config === null || config === void 0 ? void 0 : config.event);
|
|
40
|
+
const target = (_a = config === null || config === void 0 ? void 0 : config.eventTarget) !== null && _a !== void 0 ? _a : new EventTarget();
|
|
41
|
+
return {
|
|
42
|
+
publish(routingKey, ...args) {
|
|
43
|
+
var _a;
|
|
44
|
+
const payload = (_a = args[1]) !== null && _a !== void 0 ? _a : args[0];
|
|
45
|
+
const topic = args[1] === undefined
|
|
46
|
+
? routingKey
|
|
47
|
+
: `${routingKey}:${args[0]}`;
|
|
48
|
+
const event = new Event(topic);
|
|
49
|
+
event.data = payload;
|
|
50
|
+
target.dispatchEvent(event);
|
|
51
|
+
},
|
|
52
|
+
subscribe(...[routingKey, id]) {
|
|
53
|
+
const topic = id === undefined ? routingKey : `${routingKey}:${id}`;
|
|
54
|
+
return new repeater_1.Repeater(function subscriptionRepeater(next, stop) {
|
|
55
|
+
stop.then(function subscriptionRepeaterStopHandler() {
|
|
56
|
+
target.removeEventListener(topic, pubsubEventListener);
|
|
57
|
+
});
|
|
58
|
+
target.addEventListener(topic, pubsubEventListener);
|
|
59
|
+
function pubsubEventListener(event) {
|
|
60
|
+
next(event.data);
|
|
61
|
+
}
|
|
62
|
+
});
|
|
63
|
+
},
|
|
64
|
+
};
|
|
65
|
+
};
|
|
66
|
+
exports.createPubSub = createPubSub;
|
|
67
|
+
//# sourceMappingURL=createPubSub.js.map
|
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
const createPubSub_js_1 = require("./createPubSub.js");
|
|
4
|
+
async function collectAsyncIterableValues(asyncIterable) {
|
|
5
|
+
const values = [];
|
|
6
|
+
for await (const value of asyncIterable) {
|
|
7
|
+
values.push(value);
|
|
8
|
+
}
|
|
9
|
+
return values;
|
|
10
|
+
}
|
|
11
|
+
if (!globalThis.EventTarget || !globalThis.Event) {
|
|
12
|
+
require('event-target-polyfill');
|
|
13
|
+
}
|
|
14
|
+
describe('createPubSub', () => {
|
|
15
|
+
it('create', () => {
|
|
16
|
+
(0, createPubSub_js_1.createPubSub)();
|
|
17
|
+
});
|
|
18
|
+
it('subscribe to topic', async () => {
|
|
19
|
+
const pubSub = (0, createPubSub_js_1.createPubSub)();
|
|
20
|
+
const sub = pubSub.subscribe('a');
|
|
21
|
+
const allValues = collectAsyncIterableValues(sub);
|
|
22
|
+
pubSub.publish('a', 1);
|
|
23
|
+
pubSub.publish('a', 2);
|
|
24
|
+
pubSub.publish('a', 3);
|
|
25
|
+
setImmediate(() => {
|
|
26
|
+
sub.return();
|
|
27
|
+
});
|
|
28
|
+
const result = await allValues;
|
|
29
|
+
expect(result).toEqual([1, 2, 3]);
|
|
30
|
+
});
|
|
31
|
+
it('subscribe to multiple topics', async () => {
|
|
32
|
+
const pubSub = (0, createPubSub_js_1.createPubSub)();
|
|
33
|
+
const sub1 = pubSub.subscribe('a');
|
|
34
|
+
const sub2 = pubSub.subscribe('b');
|
|
35
|
+
const allValues1 = collectAsyncIterableValues(sub1);
|
|
36
|
+
const allValues2 = collectAsyncIterableValues(sub2);
|
|
37
|
+
pubSub.publish('a', 1);
|
|
38
|
+
pubSub.publish('b', '1');
|
|
39
|
+
pubSub.publish('a', 2);
|
|
40
|
+
pubSub.publish('b', '2');
|
|
41
|
+
pubSub.publish('a', 3);
|
|
42
|
+
pubSub.publish('b', '3');
|
|
43
|
+
setImmediate(() => {
|
|
44
|
+
sub1.return();
|
|
45
|
+
sub2.return();
|
|
46
|
+
});
|
|
47
|
+
const result1 = await allValues1;
|
|
48
|
+
const result2 = await allValues2;
|
|
49
|
+
expect(result1).toEqual([1, 2, 3]);
|
|
50
|
+
expect(result2).toEqual(['1', '2', '3']);
|
|
51
|
+
});
|
|
52
|
+
it('subscribe to fine-grained topic', async () => {
|
|
53
|
+
const pubSub = (0, createPubSub_js_1.createPubSub)();
|
|
54
|
+
const id1 = '1';
|
|
55
|
+
const sub1 = pubSub.subscribe('a', id1);
|
|
56
|
+
const allValues1 = collectAsyncIterableValues(sub1);
|
|
57
|
+
pubSub.publish('a', id1, 1);
|
|
58
|
+
pubSub.publish('a', id1, 2);
|
|
59
|
+
pubSub.publish('a', id1, 3);
|
|
60
|
+
setImmediate(() => {
|
|
61
|
+
sub1.return();
|
|
62
|
+
});
|
|
63
|
+
const result1 = await allValues1;
|
|
64
|
+
expect(result1).toEqual([1, 2, 3]);
|
|
65
|
+
});
|
|
66
|
+
it('subscribe to multiple fine-grained topics', async () => {
|
|
67
|
+
const pubSub = (0, createPubSub_js_1.createPubSub)();
|
|
68
|
+
const id1 = '1';
|
|
69
|
+
const id2 = '1';
|
|
70
|
+
const sub1 = pubSub.subscribe('a', id1);
|
|
71
|
+
const sub2 = pubSub.subscribe('b', id2);
|
|
72
|
+
const allValues1 = collectAsyncIterableValues(sub1);
|
|
73
|
+
const allValues2 = collectAsyncIterableValues(sub2);
|
|
74
|
+
pubSub.publish('a', id1, 1);
|
|
75
|
+
pubSub.publish('b', id1, '1');
|
|
76
|
+
pubSub.publish('a', id1, 2);
|
|
77
|
+
pubSub.publish('b', id1, '2');
|
|
78
|
+
pubSub.publish('a', id1, 3);
|
|
79
|
+
pubSub.publish('b', id1, '3');
|
|
80
|
+
setImmediate(() => {
|
|
81
|
+
sub1.return();
|
|
82
|
+
sub2.return();
|
|
83
|
+
});
|
|
84
|
+
const result1 = await allValues1;
|
|
85
|
+
const result2 = await allValues2;
|
|
86
|
+
expect(result1).toEqual([1, 2, 3]);
|
|
87
|
+
expect(result2).toEqual(['1', '2', '3']);
|
|
88
|
+
});
|
|
89
|
+
});
|
|
90
|
+
//# sourceMappingURL=createPubSub.spec.js.map
|
package/cjs/index.js
ADDED
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.pipe = exports.filter = exports.map = exports.createPubSub = exports.Repeater = void 0;
|
|
4
|
+
var repeater_1 = require("@repeaterjs/repeater");
|
|
5
|
+
Object.defineProperty(exports, "Repeater", { enumerable: true, get: function () { return repeater_1.Repeater; } });
|
|
6
|
+
var createPubSub_js_1 = require("./createPubSub.js");
|
|
7
|
+
Object.defineProperty(exports, "createPubSub", { enumerable: true, get: function () { return createPubSub_js_1.createPubSub; } });
|
|
8
|
+
var map_js_1 = require("./operator/map.js");
|
|
9
|
+
Object.defineProperty(exports, "map", { enumerable: true, get: function () { return map_js_1.map; } });
|
|
10
|
+
var filter_js_1 = require("./operator/filter.js");
|
|
11
|
+
Object.defineProperty(exports, "filter", { enumerable: true, get: function () { return filter_js_1.filter; } });
|
|
12
|
+
var pipe_js_1 = require("./utils/pipe.js");
|
|
13
|
+
Object.defineProperty(exports, "pipe", { enumerable: true, get: function () { return pipe_js_1.pipe; } });
|
|
14
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.filter = void 0;
|
|
4
|
+
const repeater_1 = require("@repeaterjs/repeater");
|
|
5
|
+
function filter(filter) {
|
|
6
|
+
return (source) => new repeater_1.Repeater(async (push, stop) => {
|
|
7
|
+
const iterable = source[Symbol.asyncIterator]();
|
|
8
|
+
stop.then(() => {
|
|
9
|
+
var _a;
|
|
10
|
+
(_a = iterable.return) === null || _a === void 0 ? void 0 : _a.call(iterable);
|
|
11
|
+
});
|
|
12
|
+
let latest;
|
|
13
|
+
while ((latest = await iterable.next()).done === false) {
|
|
14
|
+
if (filter(latest.value)) {
|
|
15
|
+
await push(latest.value);
|
|
16
|
+
}
|
|
17
|
+
}
|
|
18
|
+
stop();
|
|
19
|
+
});
|
|
20
|
+
}
|
|
21
|
+
exports.filter = filter;
|
|
22
|
+
//# sourceMappingURL=filter.js.map
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
const filter_js_1 = require("./filter.js");
|
|
4
|
+
async function collectAsyncIterableValues(asyncIterable) {
|
|
5
|
+
const values = [];
|
|
6
|
+
for await (const value of asyncIterable) {
|
|
7
|
+
values.push(value);
|
|
8
|
+
}
|
|
9
|
+
return values;
|
|
10
|
+
}
|
|
11
|
+
describe('filter', () => {
|
|
12
|
+
it('filters source stream', async () => {
|
|
13
|
+
async function* source() {
|
|
14
|
+
yield 1;
|
|
15
|
+
yield 2;
|
|
16
|
+
yield 3;
|
|
17
|
+
yield 1;
|
|
18
|
+
}
|
|
19
|
+
const filterFn = (value) => value < 3;
|
|
20
|
+
const stream = (0, filter_js_1.filter)(filterFn)(source());
|
|
21
|
+
const result = await collectAsyncIterableValues(stream);
|
|
22
|
+
expect(result).toEqual([1, 2, 1]);
|
|
23
|
+
});
|
|
24
|
+
});
|
|
25
|
+
//# sourceMappingURL=filter.spec.js.map
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.map = void 0;
|
|
4
|
+
const repeater_1 = require("@repeaterjs/repeater");
|
|
5
|
+
/**
|
|
6
|
+
* Utility for mapping an event stream.
|
|
7
|
+
*/
|
|
8
|
+
const map = (mapper) => (source) => new repeater_1.Repeater(async (push, stop) => {
|
|
9
|
+
const iterable = source[Symbol.asyncIterator]();
|
|
10
|
+
stop.then(() => {
|
|
11
|
+
var _a;
|
|
12
|
+
(_a = iterable.return) === null || _a === void 0 ? void 0 : _a.call(iterable);
|
|
13
|
+
});
|
|
14
|
+
let latest;
|
|
15
|
+
while ((latest = await iterable.next()).done === false) {
|
|
16
|
+
await push(await mapper(latest.value));
|
|
17
|
+
}
|
|
18
|
+
stop();
|
|
19
|
+
});
|
|
20
|
+
exports.map = map;
|
|
21
|
+
//# sourceMappingURL=map.js.map
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
const map_js_1 = require("./map.js");
|
|
4
|
+
async function collectAsyncIterableValues(asyncIterable) {
|
|
5
|
+
const values = [];
|
|
6
|
+
for await (const value of asyncIterable) {
|
|
7
|
+
values.push(value);
|
|
8
|
+
}
|
|
9
|
+
return values;
|
|
10
|
+
}
|
|
11
|
+
describe('map', () => {
|
|
12
|
+
it('maps source stream', async () => {
|
|
13
|
+
async function* source() {
|
|
14
|
+
yield 1;
|
|
15
|
+
yield 2;
|
|
16
|
+
yield 3;
|
|
17
|
+
yield 1;
|
|
18
|
+
}
|
|
19
|
+
const filterFn = (value) => value * 2;
|
|
20
|
+
const stream = (0, map_js_1.map)(filterFn)(source());
|
|
21
|
+
const result = await collectAsyncIterableValues(stream);
|
|
22
|
+
expect(result).toEqual([2, 4, 6, 2]);
|
|
23
|
+
});
|
|
24
|
+
});
|
|
25
|
+
//# sourceMappingURL=map.spec.js.map
|
package/cjs/package.json
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"type":"commonjs"}
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.pipe = void 0;
|
|
4
|
+
function pipe(a, ab, bc, cd, de, ef, fg, gh, hi) {
|
|
5
|
+
switch (arguments.length) {
|
|
6
|
+
case 1:
|
|
7
|
+
return a;
|
|
8
|
+
case 2:
|
|
9
|
+
return ab(a);
|
|
10
|
+
case 3:
|
|
11
|
+
return bc(ab(a));
|
|
12
|
+
case 4:
|
|
13
|
+
return cd(bc(ab(a)));
|
|
14
|
+
case 5:
|
|
15
|
+
return de(cd(bc(ab(a))));
|
|
16
|
+
case 6:
|
|
17
|
+
return ef(de(cd(bc(ab(a)))));
|
|
18
|
+
case 7:
|
|
19
|
+
return fg(ef(de(cd(bc(ab(a))))));
|
|
20
|
+
case 8:
|
|
21
|
+
return gh(fg(ef(de(cd(bc(ab(a)))))));
|
|
22
|
+
case 9:
|
|
23
|
+
return hi(gh(fg(ef(de(cd(bc(ab(a))))))));
|
|
24
|
+
default:
|
|
25
|
+
let ret = arguments[0];
|
|
26
|
+
for (let i = 1; i < arguments.length; i++) {
|
|
27
|
+
ret = arguments[i](ret);
|
|
28
|
+
}
|
|
29
|
+
return ret;
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
exports.pipe = pipe;
|
|
33
|
+
//# sourceMappingURL=pipe.js.map
|
|
@@ -1,6 +1,4 @@
|
|
|
1
1
|
import { Repeater } from '@repeaterjs/repeater';
|
|
2
|
-
export { Repeater } from '@repeaterjs/repeater';
|
|
3
|
-
|
|
4
2
|
const resolveGlobalConfig = (api = globalThis) => {
|
|
5
3
|
if (!api.Event || !api.EventTarget) {
|
|
6
4
|
throw new Error(`
|
|
@@ -33,7 +31,7 @@ const pubSub = createPubSub({
|
|
|
33
31
|
/**
|
|
34
32
|
* Utility for publishing and subscribing to events.
|
|
35
33
|
*/
|
|
36
|
-
const createPubSub = (config) => {
|
|
34
|
+
export const createPubSub = (config) => {
|
|
37
35
|
var _a;
|
|
38
36
|
const { Event, EventTarget } = resolveGlobalConfig(config === null || config === void 0 ? void 0 : config.event);
|
|
39
37
|
const target = (_a = config === null || config === void 0 ? void 0 : config.eventTarget) !== null && _a !== void 0 ? _a : new EventTarget();
|
|
@@ -62,67 +60,4 @@ const createPubSub = (config) => {
|
|
|
62
60
|
},
|
|
63
61
|
};
|
|
64
62
|
};
|
|
65
|
-
|
|
66
|
-
/**
|
|
67
|
-
* Utility for mapping an event stream.
|
|
68
|
-
*/
|
|
69
|
-
const map = (mapper) => (source) => new Repeater(async (push, stop) => {
|
|
70
|
-
const iterable = source[Symbol.asyncIterator]();
|
|
71
|
-
stop.then(() => {
|
|
72
|
-
var _a;
|
|
73
|
-
(_a = iterable.return) === null || _a === void 0 ? void 0 : _a.call(iterable);
|
|
74
|
-
});
|
|
75
|
-
let latest;
|
|
76
|
-
while ((latest = await iterable.next()).done === false) {
|
|
77
|
-
await push(await mapper(latest.value));
|
|
78
|
-
}
|
|
79
|
-
stop();
|
|
80
|
-
});
|
|
81
|
-
|
|
82
|
-
function filter(filter) {
|
|
83
|
-
return (source) => new Repeater(async (push, stop) => {
|
|
84
|
-
const iterable = source[Symbol.asyncIterator]();
|
|
85
|
-
stop.then(() => {
|
|
86
|
-
var _a;
|
|
87
|
-
(_a = iterable.return) === null || _a === void 0 ? void 0 : _a.call(iterable);
|
|
88
|
-
});
|
|
89
|
-
let latest;
|
|
90
|
-
while ((latest = await iterable.next()).done === false) {
|
|
91
|
-
if (filter(latest.value)) {
|
|
92
|
-
await push(latest.value);
|
|
93
|
-
}
|
|
94
|
-
}
|
|
95
|
-
stop();
|
|
96
|
-
});
|
|
97
|
-
}
|
|
98
|
-
|
|
99
|
-
function pipe(a, ab, bc, cd, de, ef, fg, gh, hi) {
|
|
100
|
-
switch (arguments.length) {
|
|
101
|
-
case 1:
|
|
102
|
-
return a;
|
|
103
|
-
case 2:
|
|
104
|
-
return ab(a);
|
|
105
|
-
case 3:
|
|
106
|
-
return bc(ab(a));
|
|
107
|
-
case 4:
|
|
108
|
-
return cd(bc(ab(a)));
|
|
109
|
-
case 5:
|
|
110
|
-
return de(cd(bc(ab(a))));
|
|
111
|
-
case 6:
|
|
112
|
-
return ef(de(cd(bc(ab(a)))));
|
|
113
|
-
case 7:
|
|
114
|
-
return fg(ef(de(cd(bc(ab(a))))));
|
|
115
|
-
case 8:
|
|
116
|
-
return gh(fg(ef(de(cd(bc(ab(a)))))));
|
|
117
|
-
case 9:
|
|
118
|
-
return hi(gh(fg(ef(de(cd(bc(ab(a))))))));
|
|
119
|
-
default:
|
|
120
|
-
let ret = arguments[0];
|
|
121
|
-
for (let i = 1; i < arguments.length; i++) {
|
|
122
|
-
ret = arguments[i](ret);
|
|
123
|
-
}
|
|
124
|
-
return ret;
|
|
125
|
-
}
|
|
126
|
-
}
|
|
127
|
-
|
|
128
|
-
export { createPubSub, filter, map, pipe };
|
|
63
|
+
//# sourceMappingURL=createPubSub.js.map
|
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
import { createPubSub } from './createPubSub.js';
|
|
2
|
+
async function collectAsyncIterableValues(asyncIterable) {
|
|
3
|
+
const values = [];
|
|
4
|
+
for await (const value of asyncIterable) {
|
|
5
|
+
values.push(value);
|
|
6
|
+
}
|
|
7
|
+
return values;
|
|
8
|
+
}
|
|
9
|
+
if (!globalThis.EventTarget || !globalThis.Event) {
|
|
10
|
+
require('event-target-polyfill');
|
|
11
|
+
}
|
|
12
|
+
describe('createPubSub', () => {
|
|
13
|
+
it('create', () => {
|
|
14
|
+
createPubSub();
|
|
15
|
+
});
|
|
16
|
+
it('subscribe to topic', async () => {
|
|
17
|
+
const pubSub = createPubSub();
|
|
18
|
+
const sub = pubSub.subscribe('a');
|
|
19
|
+
const allValues = collectAsyncIterableValues(sub);
|
|
20
|
+
pubSub.publish('a', 1);
|
|
21
|
+
pubSub.publish('a', 2);
|
|
22
|
+
pubSub.publish('a', 3);
|
|
23
|
+
setImmediate(() => {
|
|
24
|
+
sub.return();
|
|
25
|
+
});
|
|
26
|
+
const result = await allValues;
|
|
27
|
+
expect(result).toEqual([1, 2, 3]);
|
|
28
|
+
});
|
|
29
|
+
it('subscribe to multiple topics', async () => {
|
|
30
|
+
const pubSub = createPubSub();
|
|
31
|
+
const sub1 = pubSub.subscribe('a');
|
|
32
|
+
const sub2 = pubSub.subscribe('b');
|
|
33
|
+
const allValues1 = collectAsyncIterableValues(sub1);
|
|
34
|
+
const allValues2 = collectAsyncIterableValues(sub2);
|
|
35
|
+
pubSub.publish('a', 1);
|
|
36
|
+
pubSub.publish('b', '1');
|
|
37
|
+
pubSub.publish('a', 2);
|
|
38
|
+
pubSub.publish('b', '2');
|
|
39
|
+
pubSub.publish('a', 3);
|
|
40
|
+
pubSub.publish('b', '3');
|
|
41
|
+
setImmediate(() => {
|
|
42
|
+
sub1.return();
|
|
43
|
+
sub2.return();
|
|
44
|
+
});
|
|
45
|
+
const result1 = await allValues1;
|
|
46
|
+
const result2 = await allValues2;
|
|
47
|
+
expect(result1).toEqual([1, 2, 3]);
|
|
48
|
+
expect(result2).toEqual(['1', '2', '3']);
|
|
49
|
+
});
|
|
50
|
+
it('subscribe to fine-grained topic', async () => {
|
|
51
|
+
const pubSub = createPubSub();
|
|
52
|
+
const id1 = '1';
|
|
53
|
+
const sub1 = pubSub.subscribe('a', id1);
|
|
54
|
+
const allValues1 = collectAsyncIterableValues(sub1);
|
|
55
|
+
pubSub.publish('a', id1, 1);
|
|
56
|
+
pubSub.publish('a', id1, 2);
|
|
57
|
+
pubSub.publish('a', id1, 3);
|
|
58
|
+
setImmediate(() => {
|
|
59
|
+
sub1.return();
|
|
60
|
+
});
|
|
61
|
+
const result1 = await allValues1;
|
|
62
|
+
expect(result1).toEqual([1, 2, 3]);
|
|
63
|
+
});
|
|
64
|
+
it('subscribe to multiple fine-grained topics', async () => {
|
|
65
|
+
const pubSub = createPubSub();
|
|
66
|
+
const id1 = '1';
|
|
67
|
+
const id2 = '1';
|
|
68
|
+
const sub1 = pubSub.subscribe('a', id1);
|
|
69
|
+
const sub2 = pubSub.subscribe('b', id2);
|
|
70
|
+
const allValues1 = collectAsyncIterableValues(sub1);
|
|
71
|
+
const allValues2 = collectAsyncIterableValues(sub2);
|
|
72
|
+
pubSub.publish('a', id1, 1);
|
|
73
|
+
pubSub.publish('b', id1, '1');
|
|
74
|
+
pubSub.publish('a', id1, 2);
|
|
75
|
+
pubSub.publish('b', id1, '2');
|
|
76
|
+
pubSub.publish('a', id1, 3);
|
|
77
|
+
pubSub.publish('b', id1, '3');
|
|
78
|
+
setImmediate(() => {
|
|
79
|
+
sub1.return();
|
|
80
|
+
sub2.return();
|
|
81
|
+
});
|
|
82
|
+
const result1 = await allValues1;
|
|
83
|
+
const result2 = await allValues2;
|
|
84
|
+
expect(result1).toEqual([1, 2, 3]);
|
|
85
|
+
expect(result2).toEqual(['1', '2', '3']);
|
|
86
|
+
});
|
|
87
|
+
});
|
|
88
|
+
//# sourceMappingURL=createPubSub.spec.js.map
|
package/esm/index.js
ADDED
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
export { Repeater } from '@repeaterjs/repeater';
|
|
2
|
+
export { createPubSub } from './createPubSub.js';
|
|
3
|
+
export { map } from './operator/map.js';
|
|
4
|
+
export { filter } from './operator/filter.js';
|
|
5
|
+
export { pipe } from './utils/pipe.js';
|
|
6
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { Repeater } from '@repeaterjs/repeater';
|
|
2
|
+
export function filter(filter) {
|
|
3
|
+
return (source) => new Repeater(async (push, stop) => {
|
|
4
|
+
const iterable = source[Symbol.asyncIterator]();
|
|
5
|
+
stop.then(() => {
|
|
6
|
+
var _a;
|
|
7
|
+
(_a = iterable.return) === null || _a === void 0 ? void 0 : _a.call(iterable);
|
|
8
|
+
});
|
|
9
|
+
let latest;
|
|
10
|
+
while ((latest = await iterable.next()).done === false) {
|
|
11
|
+
if (filter(latest.value)) {
|
|
12
|
+
await push(latest.value);
|
|
13
|
+
}
|
|
14
|
+
}
|
|
15
|
+
stop();
|
|
16
|
+
});
|
|
17
|
+
}
|
|
18
|
+
//# sourceMappingURL=filter.js.map
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import { filter } from './filter.js';
|
|
2
|
+
async function collectAsyncIterableValues(asyncIterable) {
|
|
3
|
+
const values = [];
|
|
4
|
+
for await (const value of asyncIterable) {
|
|
5
|
+
values.push(value);
|
|
6
|
+
}
|
|
7
|
+
return values;
|
|
8
|
+
}
|
|
9
|
+
describe('filter', () => {
|
|
10
|
+
it('filters source stream', async () => {
|
|
11
|
+
async function* source() {
|
|
12
|
+
yield 1;
|
|
13
|
+
yield 2;
|
|
14
|
+
yield 3;
|
|
15
|
+
yield 1;
|
|
16
|
+
}
|
|
17
|
+
const filterFn = (value) => value < 3;
|
|
18
|
+
const stream = filter(filterFn)(source());
|
|
19
|
+
const result = await collectAsyncIterableValues(stream);
|
|
20
|
+
expect(result).toEqual([1, 2, 1]);
|
|
21
|
+
});
|
|
22
|
+
});
|
|
23
|
+
//# sourceMappingURL=filter.spec.js.map
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import { Repeater } from '@repeaterjs/repeater';
|
|
2
|
+
/**
|
|
3
|
+
* Utility for mapping an event stream.
|
|
4
|
+
*/
|
|
5
|
+
export const map = (mapper) => (source) => new Repeater(async (push, stop) => {
|
|
6
|
+
const iterable = source[Symbol.asyncIterator]();
|
|
7
|
+
stop.then(() => {
|
|
8
|
+
var _a;
|
|
9
|
+
(_a = iterable.return) === null || _a === void 0 ? void 0 : _a.call(iterable);
|
|
10
|
+
});
|
|
11
|
+
let latest;
|
|
12
|
+
while ((latest = await iterable.next()).done === false) {
|
|
13
|
+
await push(await mapper(latest.value));
|
|
14
|
+
}
|
|
15
|
+
stop();
|
|
16
|
+
});
|
|
17
|
+
//# sourceMappingURL=map.js.map
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import { map } from './map.js';
|
|
2
|
+
async function collectAsyncIterableValues(asyncIterable) {
|
|
3
|
+
const values = [];
|
|
4
|
+
for await (const value of asyncIterable) {
|
|
5
|
+
values.push(value);
|
|
6
|
+
}
|
|
7
|
+
return values;
|
|
8
|
+
}
|
|
9
|
+
describe('map', () => {
|
|
10
|
+
it('maps source stream', async () => {
|
|
11
|
+
async function* source() {
|
|
12
|
+
yield 1;
|
|
13
|
+
yield 2;
|
|
14
|
+
yield 3;
|
|
15
|
+
yield 1;
|
|
16
|
+
}
|
|
17
|
+
const filterFn = (value) => value * 2;
|
|
18
|
+
const stream = map(filterFn)(source());
|
|
19
|
+
const result = await collectAsyncIterableValues(stream);
|
|
20
|
+
expect(result).toEqual([2, 4, 6, 2]);
|
|
21
|
+
});
|
|
22
|
+
});
|
|
23
|
+
//# sourceMappingURL=map.spec.js.map
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
export function pipe(a, ab, bc, cd, de, ef, fg, gh, hi) {
|
|
2
|
+
switch (arguments.length) {
|
|
3
|
+
case 1:
|
|
4
|
+
return a;
|
|
5
|
+
case 2:
|
|
6
|
+
return ab(a);
|
|
7
|
+
case 3:
|
|
8
|
+
return bc(ab(a));
|
|
9
|
+
case 4:
|
|
10
|
+
return cd(bc(ab(a)));
|
|
11
|
+
case 5:
|
|
12
|
+
return de(cd(bc(ab(a))));
|
|
13
|
+
case 6:
|
|
14
|
+
return ef(de(cd(bc(ab(a)))));
|
|
15
|
+
case 7:
|
|
16
|
+
return fg(ef(de(cd(bc(ab(a))))));
|
|
17
|
+
case 8:
|
|
18
|
+
return gh(fg(ef(de(cd(bc(ab(a)))))));
|
|
19
|
+
case 9:
|
|
20
|
+
return hi(gh(fg(ef(de(cd(bc(ab(a))))))));
|
|
21
|
+
default:
|
|
22
|
+
let ret = arguments[0];
|
|
23
|
+
for (let i = 1; i < arguments.length; i++) {
|
|
24
|
+
ret = arguments[i](ret);
|
|
25
|
+
}
|
|
26
|
+
return ret;
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
//# sourceMappingURL=pipe.js.map
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@graphql-yoga/subscription",
|
|
3
|
-
"version": "2.0.0",
|
|
3
|
+
"version": "2.1.0-canary-80e0902.0",
|
|
4
4
|
"description": "",
|
|
5
5
|
"dependencies": {
|
|
6
6
|
"@repeaterjs/repeater": "^3.0.4",
|
|
@@ -19,21 +19,42 @@
|
|
|
19
19
|
],
|
|
20
20
|
"author": "Laurin Quast <laurinquast@googlemail.com>",
|
|
21
21
|
"license": "MIT",
|
|
22
|
-
"main": "index.js",
|
|
23
|
-
"module": "index.
|
|
24
|
-
"typings": "index.d.ts",
|
|
22
|
+
"main": "cjs/index.js",
|
|
23
|
+
"module": "esm/index.js",
|
|
24
|
+
"typings": "typings/index.d.ts",
|
|
25
25
|
"typescript": {
|
|
26
|
-
"definition": "index.d.ts"
|
|
26
|
+
"definition": "typings/index.d.ts"
|
|
27
27
|
},
|
|
28
|
+
"type": "module",
|
|
28
29
|
"exports": {
|
|
29
30
|
".": {
|
|
30
|
-
"require":
|
|
31
|
-
|
|
31
|
+
"require": {
|
|
32
|
+
"types": "./typings/index.d.ts",
|
|
33
|
+
"default": "./cjs/index.js"
|
|
34
|
+
},
|
|
35
|
+
"import": {
|
|
36
|
+
"types": "./typings/index.d.ts",
|
|
37
|
+
"default": "./esm/index.js"
|
|
38
|
+
},
|
|
39
|
+
"default": {
|
|
40
|
+
"types": "./typings/index.d.ts",
|
|
41
|
+
"default": "./esm/index.js"
|
|
42
|
+
}
|
|
32
43
|
},
|
|
33
44
|
"./*": {
|
|
34
|
-
"require":
|
|
35
|
-
|
|
45
|
+
"require": {
|
|
46
|
+
"types": "./typings/*.d.ts",
|
|
47
|
+
"default": "./cjs/*.js"
|
|
48
|
+
},
|
|
49
|
+
"import": {
|
|
50
|
+
"types": "./typings/*.d.ts",
|
|
51
|
+
"default": "./esm/*.js"
|
|
52
|
+
},
|
|
53
|
+
"default": {
|
|
54
|
+
"types": "./typings/*.d.ts",
|
|
55
|
+
"default": "./esm/*.js"
|
|
56
|
+
}
|
|
36
57
|
},
|
|
37
58
|
"./package.json": "./package.json"
|
|
38
59
|
}
|
|
39
|
-
}
|
|
60
|
+
}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { Repeater } from '@repeaterjs/repeater';
|
|
2
|
-
import { TypedEventTarget } from './typed-event-target';
|
|
2
|
+
import { TypedEventTarget } from './typed-event-target.js';
|
|
3
3
|
declare type PubSubPublishArgsByKey = {
|
|
4
4
|
[key: string]: [] | [any] | [number | string, any];
|
|
5
5
|
};
|
|
File without changes
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
export { Repeater } from '@repeaterjs/repeater';
|
|
2
|
+
export { createPubSub, PubSub } from './createPubSub.js';
|
|
3
|
+
export type { PubSubEventTarget, PubSubEvent } from './createPubSub.js';
|
|
4
|
+
export { map } from './operator/map.js';
|
|
5
|
+
export { filter } from './operator/filter.js';
|
|
6
|
+
export { pipe } from './utils/pipe.js';
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
package/index.d.ts
DELETED
|
@@ -1,6 +0,0 @@
|
|
|
1
|
-
export { Repeater } from '@repeaterjs/repeater';
|
|
2
|
-
export { createPubSub, PubSub } from './createPubSub';
|
|
3
|
-
export type { PubSubEventTarget, PubSubEvent } from './createPubSub';
|
|
4
|
-
export { map } from './operator/map';
|
|
5
|
-
export { filter } from './operator/filter';
|
|
6
|
-
export { pipe } from './utils/pipe';
|
package/index.js
DELETED
|
@@ -1,140 +0,0 @@
|
|
|
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 --exact event-target-polyfill@0.0.3
|
|
17
|
-
import 'event-target-polyfill'
|
|
18
|
-
|
|
19
|
-
const pubSub = createPubSub()
|
|
20
|
-
\`\`\`
|
|
21
|
-
|
|
22
|
-
Alternatively, you can provide your own custom implementation.
|
|
23
|
-
|
|
24
|
-
\`\`\`
|
|
25
|
-
const pubSub = createPubSub({
|
|
26
|
-
event: {
|
|
27
|
-
Event,
|
|
28
|
-
EventTarget,
|
|
29
|
-
}
|
|
30
|
-
})
|
|
31
|
-
\`\`\`
|
|
32
|
-
`);
|
|
33
|
-
}
|
|
34
|
-
return globalThis;
|
|
35
|
-
};
|
|
36
|
-
/**
|
|
37
|
-
* Utility for publishing and subscribing to events.
|
|
38
|
-
*/
|
|
39
|
-
const createPubSub = (config) => {
|
|
40
|
-
var _a;
|
|
41
|
-
const { Event, EventTarget } = resolveGlobalConfig(config === null || config === void 0 ? void 0 : config.event);
|
|
42
|
-
const target = (_a = config === null || config === void 0 ? void 0 : config.eventTarget) !== null && _a !== void 0 ? _a : new EventTarget();
|
|
43
|
-
return {
|
|
44
|
-
publish(routingKey, ...args) {
|
|
45
|
-
var _a;
|
|
46
|
-
const payload = (_a = args[1]) !== null && _a !== void 0 ? _a : args[0];
|
|
47
|
-
const topic = args[1] === undefined
|
|
48
|
-
? routingKey
|
|
49
|
-
: `${routingKey}:${args[0]}`;
|
|
50
|
-
const event = new Event(topic);
|
|
51
|
-
event.data = payload;
|
|
52
|
-
target.dispatchEvent(event);
|
|
53
|
-
},
|
|
54
|
-
subscribe(...[routingKey, id]) {
|
|
55
|
-
const topic = id === undefined ? routingKey : `${routingKey}:${id}`;
|
|
56
|
-
return new repeater.Repeater(function subscriptionRepeater(next, stop) {
|
|
57
|
-
stop.then(function subscriptionRepeaterStopHandler() {
|
|
58
|
-
target.removeEventListener(topic, pubsubEventListener);
|
|
59
|
-
});
|
|
60
|
-
target.addEventListener(topic, pubsubEventListener);
|
|
61
|
-
function pubsubEventListener(event) {
|
|
62
|
-
next(event.data);
|
|
63
|
-
}
|
|
64
|
-
});
|
|
65
|
-
},
|
|
66
|
-
};
|
|
67
|
-
};
|
|
68
|
-
|
|
69
|
-
/**
|
|
70
|
-
* Utility for mapping an event stream.
|
|
71
|
-
*/
|
|
72
|
-
const map = (mapper) => (source) => new repeater.Repeater(async (push, stop) => {
|
|
73
|
-
const iterable = source[Symbol.asyncIterator]();
|
|
74
|
-
stop.then(() => {
|
|
75
|
-
var _a;
|
|
76
|
-
(_a = iterable.return) === null || _a === void 0 ? void 0 : _a.call(iterable);
|
|
77
|
-
});
|
|
78
|
-
let latest;
|
|
79
|
-
while ((latest = await iterable.next()).done === false) {
|
|
80
|
-
await push(await mapper(latest.value));
|
|
81
|
-
}
|
|
82
|
-
stop();
|
|
83
|
-
});
|
|
84
|
-
|
|
85
|
-
function filter(filter) {
|
|
86
|
-
return (source) => new repeater.Repeater(async (push, stop) => {
|
|
87
|
-
const iterable = source[Symbol.asyncIterator]();
|
|
88
|
-
stop.then(() => {
|
|
89
|
-
var _a;
|
|
90
|
-
(_a = iterable.return) === null || _a === void 0 ? void 0 : _a.call(iterable);
|
|
91
|
-
});
|
|
92
|
-
let latest;
|
|
93
|
-
while ((latest = await iterable.next()).done === false) {
|
|
94
|
-
if (filter(latest.value)) {
|
|
95
|
-
await push(latest.value);
|
|
96
|
-
}
|
|
97
|
-
}
|
|
98
|
-
stop();
|
|
99
|
-
});
|
|
100
|
-
}
|
|
101
|
-
|
|
102
|
-
function pipe(a, ab, bc, cd, de, ef, fg, gh, hi) {
|
|
103
|
-
switch (arguments.length) {
|
|
104
|
-
case 1:
|
|
105
|
-
return a;
|
|
106
|
-
case 2:
|
|
107
|
-
return ab(a);
|
|
108
|
-
case 3:
|
|
109
|
-
return bc(ab(a));
|
|
110
|
-
case 4:
|
|
111
|
-
return cd(bc(ab(a)));
|
|
112
|
-
case 5:
|
|
113
|
-
return de(cd(bc(ab(a))));
|
|
114
|
-
case 6:
|
|
115
|
-
return ef(de(cd(bc(ab(a)))));
|
|
116
|
-
case 7:
|
|
117
|
-
return fg(ef(de(cd(bc(ab(a))))));
|
|
118
|
-
case 8:
|
|
119
|
-
return gh(fg(ef(de(cd(bc(ab(a)))))));
|
|
120
|
-
case 9:
|
|
121
|
-
return hi(gh(fg(ef(de(cd(bc(ab(a))))))));
|
|
122
|
-
default:
|
|
123
|
-
let ret = arguments[0];
|
|
124
|
-
for (let i = 1; i < arguments.length; i++) {
|
|
125
|
-
ret = arguments[i](ret);
|
|
126
|
-
}
|
|
127
|
-
return ret;
|
|
128
|
-
}
|
|
129
|
-
}
|
|
130
|
-
|
|
131
|
-
Object.defineProperty(exports, 'Repeater', {
|
|
132
|
-
enumerable: true,
|
|
133
|
-
get: function () {
|
|
134
|
-
return repeater.Repeater;
|
|
135
|
-
}
|
|
136
|
-
});
|
|
137
|
-
exports.createPubSub = createPubSub;
|
|
138
|
-
exports.filter = filter;
|
|
139
|
-
exports.map = map;
|
|
140
|
-
exports.pipe = pipe;
|