graphql-pg-subscriptions 3.0.0 → 3.1.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/README.md +5 -1
- package/dist/cjs/index.d.ts +2 -0
- package/dist/cjs/index.js +6 -0
- package/dist/cjs/index.js.map +1 -0
- package/dist/cjs/pubsub/event-emitter-to-async-iterator.d.ts +14 -0
- package/dist/cjs/pubsub/event-emitter-to-async-iterator.js +67 -0
- package/dist/cjs/pubsub/event-emitter-to-async-iterator.js.map +1 -0
- package/dist/cjs/pubsub/postgres-pubsub.d.ts +20 -0
- package/dist/cjs/pubsub/postgres-pubsub.js +62 -0
- package/dist/cjs/pubsub/postgres-pubsub.js.map +1 -0
- package/dist/esm/index.d.ts +2 -0
- package/dist/esm/index.js +3 -0
- package/dist/esm/index.js.map +1 -0
- package/dist/esm/pubsub/event-emitter-to-async-iterator.d.ts +14 -0
- package/{event-emitter-to-async-iterator.js → dist/esm/pubsub/event-emitter-to-async-iterator.js} +64 -77
- package/dist/esm/pubsub/event-emitter-to-async-iterator.js.map +1 -0
- package/dist/esm/pubsub/postgres-pubsub.d.ts +20 -0
- package/dist/esm/pubsub/postgres-pubsub.js +56 -0
- package/dist/esm/pubsub/postgres-pubsub.js.map +1 -0
- package/package.json +20 -6
- package/index.d.ts +0 -22
- package/index.js +0 -1
- package/postgres-pubsub.js +0 -56
- package/postgres-pubsub.test.js +0 -201
package/README.md
CHANGED
|
@@ -43,8 +43,12 @@ const client = new Client({
|
|
|
43
43
|
password: 'secretpassword',
|
|
44
44
|
port: 3211,
|
|
45
45
|
});
|
|
46
|
+
|
|
46
47
|
client.connect();
|
|
47
|
-
|
|
48
|
+
|
|
49
|
+
const pubsub = new PostgresPubSub({ client, maxListeners: 15 });
|
|
50
|
+
|
|
51
|
+
//You can increase max event listeners if you need, default is 15
|
|
48
52
|
```
|
|
49
53
|
|
|
50
54
|
**Important**: Don't pass clients from `pg`'s `Pool` to `PostgresPubSub`. As [node-postgres creator states in this StackOverflow answer](https://stackoverflow.com/questions/8484404/what-is-the-proper-way-to-use-the-node-js-postgresql-module), the client needs to be around and not shared so pg can properly handle `NOTIFY` messages (which this library uses under the hood)
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.PostgresPubSub = void 0;
|
|
4
|
+
const postgres_pubsub_1 = require("./pubsub/postgres-pubsub");
|
|
5
|
+
Object.defineProperty(exports, "PostgresPubSub", { enumerable: true, get: function () { return postgres_pubsub_1.PostgresPubSub; } });
|
|
6
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":";;;AAAA,8DAA0D;AAEjD,+FAFA,gCAAc,OAEA"}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
/// <reference types="node" />
|
|
2
|
+
import { $$asyncIterator } from "iterall";
|
|
3
|
+
import { EventEmitter } from "events";
|
|
4
|
+
type MessageHandler<T> = (message: T) => any;
|
|
5
|
+
declare function eventEmitterAsyncIterator<T>(eventEmitter: EventEmitter, eventsNames: string | string[], commonMessageHandler?: MessageHandler<T>): {
|
|
6
|
+
next(): Promise<IteratorResult<any, any>>;
|
|
7
|
+
return(): Promise<{
|
|
8
|
+
value: undefined;
|
|
9
|
+
done: boolean;
|
|
10
|
+
}>;
|
|
11
|
+
throw(error: any): Promise<never>;
|
|
12
|
+
[$$asyncIterator](): any;
|
|
13
|
+
};
|
|
14
|
+
export { eventEmitterAsyncIterator };
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.eventEmitterAsyncIterator = void 0;
|
|
4
|
+
const iterall_1 = require("iterall");
|
|
5
|
+
function eventEmitterAsyncIterator(eventEmitter, eventsNames, commonMessageHandler = message => message) {
|
|
6
|
+
const pullQueue = [];
|
|
7
|
+
const pushQueue = [];
|
|
8
|
+
const eventsArray = typeof eventsNames === "string" ? [eventsNames] : eventsNames;
|
|
9
|
+
let listening = true;
|
|
10
|
+
const pushValue = ({ payload: event }) => {
|
|
11
|
+
const value = commonMessageHandler(event);
|
|
12
|
+
if (pullQueue.length !== 0) {
|
|
13
|
+
pullQueue.shift()({ value, done: false });
|
|
14
|
+
}
|
|
15
|
+
else {
|
|
16
|
+
pushQueue.push(value);
|
|
17
|
+
}
|
|
18
|
+
};
|
|
19
|
+
const pullValue = () => {
|
|
20
|
+
return new Promise(resolve => {
|
|
21
|
+
if (pushQueue.length !== 0) {
|
|
22
|
+
resolve({ value: pushQueue.shift(), done: false });
|
|
23
|
+
}
|
|
24
|
+
else {
|
|
25
|
+
pullQueue.push(resolve);
|
|
26
|
+
}
|
|
27
|
+
});
|
|
28
|
+
};
|
|
29
|
+
const emptyQueue = () => {
|
|
30
|
+
if (listening) {
|
|
31
|
+
listening = false;
|
|
32
|
+
removeEventListeners();
|
|
33
|
+
pullQueue.forEach(resolve => resolve({ value: undefined, done: true }));
|
|
34
|
+
pullQueue.length = 0;
|
|
35
|
+
pushQueue.length = 0;
|
|
36
|
+
}
|
|
37
|
+
};
|
|
38
|
+
const addEventListeners = () => {
|
|
39
|
+
for (const eventName of eventsArray) {
|
|
40
|
+
eventEmitter.addListener(eventName, pushValue);
|
|
41
|
+
}
|
|
42
|
+
};
|
|
43
|
+
const removeEventListeners = () => {
|
|
44
|
+
for (const eventName of eventsArray) {
|
|
45
|
+
eventEmitter.removeListener(eventName, pushValue);
|
|
46
|
+
}
|
|
47
|
+
};
|
|
48
|
+
addEventListeners();
|
|
49
|
+
return {
|
|
50
|
+
next() {
|
|
51
|
+
return listening ? pullValue() : this.return();
|
|
52
|
+
},
|
|
53
|
+
return() {
|
|
54
|
+
emptyQueue();
|
|
55
|
+
return Promise.resolve({ value: undefined, done: true });
|
|
56
|
+
},
|
|
57
|
+
throw(error) {
|
|
58
|
+
emptyQueue();
|
|
59
|
+
return Promise.reject(error);
|
|
60
|
+
},
|
|
61
|
+
[iterall_1.$$asyncIterator]() {
|
|
62
|
+
return this;
|
|
63
|
+
}
|
|
64
|
+
};
|
|
65
|
+
}
|
|
66
|
+
exports.eventEmitterAsyncIterator = eventEmitterAsyncIterator;
|
|
67
|
+
//# sourceMappingURL=event-emitter-to-async-iterator.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"event-emitter-to-async-iterator.js","sourceRoot":"","sources":["../../../src/pubsub/event-emitter-to-async-iterator.ts"],"names":[],"mappings":";;;AAAA,qCAA0C;AAK1C,SAAS,yBAAyB,CAC9B,YAA0B,EAC1B,WAA8B,EAC9B,uBAA0C,OAAO,CAAC,EAAE,CAAC,OAAO;IAE5D,MAAM,SAAS,GAAgD,EAAE,CAAC;IAClE,MAAM,SAAS,GAAU,EAAE,CAAC;IAC5B,MAAM,WAAW,GAAG,OAAO,WAAW,KAAK,QAAQ,CAAC,CAAC,CAAC,CAAC,WAAW,CAAC,CAAC,CAAC,CAAC,WAAW,CAAC;IAClF,IAAI,SAAS,GAAG,IAAI,CAAC;IAErB,MAAM,SAAS,GAAG,CAAC,EAAE,OAAO,EAAE,KAAK,EAAkB,EAAE,EAAE;QACrD,MAAM,KAAK,GAAG,oBAAoB,CAAC,KAAK,CAAC,CAAC;QAC1C,IAAI,SAAS,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;YACzB,SAAS,CAAC,KAAK,EAAG,CAAC,EAAE,KAAK,EAAE,IAAI,EAAE,KAAK,EAAE,CAAC,CAAC;QAC/C,CAAC;aAAM,CAAC;YACJ,SAAS,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;QAC1B,CAAC;IACL,CAAC,CAAC;IAEF,MAAM,SAAS,GAAG,GAAG,EAAE;QACnB,OAAO,IAAI,OAAO,CAAsB,OAAO,CAAC,EAAE;YAC9C,IAAI,SAAS,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;gBACzB,OAAO,CAAC,EAAE,KAAK,EAAE,SAAS,CAAC,KAAK,EAAE,EAAE,IAAI,EAAE,KAAK,EAAE,CAAC,CAAC;YACvD,CAAC;iBAAM,CAAC;gBACJ,SAAS,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;YAC5B,CAAC;QACL,CAAC,CAAC,CAAC;IACP,CAAC,CAAC;IAEF,MAAM,UAAU,GAAG,GAAG,EAAE;QACpB,IAAI,SAAS,EAAE,CAAC;YACZ,SAAS,GAAG,KAAK,CAAC;YAClB,oBAAoB,EAAE,CAAC;YACvB,SAAS,CAAC,OAAO,CAAC,OAAO,CAAC,EAAE,CAAC,OAAO,CAAC,EAAE,KAAK,EAAE,SAAS,EAAE,IAAI,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC;YACxE,SAAS,CAAC,MAAM,GAAG,CAAC,CAAC;YACrB,SAAS,CAAC,MAAM,GAAG,CAAC,CAAC;QACzB,CAAC;IACL,CAAC,CAAC;IAEF,MAAM,iBAAiB,GAAG,GAAG,EAAE;QAC3B,KAAK,MAAM,SAAS,IAAI,WAAW,EAAE,CAAC;YAClC,YAAY,CAAC,WAAW,CAAC,SAAS,EAAE,SAAS,CAAC,CAAC;QACnD,CAAC;IACL,CAAC,CAAC;IAEF,MAAM,oBAAoB,GAAG,GAAG,EAAE;QAC9B,KAAK,MAAM,SAAS,IAAI,WAAW,EAAE,CAAC;YAClC,YAAY,CAAC,cAAc,CAAC,SAAS,EAAE,SAAS,CAAC,CAAC;QACtD,CAAC;IACL,CAAC,CAAC;IAEF,iBAAiB,EAAE,CAAC;IAEpB,OAAO;QACH,IAAI;YACA,OAAO,SAAS,CAAC,CAAC,CAAC,SAAS,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,MAAM,EAAE,CAAC;QACnD,CAAC;QACD,MAAM;YACF,UAAU,EAAE,CAAC;YACb,OAAO,OAAO,CAAC,OAAO,CAAC,EAAE,KAAK,EAAE,SAAS,EAAE,IAAI,EAAE,IAAI,EAAE,CAAC,CAAC;QAC7D,CAAC;QACD,KAAK,CAAC,KAAU;YACZ,UAAU,EAAE,CAAC;YACb,OAAO,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;QACjC,CAAC;QACD,CAAC,yBAAe,CAAC;YACb,OAAO,IAAI,CAAC;QAChB,CAAC;KACJ,CAAC;AACN,CAAC;AAGG,8DAAyB"}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import { PubSubEngine } from "graphql-subscriptions";
|
|
2
|
+
import { Client, ClientConfig } from "pg";
|
|
3
|
+
interface PostgresPubSubOptions extends ClientConfig {
|
|
4
|
+
commonMessageHandler?: (message: any) => any;
|
|
5
|
+
client?: Client;
|
|
6
|
+
maxListeners?: number;
|
|
7
|
+
}
|
|
8
|
+
declare class PostgresPubSub extends PubSubEngine {
|
|
9
|
+
private client;
|
|
10
|
+
private ee;
|
|
11
|
+
private subscriptions;
|
|
12
|
+
private subIdCounter;
|
|
13
|
+
private commonMessageHandler;
|
|
14
|
+
constructor(options?: PostgresPubSubOptions);
|
|
15
|
+
publish(triggerName: string, payload: any): Promise<void>;
|
|
16
|
+
subscribe(triggerName: string, onMessage: (message: any) => void): Promise<number>;
|
|
17
|
+
unsubscribe(subId: number): void;
|
|
18
|
+
asyncIterator<T>(triggers: string | string[]): AsyncIterator<T>;
|
|
19
|
+
}
|
|
20
|
+
export { PostgresPubSub, PostgresPubSubOptions };
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __rest = (this && this.__rest) || function (s, e) {
|
|
3
|
+
var t = {};
|
|
4
|
+
for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0)
|
|
5
|
+
t[p] = s[p];
|
|
6
|
+
if (s != null && typeof Object.getOwnPropertySymbols === "function")
|
|
7
|
+
for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) {
|
|
8
|
+
if (e.indexOf(p[i]) < 0 && Object.prototype.propertyIsEnumerable.call(s, p[i]))
|
|
9
|
+
t[p[i]] = s[p[i]];
|
|
10
|
+
}
|
|
11
|
+
return t;
|
|
12
|
+
};
|
|
13
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
14
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
15
|
+
};
|
|
16
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
17
|
+
exports.PostgresPubSub = void 0;
|
|
18
|
+
const graphql_subscriptions_1 = require("graphql-subscriptions");
|
|
19
|
+
//@ts-ignore
|
|
20
|
+
const pg_ipc_1 = __importDefault(require("pg-ipc"));
|
|
21
|
+
const pg_1 = require("pg");
|
|
22
|
+
const event_emitter_to_async_iterator_1 = require("./event-emitter-to-async-iterator");
|
|
23
|
+
const defaultCommonMessageHandler = (message) => message;
|
|
24
|
+
class PostgresPubSub extends graphql_subscriptions_1.PubSubEngine {
|
|
25
|
+
constructor(options = {}) {
|
|
26
|
+
const { commonMessageHandler, client, maxListeners = 15 } = options, pgOptions = __rest(options, ["commonMessageHandler", "client", "maxListeners"]);
|
|
27
|
+
super();
|
|
28
|
+
this.client = client || new pg_1.Client(pgOptions);
|
|
29
|
+
if (!client) {
|
|
30
|
+
this.client.connect();
|
|
31
|
+
}
|
|
32
|
+
this.ee = new pg_ipc_1.default(this.client);
|
|
33
|
+
this.ee.setMaxListeners(maxListeners);
|
|
34
|
+
this.subscriptions = {};
|
|
35
|
+
this.subIdCounter = 0;
|
|
36
|
+
this.commonMessageHandler = commonMessageHandler || defaultCommonMessageHandler;
|
|
37
|
+
}
|
|
38
|
+
publish(triggerName, payload) {
|
|
39
|
+
return this.ee.notify(triggerName, payload);
|
|
40
|
+
}
|
|
41
|
+
subscribe(triggerName, onMessage) {
|
|
42
|
+
const callback = (message) => {
|
|
43
|
+
onMessage(message instanceof Error
|
|
44
|
+
? message
|
|
45
|
+
: this.commonMessageHandler(message.payload));
|
|
46
|
+
};
|
|
47
|
+
this.ee.on(triggerName, callback);
|
|
48
|
+
this.subIdCounter += 1;
|
|
49
|
+
this.subscriptions[this.subIdCounter] = [triggerName, callback];
|
|
50
|
+
return Promise.resolve(this.subIdCounter);
|
|
51
|
+
}
|
|
52
|
+
unsubscribe(subId) {
|
|
53
|
+
const [triggerName, onMessage] = this.subscriptions[subId];
|
|
54
|
+
delete this.subscriptions[subId];
|
|
55
|
+
this.ee.removeListener(triggerName, onMessage);
|
|
56
|
+
}
|
|
57
|
+
asyncIterator(triggers) {
|
|
58
|
+
return (0, event_emitter_to_async_iterator_1.eventEmitterAsyncIterator)(this.ee, triggers, this.commonMessageHandler);
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
exports.PostgresPubSub = PostgresPubSub;
|
|
62
|
+
//# sourceMappingURL=postgres-pubsub.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"postgres-pubsub.js","sourceRoot":"","sources":["../../../src/pubsub/postgres-pubsub.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;AAAA,iEAAqD;AACrD,YAAY;AACZ,oDAA2B;AAC3B,2BAA0C;AAC1C,uFAA8E;AAE9E,MAAM,2BAA2B,GAAG,CAAC,OAAY,EAAE,EAAE,CAAC,OAAO,CAAC;AAQ9D,MAAM,cAAe,SAAQ,oCAAY;IAOrC,YAAY,UAAiC,EAAE;QAC3C,MAAM,EAAE,oBAAoB,EAAE,MAAM,EAAE,YAAY,GAAG,EAAE,KAAmB,OAAO,EAArB,SAAS,UAAK,OAAO,EAA3E,kDAAiE,CAAU,CAAC;QAClF,KAAK,EAAE,CAAC;QACR,IAAI,CAAC,MAAM,GAAG,MAAM,IAAI,IAAI,WAAM,CAAC,SAAS,CAAC,CAAC;QAC9C,IAAI,CAAC,MAAM,EAAE,CAAC;YACV,IAAI,CAAC,MAAM,CAAC,OAAO,EAAE,CAAC;QAC1B,CAAC;QACD,IAAI,CAAC,EAAE,GAAG,IAAI,gBAAK,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;QACjC,IAAI,CAAC,EAAE,CAAC,eAAe,CAAC,YAAY,CAAC,CAAC;QACtC,IAAI,CAAC,aAAa,GAAG,EAAE,CAAC;QACxB,IAAI,CAAC,YAAY,GAAG,CAAC,CAAC;QACtB,IAAI,CAAC,oBAAoB,GAAG,oBAAoB,IAAI,2BAA2B,CAAC;IACpF,CAAC;IAED,OAAO,CAAC,WAAmB,EAAE,OAAY;QACrC,OAAO,IAAI,CAAC,EAAE,CAAC,MAAM,CAAC,WAAW,EAAE,OAAO,CAAC,CAAC;IAChD,CAAC;IAED,SAAS,CAAC,WAAmB,EAAE,SAAiC;QAC5D,MAAM,QAAQ,GAAG,CAAC,OAAY,EAAE,EAAE;YAC9B,SAAS,CACL,OAAO,YAAY,KAAK;gBACpB,CAAC,CAAC,OAAO;gBACT,CAAC,CAAC,IAAI,CAAC,oBAAoB,CAAC,OAAO,CAAC,OAAO,CAAC,CACnD,CAAC;QACN,CAAC,CAAC;QACF,IAAI,CAAC,EAAE,CAAC,EAAE,CAAC,WAAW,EAAE,QAAQ,CAAC,CAAC;QAClC,IAAI,CAAC,YAAY,IAAI,CAAC,CAAC;QACvB,IAAI,CAAC,aAAa,CAAC,IAAI,CAAC,YAAY,CAAC,GAAG,CAAC,WAAW,EAAE,QAAQ,CAAC,CAAC;QAChE,OAAO,OAAO,CAAC,OAAO,CAAC,IAAI,CAAC,YAAY,CAAC,CAAC;IAC9C,CAAC;IAED,WAAW,CAAC,KAAa;QACrB,MAAM,CAAC,WAAW,EAAE,SAAS,CAAC,GAAG,IAAI,CAAC,aAAa,CAAC,KAAK,CAAC,CAAC;QAC3D,OAAO,IAAI,CAAC,aAAa,CAAC,KAAK,CAAC,CAAC;QACjC,IAAI,CAAC,EAAE,CAAC,cAAc,CAAC,WAAW,EAAE,SAAS,CAAC,CAAC;IACnD,CAAC;IAED,aAAa,CAAI,QAA2B;QACxC,OAAO,IAAA,2DAAyB,EAC5B,IAAI,CAAC,EAAE,EACP,QAAQ,EACR,IAAI,CAAC,oBAAoB,CACrB,CAAC;IACb,CAAC;CACJ;AAEQ,wCAAc"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,EAAE,MAAM,0BAA0B,CAAC;AAE1D,OAAO,EAAE,cAAc,EAAE,CAAC"}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
/// <reference types="node" />
|
|
2
|
+
import { $$asyncIterator } from "iterall";
|
|
3
|
+
import { EventEmitter } from "events";
|
|
4
|
+
type MessageHandler<T> = (message: T) => any;
|
|
5
|
+
declare function eventEmitterAsyncIterator<T>(eventEmitter: EventEmitter, eventsNames: string | string[], commonMessageHandler?: MessageHandler<T>): {
|
|
6
|
+
next(): Promise<IteratorResult<any, any>>;
|
|
7
|
+
return(): Promise<{
|
|
8
|
+
value: undefined;
|
|
9
|
+
done: boolean;
|
|
10
|
+
}>;
|
|
11
|
+
throw(error: any): Promise<never>;
|
|
12
|
+
[$$asyncIterator](): any;
|
|
13
|
+
};
|
|
14
|
+
export { eventEmitterAsyncIterator };
|
package/{event-emitter-to-async-iterator.js → dist/esm/pubsub/event-emitter-to-async-iterator.js}
RENAMED
|
@@ -1,77 +1,64 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
const
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
const
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
}
|
|
39
|
-
};
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
emptyQueue();
|
|
66
|
-
|
|
67
|
-
return Promise.reject(error);
|
|
68
|
-
},
|
|
69
|
-
[$$asyncIterator]() {
|
|
70
|
-
return this;
|
|
71
|
-
}
|
|
72
|
-
};
|
|
73
|
-
}
|
|
74
|
-
|
|
75
|
-
module.exports = {
|
|
76
|
-
eventEmitterAsyncIterator
|
|
77
|
-
};
|
|
1
|
+
import { $$asyncIterator } from "iterall";
|
|
2
|
+
function eventEmitterAsyncIterator(eventEmitter, eventsNames, commonMessageHandler = message => message) {
|
|
3
|
+
const pullQueue = [];
|
|
4
|
+
const pushQueue = [];
|
|
5
|
+
const eventsArray = typeof eventsNames === "string" ? [eventsNames] : eventsNames;
|
|
6
|
+
let listening = true;
|
|
7
|
+
const pushValue = ({ payload: event }) => {
|
|
8
|
+
const value = commonMessageHandler(event);
|
|
9
|
+
if (pullQueue.length !== 0) {
|
|
10
|
+
pullQueue.shift()({ value, done: false });
|
|
11
|
+
}
|
|
12
|
+
else {
|
|
13
|
+
pushQueue.push(value);
|
|
14
|
+
}
|
|
15
|
+
};
|
|
16
|
+
const pullValue = () => {
|
|
17
|
+
return new Promise(resolve => {
|
|
18
|
+
if (pushQueue.length !== 0) {
|
|
19
|
+
resolve({ value: pushQueue.shift(), done: false });
|
|
20
|
+
}
|
|
21
|
+
else {
|
|
22
|
+
pullQueue.push(resolve);
|
|
23
|
+
}
|
|
24
|
+
});
|
|
25
|
+
};
|
|
26
|
+
const emptyQueue = () => {
|
|
27
|
+
if (listening) {
|
|
28
|
+
listening = false;
|
|
29
|
+
removeEventListeners();
|
|
30
|
+
pullQueue.forEach(resolve => resolve({ value: undefined, done: true }));
|
|
31
|
+
pullQueue.length = 0;
|
|
32
|
+
pushQueue.length = 0;
|
|
33
|
+
}
|
|
34
|
+
};
|
|
35
|
+
const addEventListeners = () => {
|
|
36
|
+
for (const eventName of eventsArray) {
|
|
37
|
+
eventEmitter.addListener(eventName, pushValue);
|
|
38
|
+
}
|
|
39
|
+
};
|
|
40
|
+
const removeEventListeners = () => {
|
|
41
|
+
for (const eventName of eventsArray) {
|
|
42
|
+
eventEmitter.removeListener(eventName, pushValue);
|
|
43
|
+
}
|
|
44
|
+
};
|
|
45
|
+
addEventListeners();
|
|
46
|
+
return {
|
|
47
|
+
next() {
|
|
48
|
+
return listening ? pullValue() : this.return();
|
|
49
|
+
},
|
|
50
|
+
return() {
|
|
51
|
+
emptyQueue();
|
|
52
|
+
return Promise.resolve({ value: undefined, done: true });
|
|
53
|
+
},
|
|
54
|
+
throw(error) {
|
|
55
|
+
emptyQueue();
|
|
56
|
+
return Promise.reject(error);
|
|
57
|
+
},
|
|
58
|
+
[$$asyncIterator]() {
|
|
59
|
+
return this;
|
|
60
|
+
}
|
|
61
|
+
};
|
|
62
|
+
}
|
|
63
|
+
export { eventEmitterAsyncIterator };
|
|
64
|
+
//# sourceMappingURL=event-emitter-to-async-iterator.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"event-emitter-to-async-iterator.js","sourceRoot":"","sources":["../../../src/pubsub/event-emitter-to-async-iterator.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,eAAe,EAAE,MAAM,SAAS,CAAC;AAK1C,SAAS,yBAAyB,CAC9B,YAA0B,EAC1B,WAA8B,EAC9B,uBAA0C,OAAO,CAAC,EAAE,CAAC,OAAO;IAE5D,MAAM,SAAS,GAAgD,EAAE,CAAC;IAClE,MAAM,SAAS,GAAU,EAAE,CAAC;IAC5B,MAAM,WAAW,GAAG,OAAO,WAAW,KAAK,QAAQ,CAAC,CAAC,CAAC,CAAC,WAAW,CAAC,CAAC,CAAC,CAAC,WAAW,CAAC;IAClF,IAAI,SAAS,GAAG,IAAI,CAAC;IAErB,MAAM,SAAS,GAAG,CAAC,EAAE,OAAO,EAAE,KAAK,EAAkB,EAAE,EAAE;QACrD,MAAM,KAAK,GAAG,oBAAoB,CAAC,KAAK,CAAC,CAAC;QAC1C,IAAI,SAAS,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;YACzB,SAAS,CAAC,KAAK,EAAG,CAAC,EAAE,KAAK,EAAE,IAAI,EAAE,KAAK,EAAE,CAAC,CAAC;QAC/C,CAAC;aAAM,CAAC;YACJ,SAAS,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;QAC1B,CAAC;IACL,CAAC,CAAC;IAEF,MAAM,SAAS,GAAG,GAAG,EAAE;QACnB,OAAO,IAAI,OAAO,CAAsB,OAAO,CAAC,EAAE;YAC9C,IAAI,SAAS,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;gBACzB,OAAO,CAAC,EAAE,KAAK,EAAE,SAAS,CAAC,KAAK,EAAE,EAAE,IAAI,EAAE,KAAK,EAAE,CAAC,CAAC;YACvD,CAAC;iBAAM,CAAC;gBACJ,SAAS,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;YAC5B,CAAC;QACL,CAAC,CAAC,CAAC;IACP,CAAC,CAAC;IAEF,MAAM,UAAU,GAAG,GAAG,EAAE;QACpB,IAAI,SAAS,EAAE,CAAC;YACZ,SAAS,GAAG,KAAK,CAAC;YAClB,oBAAoB,EAAE,CAAC;YACvB,SAAS,CAAC,OAAO,CAAC,OAAO,CAAC,EAAE,CAAC,OAAO,CAAC,EAAE,KAAK,EAAE,SAAS,EAAE,IAAI,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC;YACxE,SAAS,CAAC,MAAM,GAAG,CAAC,CAAC;YACrB,SAAS,CAAC,MAAM,GAAG,CAAC,CAAC;QACzB,CAAC;IACL,CAAC,CAAC;IAEF,MAAM,iBAAiB,GAAG,GAAG,EAAE;QAC3B,KAAK,MAAM,SAAS,IAAI,WAAW,EAAE,CAAC;YAClC,YAAY,CAAC,WAAW,CAAC,SAAS,EAAE,SAAS,CAAC,CAAC;QACnD,CAAC;IACL,CAAC,CAAC;IAEF,MAAM,oBAAoB,GAAG,GAAG,EAAE;QAC9B,KAAK,MAAM,SAAS,IAAI,WAAW,EAAE,CAAC;YAClC,YAAY,CAAC,cAAc,CAAC,SAAS,EAAE,SAAS,CAAC,CAAC;QACtD,CAAC;IACL,CAAC,CAAC;IAEF,iBAAiB,EAAE,CAAC;IAEpB,OAAO;QACH,IAAI;YACA,OAAO,SAAS,CAAC,CAAC,CAAC,SAAS,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,MAAM,EAAE,CAAC;QACnD,CAAC;QACD,MAAM;YACF,UAAU,EAAE,CAAC;YACb,OAAO,OAAO,CAAC,OAAO,CAAC,EAAE,KAAK,EAAE,SAAS,EAAE,IAAI,EAAE,IAAI,EAAE,CAAC,CAAC;QAC7D,CAAC;QACD,KAAK,CAAC,KAAU;YACZ,UAAU,EAAE,CAAC;YACb,OAAO,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;QACjC,CAAC;QACD,CAAC,eAAe,CAAC;YACb,OAAO,IAAI,CAAC;QAChB,CAAC;KACJ,CAAC;AACN,CAAC;AAED,OAAO,EACH,yBAAyB,EAC5B,CAAC"}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import { PubSubEngine } from "graphql-subscriptions";
|
|
2
|
+
import { Client, ClientConfig } from "pg";
|
|
3
|
+
interface PostgresPubSubOptions extends ClientConfig {
|
|
4
|
+
commonMessageHandler?: (message: any) => any;
|
|
5
|
+
client?: Client;
|
|
6
|
+
maxListeners?: number;
|
|
7
|
+
}
|
|
8
|
+
declare class PostgresPubSub extends PubSubEngine {
|
|
9
|
+
private client;
|
|
10
|
+
private ee;
|
|
11
|
+
private subscriptions;
|
|
12
|
+
private subIdCounter;
|
|
13
|
+
private commonMessageHandler;
|
|
14
|
+
constructor(options?: PostgresPubSubOptions);
|
|
15
|
+
publish(triggerName: string, payload: any): Promise<void>;
|
|
16
|
+
subscribe(triggerName: string, onMessage: (message: any) => void): Promise<number>;
|
|
17
|
+
unsubscribe(subId: number): void;
|
|
18
|
+
asyncIterator<T>(triggers: string | string[]): AsyncIterator<T>;
|
|
19
|
+
}
|
|
20
|
+
export { PostgresPubSub, PostgresPubSubOptions };
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
var __rest = (this && this.__rest) || function (s, e) {
|
|
2
|
+
var t = {};
|
|
3
|
+
for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0)
|
|
4
|
+
t[p] = s[p];
|
|
5
|
+
if (s != null && typeof Object.getOwnPropertySymbols === "function")
|
|
6
|
+
for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) {
|
|
7
|
+
if (e.indexOf(p[i]) < 0 && Object.prototype.propertyIsEnumerable.call(s, p[i]))
|
|
8
|
+
t[p[i]] = s[p[i]];
|
|
9
|
+
}
|
|
10
|
+
return t;
|
|
11
|
+
};
|
|
12
|
+
import { PubSubEngine } from "graphql-subscriptions";
|
|
13
|
+
//@ts-ignore
|
|
14
|
+
import pgIPC from "pg-ipc";
|
|
15
|
+
import { Client } from "pg";
|
|
16
|
+
import { eventEmitterAsyncIterator } from "./event-emitter-to-async-iterator";
|
|
17
|
+
const defaultCommonMessageHandler = (message) => message;
|
|
18
|
+
class PostgresPubSub extends PubSubEngine {
|
|
19
|
+
constructor(options = {}) {
|
|
20
|
+
const { commonMessageHandler, client, maxListeners = 15 } = options, pgOptions = __rest(options, ["commonMessageHandler", "client", "maxListeners"]);
|
|
21
|
+
super();
|
|
22
|
+
this.client = client || new Client(pgOptions);
|
|
23
|
+
if (!client) {
|
|
24
|
+
this.client.connect();
|
|
25
|
+
}
|
|
26
|
+
this.ee = new pgIPC(this.client);
|
|
27
|
+
this.ee.setMaxListeners(maxListeners);
|
|
28
|
+
this.subscriptions = {};
|
|
29
|
+
this.subIdCounter = 0;
|
|
30
|
+
this.commonMessageHandler = commonMessageHandler || defaultCommonMessageHandler;
|
|
31
|
+
}
|
|
32
|
+
publish(triggerName, payload) {
|
|
33
|
+
return this.ee.notify(triggerName, payload);
|
|
34
|
+
}
|
|
35
|
+
subscribe(triggerName, onMessage) {
|
|
36
|
+
const callback = (message) => {
|
|
37
|
+
onMessage(message instanceof Error
|
|
38
|
+
? message
|
|
39
|
+
: this.commonMessageHandler(message.payload));
|
|
40
|
+
};
|
|
41
|
+
this.ee.on(triggerName, callback);
|
|
42
|
+
this.subIdCounter += 1;
|
|
43
|
+
this.subscriptions[this.subIdCounter] = [triggerName, callback];
|
|
44
|
+
return Promise.resolve(this.subIdCounter);
|
|
45
|
+
}
|
|
46
|
+
unsubscribe(subId) {
|
|
47
|
+
const [triggerName, onMessage] = this.subscriptions[subId];
|
|
48
|
+
delete this.subscriptions[subId];
|
|
49
|
+
this.ee.removeListener(triggerName, onMessage);
|
|
50
|
+
}
|
|
51
|
+
asyncIterator(triggers) {
|
|
52
|
+
return eventEmitterAsyncIterator(this.ee, triggers, this.commonMessageHandler);
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
export { PostgresPubSub };
|
|
56
|
+
//# sourceMappingURL=postgres-pubsub.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"postgres-pubsub.js","sourceRoot":"","sources":["../../../src/pubsub/postgres-pubsub.ts"],"names":[],"mappings":";;;;;;;;;;;AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,uBAAuB,CAAC;AACrD,YAAY;AACZ,OAAO,KAAK,MAAM,QAAQ,CAAC;AAC3B,OAAO,EAAE,MAAM,EAAgB,MAAM,IAAI,CAAC;AAC1C,OAAO,EAAE,yBAAyB,EAAE,MAAM,mCAAmC,CAAC;AAE9E,MAAM,2BAA2B,GAAG,CAAC,OAAY,EAAE,EAAE,CAAC,OAAO,CAAC;AAQ9D,MAAM,cAAe,SAAQ,YAAY;IAOrC,YAAY,UAAiC,EAAE;QAC3C,MAAM,EAAE,oBAAoB,EAAE,MAAM,EAAE,YAAY,GAAG,EAAE,KAAmB,OAAO,EAArB,SAAS,UAAK,OAAO,EAA3E,kDAAiE,CAAU,CAAC;QAClF,KAAK,EAAE,CAAC;QACR,IAAI,CAAC,MAAM,GAAG,MAAM,IAAI,IAAI,MAAM,CAAC,SAAS,CAAC,CAAC;QAC9C,IAAI,CAAC,MAAM,EAAE,CAAC;YACV,IAAI,CAAC,MAAM,CAAC,OAAO,EAAE,CAAC;QAC1B,CAAC;QACD,IAAI,CAAC,EAAE,GAAG,IAAI,KAAK,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;QACjC,IAAI,CAAC,EAAE,CAAC,eAAe,CAAC,YAAY,CAAC,CAAC;QACtC,IAAI,CAAC,aAAa,GAAG,EAAE,CAAC;QACxB,IAAI,CAAC,YAAY,GAAG,CAAC,CAAC;QACtB,IAAI,CAAC,oBAAoB,GAAG,oBAAoB,IAAI,2BAA2B,CAAC;IACpF,CAAC;IAED,OAAO,CAAC,WAAmB,EAAE,OAAY;QACrC,OAAO,IAAI,CAAC,EAAE,CAAC,MAAM,CAAC,WAAW,EAAE,OAAO,CAAC,CAAC;IAChD,CAAC;IAED,SAAS,CAAC,WAAmB,EAAE,SAAiC;QAC5D,MAAM,QAAQ,GAAG,CAAC,OAAY,EAAE,EAAE;YAC9B,SAAS,CACL,OAAO,YAAY,KAAK;gBACpB,CAAC,CAAC,OAAO;gBACT,CAAC,CAAC,IAAI,CAAC,oBAAoB,CAAC,OAAO,CAAC,OAAO,CAAC,CACnD,CAAC;QACN,CAAC,CAAC;QACF,IAAI,CAAC,EAAE,CAAC,EAAE,CAAC,WAAW,EAAE,QAAQ,CAAC,CAAC;QAClC,IAAI,CAAC,YAAY,IAAI,CAAC,CAAC;QACvB,IAAI,CAAC,aAAa,CAAC,IAAI,CAAC,YAAY,CAAC,GAAG,CAAC,WAAW,EAAE,QAAQ,CAAC,CAAC;QAChE,OAAO,OAAO,CAAC,OAAO,CAAC,IAAI,CAAC,YAAY,CAAC,CAAC;IAC9C,CAAC;IAED,WAAW,CAAC,KAAa;QACrB,MAAM,CAAC,WAAW,EAAE,SAAS,CAAC,GAAG,IAAI,CAAC,aAAa,CAAC,KAAK,CAAC,CAAC;QAC3D,OAAO,IAAI,CAAC,aAAa,CAAC,KAAK,CAAC,CAAC;QACjC,IAAI,CAAC,EAAE,CAAC,cAAc,CAAC,WAAW,EAAE,SAAS,CAAC,CAAC;IACnD,CAAC;IAED,aAAa,CAAI,QAA2B;QACxC,OAAO,yBAAyB,CAC5B,IAAI,CAAC,EAAE,EACP,QAAQ,EACR,IAAI,CAAC,oBAAoB,CACrB,CAAC;IACb,CAAC;CACJ;AAED,OAAO,EAAE,cAAc,EAAyB,CAAC"}
|
package/package.json
CHANGED
|
@@ -1,8 +1,18 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "graphql-pg-subscriptions",
|
|
3
|
-
"version": "3.
|
|
4
|
-
"description": "",
|
|
5
|
-
"
|
|
3
|
+
"version": "3.1.0",
|
|
4
|
+
"description": "A graphql subscriptions implementation using postgres and apollo's graphql-subscriptions.",
|
|
5
|
+
"homepage": "https://github.com/siamahnaf/graphql-pg-subscriptions",
|
|
6
|
+
"main": "dist/cjs/index.js",
|
|
7
|
+
"module": "dist/esm/index.js",
|
|
8
|
+
"files": [
|
|
9
|
+
"dist"
|
|
10
|
+
],
|
|
11
|
+
"scripts": {
|
|
12
|
+
"build": "rimraf dist && npm run build:esm && npm run build.cjs",
|
|
13
|
+
"build:esm": "tsc",
|
|
14
|
+
"build.cjs": "tsc --module CommonJS --outDir dist/cjs"
|
|
15
|
+
},
|
|
6
16
|
"author": {
|
|
7
17
|
"name": "Siam Ahnaf",
|
|
8
18
|
"email": "mail@siamahnaf.com",
|
|
@@ -13,9 +23,10 @@
|
|
|
13
23
|
"pub/sub for pg",
|
|
14
24
|
"pub/sub for postgreesql",
|
|
15
25
|
"graphql",
|
|
16
|
-
"graphql-subscriptions"
|
|
26
|
+
"graphql-subscriptions",
|
|
27
|
+
"graphql-pg-subscriptions"
|
|
17
28
|
],
|
|
18
|
-
"license": "
|
|
29
|
+
"license": "ISC",
|
|
19
30
|
"repository": {
|
|
20
31
|
"type": "git",
|
|
21
32
|
"directory": "https://github.com/siamahnaf/graphql-pg-subscriptions",
|
|
@@ -30,7 +41,10 @@
|
|
|
30
41
|
"pg-ipc": "^1.0.5"
|
|
31
42
|
},
|
|
32
43
|
"devDependencies": {
|
|
44
|
+
"@types/node": "^20.12.12",
|
|
45
|
+
"@types/pg": "^8.11.6",
|
|
33
46
|
"graphql": "^16.8.1",
|
|
34
|
-
"pg": "^8.11.5"
|
|
47
|
+
"pg": "^8.11.5",
|
|
48
|
+
"typescript": "^5.4.5"
|
|
35
49
|
}
|
|
36
50
|
}
|
package/index.d.ts
DELETED
|
@@ -1,22 +0,0 @@
|
|
|
1
|
-
import { Client, ClientConfig } from "pg";
|
|
2
|
-
import { PubSub } from "graphql-subscriptions";
|
|
3
|
-
|
|
4
|
-
interface PostgresPubSubOptions extends ClientConfig {
|
|
5
|
-
commonMessageHandler?: (...args: any) => any,
|
|
6
|
-
client?: Client,
|
|
7
|
-
maxListeners?: number;
|
|
8
|
-
}
|
|
9
|
-
|
|
10
|
-
export class PostgresPubSub extends PubSub {
|
|
11
|
-
constructor(config?: PostgresPubSubOptions);
|
|
12
|
-
asyncIterator(triggers: string | string[]): PubSubAsyncIterator;
|
|
13
|
-
subscribe(triggerName: string, onMessage: (...args: any) => void | Promise<void>): Promise<number>;
|
|
14
|
-
unsubscribe(subId: number): void;
|
|
15
|
-
}
|
|
16
|
-
|
|
17
|
-
export interface PubSubAsyncIterator {
|
|
18
|
-
next(): any | Promise<any>;
|
|
19
|
-
return(): any;
|
|
20
|
-
throw(error?: any): any;
|
|
21
|
-
[Symbol.asyncIterator](): any;
|
|
22
|
-
}
|
package/index.js
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
module.exports = { PostgresPubSub: require("./postgres-pubsub").PostgresPubSub };
|
package/postgres-pubsub.js
DELETED
|
@@ -1,56 +0,0 @@
|
|
|
1
|
-
const { PubSub } = require("graphql-subscriptions");
|
|
2
|
-
const pgIPC = require("pg-ipc");
|
|
3
|
-
const { Client } = require("pg");
|
|
4
|
-
const {
|
|
5
|
-
eventEmitterAsyncIterator
|
|
6
|
-
} = require("./event-emitter-to-async-iterator");
|
|
7
|
-
|
|
8
|
-
const defaultCommonMessageHandler = message => message;
|
|
9
|
-
|
|
10
|
-
class PostgresPubSub extends PubSub {
|
|
11
|
-
constructor(options = {}) {
|
|
12
|
-
const { commonMessageHandler, client, maxListeners = 15, ...pgOptions } = options;
|
|
13
|
-
super();
|
|
14
|
-
this.client = client || new Client(pgOptions);
|
|
15
|
-
if (!client) {
|
|
16
|
-
this.client.connect();
|
|
17
|
-
}
|
|
18
|
-
this.ee = new pgIPC(this.client);
|
|
19
|
-
this.ee.setMaxListeners(maxListeners);
|
|
20
|
-
this.subscriptions = {};
|
|
21
|
-
this.subIdCounter = 0;
|
|
22
|
-
this.commonMessageHandler =
|
|
23
|
-
commonMessageHandler || defaultCommonMessageHandler;
|
|
24
|
-
}
|
|
25
|
-
publish(triggerName, payload) {
|
|
26
|
-
this.ee.notify(triggerName, payload);
|
|
27
|
-
return true;
|
|
28
|
-
}
|
|
29
|
-
subscribe(triggerName, onMessage) {
|
|
30
|
-
const callback = message => {
|
|
31
|
-
onMessage(
|
|
32
|
-
message instanceof Error
|
|
33
|
-
? message
|
|
34
|
-
: this.commonMessageHandler(message.payload)
|
|
35
|
-
);
|
|
36
|
-
};
|
|
37
|
-
this.ee.on(triggerName, callback);
|
|
38
|
-
this.subIdCounter = this.subIdCounter + 1;
|
|
39
|
-
this.subscriptions[this.subIdCounter] = [triggerName, callback];
|
|
40
|
-
return Promise.resolve(this.subIdCounter);
|
|
41
|
-
}
|
|
42
|
-
unsubscribe(subId) {
|
|
43
|
-
const [triggerName, onMessage] = this.subscriptions[subId];
|
|
44
|
-
delete this.subscriptions[subId];
|
|
45
|
-
this.ee.removeListener(triggerName, onMessage);
|
|
46
|
-
}
|
|
47
|
-
asyncIterator(triggers) {
|
|
48
|
-
return eventEmitterAsyncIterator(
|
|
49
|
-
this.ee,
|
|
50
|
-
triggers,
|
|
51
|
-
this.commonMessageHandler
|
|
52
|
-
);
|
|
53
|
-
}
|
|
54
|
-
}
|
|
55
|
-
|
|
56
|
-
module.exports = { PostgresPubSub };
|
package/postgres-pubsub.test.js
DELETED
|
@@ -1,201 +0,0 @@
|
|
|
1
|
-
// Adapted from https://github.com/apollographql/graphql-subscriptions/blob/master/src/test/tests.ts
|
|
2
|
-
const { isAsyncIterable } = require("iterall");
|
|
3
|
-
const { Client } = require("pg");
|
|
4
|
-
|
|
5
|
-
const { PostgresPubSub } = require("./postgres-pubsub");
|
|
6
|
-
let client;
|
|
7
|
-
|
|
8
|
-
describe("PostgresPubSub", () => {
|
|
9
|
-
beforeEach(async () => {
|
|
10
|
-
client = new Client();
|
|
11
|
-
await client.connect();
|
|
12
|
-
});
|
|
13
|
-
|
|
14
|
-
test("PostgresPubSub can subscribe when instantiated without a client", function (done) {
|
|
15
|
-
const ps = new PostgresPubSub();
|
|
16
|
-
ps.subscribe("a", payload => {
|
|
17
|
-
expect(payload).toEqual("test");
|
|
18
|
-
done();
|
|
19
|
-
}).then(() => {
|
|
20
|
-
const succeed = ps.publish("a", "test");
|
|
21
|
-
expect(succeed).toBe(true);
|
|
22
|
-
});
|
|
23
|
-
});
|
|
24
|
-
|
|
25
|
-
test("PostgresPubSub can subscribe and is called when events happen", function (done) {
|
|
26
|
-
const ps = new PostgresPubSub({ client });
|
|
27
|
-
ps.subscribe("a", payload => {
|
|
28
|
-
expect(payload).toEqual("test");
|
|
29
|
-
done();
|
|
30
|
-
}).then(() => {
|
|
31
|
-
const succeed = ps.publish("a", "test");
|
|
32
|
-
expect(succeed).toBe(true);
|
|
33
|
-
});
|
|
34
|
-
});
|
|
35
|
-
|
|
36
|
-
test("PostgresPubSub can subscribe when instantiated with connection options but without a client", function (done) {
|
|
37
|
-
const ps = new PostgresPubSub({
|
|
38
|
-
connectionString: process.env.DATABASE_URL
|
|
39
|
-
});
|
|
40
|
-
ps.subscribe("a", payload => {
|
|
41
|
-
expect(payload).toEqual("test");
|
|
42
|
-
done();
|
|
43
|
-
}).then(() => {
|
|
44
|
-
const succeed = ps.publish("a", "test");
|
|
45
|
-
expect(succeed).toBe(true);
|
|
46
|
-
});
|
|
47
|
-
});
|
|
48
|
-
|
|
49
|
-
test("should send notification event after calling publish", done => {
|
|
50
|
-
const ps = new PostgresPubSub({ client });
|
|
51
|
-
client.on("notification", ({ payload }) => {
|
|
52
|
-
expect(payload).toEqual("test");
|
|
53
|
-
done();
|
|
54
|
-
});
|
|
55
|
-
ps.subscribe("a", payload => {
|
|
56
|
-
expect(payload).toEqual("test");
|
|
57
|
-
}).then(() => {
|
|
58
|
-
const succeed = ps.publish("a", "test");
|
|
59
|
-
expect(succeed).toBe(true);
|
|
60
|
-
});
|
|
61
|
-
});
|
|
62
|
-
|
|
63
|
-
test("PostgresPubSub can unsubscribe", function (done) {
|
|
64
|
-
const ps = new PostgresPubSub({ client });
|
|
65
|
-
ps.subscribe("a", payload => {
|
|
66
|
-
expect(false).toBe(true); // Should not reach this point
|
|
67
|
-
}).then(subId => {
|
|
68
|
-
ps.unsubscribe(subId);
|
|
69
|
-
const succeed = ps.publish("a", "test");
|
|
70
|
-
expect(succeed).toBe(true); // True because publish success is not
|
|
71
|
-
// indicated by trigger having subscriptions
|
|
72
|
-
done(); // works because pubsub is synchronous
|
|
73
|
-
});
|
|
74
|
-
});
|
|
75
|
-
|
|
76
|
-
test("Should emit error when payload exceeds Postgres 8000 character limit", done => {
|
|
77
|
-
const ps = new PostgresPubSub({ client });
|
|
78
|
-
ps.subscribe("a", () => {
|
|
79
|
-
expect(false).toBe(true); // Should not reach this point
|
|
80
|
-
done();
|
|
81
|
-
});
|
|
82
|
-
ps.subscribe("error", err => {
|
|
83
|
-
expect(err.message).toEqual("payload string too long");
|
|
84
|
-
done();
|
|
85
|
-
}).then(() => {
|
|
86
|
-
const succeed = ps.publish("a", "a".repeat(9000));
|
|
87
|
-
expect(succeed).toBe(true);
|
|
88
|
-
});
|
|
89
|
-
});
|
|
90
|
-
|
|
91
|
-
test("AsyncIterator should expose valid asyncIterator for a specific event", () => {
|
|
92
|
-
const eventName = "test";
|
|
93
|
-
const ps = new PostgresPubSub({ client });
|
|
94
|
-
const iterator = ps.asyncIterator(eventName);
|
|
95
|
-
expect(iterator).not.toBeUndefined();
|
|
96
|
-
expect(isAsyncIterable(iterator)).toBe(true);
|
|
97
|
-
});
|
|
98
|
-
|
|
99
|
-
test("AsyncIterator should trigger event on asyncIterator when published", done => {
|
|
100
|
-
const eventName = "test";
|
|
101
|
-
const ps = new PostgresPubSub({ client });
|
|
102
|
-
const iterator = ps.asyncIterator(eventName);
|
|
103
|
-
|
|
104
|
-
iterator.next().then(result => {
|
|
105
|
-
expect(result).not.toBeUndefined();
|
|
106
|
-
expect(result.value).not.toBeUndefined();
|
|
107
|
-
expect(result.done).not.toBeUndefined();
|
|
108
|
-
done();
|
|
109
|
-
});
|
|
110
|
-
|
|
111
|
-
ps.publish(eventName, { test: true });
|
|
112
|
-
});
|
|
113
|
-
|
|
114
|
-
test("AsyncIterator should not trigger event on asyncIterator when publishing other event", done => {
|
|
115
|
-
const eventName = "test2";
|
|
116
|
-
const ps = new PostgresPubSub({ client });
|
|
117
|
-
const iterator = ps.asyncIterator("test");
|
|
118
|
-
const spy = jest.fn();
|
|
119
|
-
|
|
120
|
-
iterator.next().then(spy);
|
|
121
|
-
ps.publish(eventName, { test: true });
|
|
122
|
-
expect(spy).not.toHaveBeenCalled();
|
|
123
|
-
done();
|
|
124
|
-
});
|
|
125
|
-
|
|
126
|
-
test("AsyncIterator should register to multiple events", done => {
|
|
127
|
-
const eventName = "test2";
|
|
128
|
-
const ps = new PostgresPubSub({ client });
|
|
129
|
-
const iterator = ps.asyncIterator(["test", "test2"]);
|
|
130
|
-
const spy = jest.fn();
|
|
131
|
-
|
|
132
|
-
iterator.next().then(() => {
|
|
133
|
-
spy();
|
|
134
|
-
expect(spy).toHaveBeenCalled();
|
|
135
|
-
done();
|
|
136
|
-
});
|
|
137
|
-
ps.publish(eventName, { test: true });
|
|
138
|
-
});
|
|
139
|
-
|
|
140
|
-
test("AsyncIterator transforms messages using commonMessageHandler", done => {
|
|
141
|
-
const eventName = "test";
|
|
142
|
-
const commonMessageHandler = message => ({ transformed: message });
|
|
143
|
-
const ps = new PostgresPubSub({ client, commonMessageHandler });
|
|
144
|
-
const iterator = ps.asyncIterator(eventName);
|
|
145
|
-
|
|
146
|
-
iterator.next().then(result => {
|
|
147
|
-
expect(result).not.toBeUndefined();
|
|
148
|
-
expect(result.value).toEqual({ transformed: { test: true } });
|
|
149
|
-
expect(result.done).toBe(false);
|
|
150
|
-
done();
|
|
151
|
-
});
|
|
152
|
-
|
|
153
|
-
ps.publish(eventName, { test: true });
|
|
154
|
-
});
|
|
155
|
-
|
|
156
|
-
test("PostgresPubSub transforms messages using commonMessageHandler", function (done) {
|
|
157
|
-
const commonMessageHandler = message => ({ transformed: message });
|
|
158
|
-
const ps = new PostgresPubSub({ client, commonMessageHandler });
|
|
159
|
-
ps.subscribe("transform", payload => {
|
|
160
|
-
expect(payload).toEqual({ transformed: { test: true } });
|
|
161
|
-
done();
|
|
162
|
-
}).then(() => {
|
|
163
|
-
const succeed = ps.publish("transform", { test: true });
|
|
164
|
-
expect(succeed).toBe(true);
|
|
165
|
-
});
|
|
166
|
-
});
|
|
167
|
-
|
|
168
|
-
// This test does not clean up after it ends. It breaks the test that follows after it.
|
|
169
|
-
// It won't break any tests if it's the last. https://imgflip.com/i/2lmlgm
|
|
170
|
-
// TODO: Fix it properly
|
|
171
|
-
test("AsyncIterator should not trigger event on asyncIterator already returned", async done => {
|
|
172
|
-
const eventName = "test";
|
|
173
|
-
const ps = new PostgresPubSub({ client });
|
|
174
|
-
const iterator = ps.asyncIterator(eventName);
|
|
175
|
-
|
|
176
|
-
const delay = ms => new Promise(resolve => setTimeout(resolve, ms));
|
|
177
|
-
|
|
178
|
-
iterator.next().then(result => {
|
|
179
|
-
expect(result).not.toBeUndefined();
|
|
180
|
-
expect(result.value).not.toBeUndefined();
|
|
181
|
-
expect(result.done).toBe(false);
|
|
182
|
-
});
|
|
183
|
-
|
|
184
|
-
ps.publish(eventName, { test: true });
|
|
185
|
-
|
|
186
|
-
await delay(0);
|
|
187
|
-
|
|
188
|
-
iterator.next().then(result => {
|
|
189
|
-
expect(result).not.toBeUndefined();
|
|
190
|
-
expect(result.value).toBeUndefined();
|
|
191
|
-
expect(result.done).toBe(true);
|
|
192
|
-
done();
|
|
193
|
-
});
|
|
194
|
-
|
|
195
|
-
await delay(0);
|
|
196
|
-
|
|
197
|
-
iterator.return();
|
|
198
|
-
|
|
199
|
-
ps.publish(eventName, { test: true });
|
|
200
|
-
});
|
|
201
|
-
});
|