Socket
Socket
Sign inDemoInstall

graphql-ws

Package Overview
Dependencies
Maintainers
1
Versions
103
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

graphql-ws - npm Package Compare versions

Comparing version 2.0.1 to 3.0.0

30

CHANGELOG.md

@@ -0,1 +1,31 @@

# [3.0.0](https://github.com/enisdenjo/graphql-ws/compare/v2.0.1...v3.0.0) (2020-12-09)
### Features
* **client:** Retry with randomised exponential backoff or provide your own strategy ([#84](https://github.com/enisdenjo/graphql-ws/issues/84)) ([d3e7a17](https://github.com/enisdenjo/graphql-ws/commit/d3e7a171603a3ef181c5af533768dcda416a1731))
### BREAKING CHANGES
* **client:** Client `retryTimeout` option has been replaced with the new `retryWait`.
`retryWait` allows you to control the retry timeout strategy by resolving the returned promise when ready. The default implements the randomised exponential backoff like so:
```ts
// this is the default
const retryWait = async function randomisedExponentialBackoff(retries: number) {
let retryDelay = 1000; // start with 1s delay
for (let i = 0; i < retries; i++) {
retryDelay *= 2; // square `retries` times
}
await new Promise((resolve) =>
setTimeout(
// resolve pending promise with added random timeout from 300ms to 3s
resolve,
retryDelay + Math.floor(Math.random() * (3000 - 300) + 300),
),
);
};
```
## [2.0.1](https://github.com/enisdenjo/graphql-ws/compare/v2.0.0...v2.0.1) (2020-12-03)

@@ -2,0 +32,0 @@

7

lib/client.d.ts

@@ -77,7 +77,8 @@ /**

/**
* How long should the client wait until attempting to retry.
* Control the wait time between retries. You may implement your own strategy
* by timing the resolution of the returned promise with the retries count.
*
* @default 3 * 1000 (3 seconds)
* @default Randomised exponential backoff
*/
retryTimeout?: number;
retryWait?: (retries: number) => Promise<void>;
/**

@@ -84,0 +85,0 @@ * Register listeners before initialising the client. This way

@@ -14,4 +14,11 @@ "use strict";

function createClient(options) {
const { url, connectionParams, lazy = true, keepAlive = 0, retryAttempts = 5, retryTimeout = 3 * 1000, // 3 seconds
on, webSocketImpl,
const { url, connectionParams, lazy = true, keepAlive = 0, retryAttempts = 5, retryWait = async function randomisedExponentialBackoff(retries) {
let retryDelay = 1000; // start with 1s delay
for (let i = 0; i < retries; i++) {
retryDelay *= 2;
}
await new Promise((resolve) => setTimeout(resolve, retryDelay +
// add random timeout from 300ms to 3s
Math.floor(Math.random() * (3000 - 300) + 300)));
}, on, webSocketImpl,
/**

@@ -41,8 +48,12 @@ * Generates a v4 UUID to be used as the ID using `Math`

else if (typeof global !== 'undefined') {
// @ts-expect-error: Support more browsers
ws = global.WebSocket || global.MozWebSocket;
ws =
global.WebSocket ||
// @ts-expect-error: Support more browsers
global.MozWebSocket;
}
else if (typeof window !== 'undefined') {
// @ts-expect-error: Support more browsers
ws = window.WebSocket || window.MozWebSocket;
ws =
window.WebSocket ||
// @ts-expect-error: Support more browsers
window.MozWebSocket;
}

@@ -85,5 +96,9 @@ if (!ws) {

locks: 0,
tries: 0,
retrying: false,
retries: 0,
};
// all those waiting for the `retryWait` to resolve
const retryWaiting = [];
async function connect(cancellerRef, callDepth = 0) {
var _a;
// prevents too many recursive calls when reavaluating/re-connecting

@@ -93,2 +108,22 @@ if (callDepth > 10) {

}
// retry wait strategy only on root caller
if (state.retrying && callDepth === 0) {
if (retryWaiting.length) {
// if others are waiting for retry, I'll wait too
await new Promise((resolve) => retryWaiting.push(resolve));
}
else {
retryWaiting.push(() => {
/** fake waiter to lead following connects in the `retryWaiting` queue */
});
// use retry wait strategy
await retryWait(state.retries++);
// complete all waiting and clear the queue
while (retryWaiting.length) {
(_a = retryWaiting.pop()) === null || _a === void 0 ? void 0 : _a();
}
}
}
// if recursive call, wait a bit for socket change
await new Promise((resolve) => setTimeout(resolve, callDepth * 50));
// socket already exists. can be ready or pending, check and behave accordingly

@@ -100,3 +135,2 @@ if (state.socket) {

if (!state.acknowledged) {
await new Promise((resolve) => setTimeout(resolve, 300));
return connect(cancellerRef, callDepth + 1);

@@ -108,3 +142,2 @@ }

// if the socket is in the connecting phase, wait a bit and reavaluate
await new Promise((resolve) => setTimeout(resolve, 300));
return connect(cancellerRef, callDepth + 1);

@@ -116,3 +149,2 @@ }

// if the socket is in the closing phase, wait a bit and connect
await new Promise((resolve) => setTimeout(resolve, 300));
return connect(cancellerRef, callDepth + 1);

@@ -126,3 +158,3 @@ }

const socket = new WebSocketImpl(url, protocol_1.GRAPHQL_TRANSPORT_WS_PROTOCOL);
state = Object.assign(Object.assign({}, state), { acknowledged: false, socket, tries: state.tries + 1 });
state = Object.assign(Object.assign({}, state), { acknowledged: false, socket });
emitter.emit('connecting');

@@ -162,3 +194,3 @@ await new Promise((resolve, reject) => {

clearTimeout(tooLong);
state = Object.assign(Object.assign({}, state), { acknowledged: true, socket, tries: 0 });
state = Object.assign(Object.assign({}, state), { acknowledged: true, socket, retrying: false, retries: 0 });
emitter.emit('connected', socket, message.payload); // connected = socket opened + acknowledged

@@ -267,6 +299,7 @@ return resolve();

// retries are not allowed or we tried to many times, report error
if (!retryAttempts || state.tries > retryAttempts) {
if (!retryAttempts || state.retries >= retryAttempts) {
throw errOrCloseEvent;
}
// looks good, please retry
// looks good, start retrying
state.retrying = true;
return true;

@@ -288,7 +321,4 @@ }

// return if shouldnt try again
if (!shouldRetryConnectOrThrow(errOrCloseEvent)) {
if (!shouldRetryConnectOrThrow(errOrCloseEvent))
return;
}
// if should try again, wait a bit and continue loop
await new Promise((resolve) => setTimeout(resolve, retryTimeout));
}

@@ -378,7 +408,4 @@ }

// return if shouldnt try again
if (!shouldRetryConnectOrThrow(errOrCloseEvent)) {
if (!shouldRetryConnectOrThrow(errOrCloseEvent))
return;
}
// if should try again, wait a bit and continue loop
await new Promise((resolve) => setTimeout(resolve, retryTimeout));
}

@@ -385,0 +412,0 @@ }

{
"name": "graphql-ws",
"version": "2.0.1",
"version": "3.0.0",
"description": "Coherent, zero-dependency, lazy, simple, GraphQL over WebSocket Protocol compliant server and client",

@@ -5,0 +5,0 @@ "keywords": [

@@ -446,2 +446,29 @@ <div align="center">

<details id="retry-strategy">
<summary><a href="#retry-strategy">🔗</a> Client usage with custom retry timeout strategy</summary>
```typescript
import { createClient } from 'graphql-ws';
const client = createClient({
url: 'wss://i.want.retry/control/graphql',
// this is the default
retryWait: async function randomisedExponentialBackoff(retries: number) {
let retryDelay = 1000; // start with 1s delay
for (let i = 0; i < retries; i++) {
retryDelay *= 2; // square `retries` times
}
await new Promise((resolve) =>
setTimeout(
// resolve pending promise with added random timeout from 300ms to 3s
resolve,
retryDelay + Math.floor(Math.random() * (3000 - 300) + 300),
),
);
},
});
```
</details>
<details id="browser">

@@ -746,2 +773,67 @@ <summary><a href="#browser">🔗</a> Client usage in browser</summary>

<details id="ws-backwards-compat">
<summary><a href="#ws-backwards-compat">🔗</a> <a href="https://github.com/websockets/ws">ws</a> server usage with <a href="https://github.com/apollographql/subscriptions-transport-ws">subscriptions-transport-ws</a> backwards compatibility</summary>
```ts
import https from 'https';
import ws from 'ws'; // yarn add ws
import { execute, subscribe } from 'graphql';
import { GRAPHQL_TRANSPORT_WS_PROTOCOL } from 'graphql-ws';
import { useServer } from 'graphql-ws/lib/use/ws';
import { SubscriptionServer, GRAPHQL_WS } from 'subscriptions-transport-ws';
import { schema } from 'my-graphql-schema';
// graphql-ws
const graphqlWs = new ws.Server({ noServer: true });
useServer(
{
schema,
execute,
subscribe,
},
graphqlWs,
);
// subscriptions-transport-ws
const subTransWs = new ws.Server({ noServer: true });
SubscriptionServer.create(
{
schema,
execute,
subscribe,
},
subTransWs,
);
// create https server
const server = https.createServer(function weServeSocketsOnly(_, res) {
res.writeHead(404);
res.end();
});
// listen for upgrades and delegate requests according to the WS subprotocol
server.on('upgrade', (req, socket, head) => {
// extract websocket subprotocol from header
const protocol = req.headers['sec-websocket-protocol'];
const protocols = Array.isArray(protocol)
? protocol
: protocol?.split(',').map((p) => p.trim());
// decide which websocket server to use
const wss =
protocols?.includes(GRAPHQL_WS) && // subscriptions-transport-ws subprotocol
!protocols.includes(GRAPHQL_TRANSPORT_WS_PROTOCOL) // graphql-ws subprotocol
? subTransWs
: // graphql-ws will welcome its own subprotocol and
// gracefully reject invalid ones. if the client supports
// both transports, graphql-ws will prevail
graphqlWs;
wss.handleUpgrade(req, socket, head, (ws) => {
wss.emit('connection', ws, req);
});
});
```
</details>
<details id="logging">

@@ -748,0 +840,0 @@ <summary><a href="#logging">🔗</a> <a href="https://github.com/websockets/ws">ws</a> server usage with console logging</summary>

@@ -125,4 +125,11 @@ (function (global, factory) {

function createClient(options) {
const { url, connectionParams, lazy = true, keepAlive = 0, retryAttempts = 5, retryTimeout = 3 * 1000, // 3 seconds
on, webSocketImpl,
const { url, connectionParams, lazy = true, keepAlive = 0, retryAttempts = 5, retryWait = async function randomisedExponentialBackoff(retries) {
let retryDelay = 1000; // start with 1s delay
for (let i = 0; i < retries; i++) {
retryDelay *= 2;
}
await new Promise((resolve) => setTimeout(resolve, retryDelay +
// add random timeout from 300ms to 3s
Math.floor(Math.random() * (3000 - 300) + 300)));
}, on, webSocketImpl,
/**

@@ -152,8 +159,12 @@ * Generates a v4 UUID to be used as the ID using `Math`

else if (typeof global !== 'undefined') {
// @ts-expect-error: Support more browsers
ws = global.WebSocket || global.MozWebSocket;
ws =
global.WebSocket ||
// @ts-expect-error: Support more browsers
global.MozWebSocket;
}
else if (typeof window !== 'undefined') {
// @ts-expect-error: Support more browsers
ws = window.WebSocket || window.MozWebSocket;
ws =
window.WebSocket ||
// @ts-expect-error: Support more browsers
window.MozWebSocket;
}

@@ -196,5 +207,9 @@ if (!ws) {

locks: 0,
tries: 0,
retrying: false,
retries: 0,
};
// all those waiting for the `retryWait` to resolve
const retryWaiting = [];
async function connect(cancellerRef, callDepth = 0) {
var _a;
// prevents too many recursive calls when reavaluating/re-connecting

@@ -204,2 +219,22 @@ if (callDepth > 10) {

}
// retry wait strategy only on root caller
if (state.retrying && callDepth === 0) {
if (retryWaiting.length) {
// if others are waiting for retry, I'll wait too
await new Promise((resolve) => retryWaiting.push(resolve));
}
else {
retryWaiting.push(() => {
/** fake waiter to lead following connects in the `retryWaiting` queue */
});
// use retry wait strategy
await retryWait(state.retries++);
// complete all waiting and clear the queue
while (retryWaiting.length) {
(_a = retryWaiting.pop()) === null || _a === void 0 ? void 0 : _a();
}
}
}
// if recursive call, wait a bit for socket change
await new Promise((resolve) => setTimeout(resolve, callDepth * 50));
// socket already exists. can be ready or pending, check and behave accordingly

@@ -211,3 +246,2 @@ if (state.socket) {

if (!state.acknowledged) {
await new Promise((resolve) => setTimeout(resolve, 300));
return connect(cancellerRef, callDepth + 1);

@@ -219,3 +253,2 @@ }

// if the socket is in the connecting phase, wait a bit and reavaluate
await new Promise((resolve) => setTimeout(resolve, 300));
return connect(cancellerRef, callDepth + 1);

@@ -227,3 +260,2 @@ }

// if the socket is in the closing phase, wait a bit and connect
await new Promise((resolve) => setTimeout(resolve, 300));
return connect(cancellerRef, callDepth + 1);

@@ -237,3 +269,3 @@ }

const socket = new WebSocketImpl(url, GRAPHQL_TRANSPORT_WS_PROTOCOL);
state = Object.assign(Object.assign({}, state), { acknowledged: false, socket, tries: state.tries + 1 });
state = Object.assign(Object.assign({}, state), { acknowledged: false, socket });
emitter.emit('connecting');

@@ -273,3 +305,3 @@ await new Promise((resolve, reject) => {

clearTimeout(tooLong);
state = Object.assign(Object.assign({}, state), { acknowledged: true, socket, tries: 0 });
state = Object.assign(Object.assign({}, state), { acknowledged: true, socket, retrying: false, retries: 0 });
emitter.emit('connected', socket, message.payload); // connected = socket opened + acknowledged

@@ -378,6 +410,7 @@ return resolve();

// retries are not allowed or we tried to many times, report error
if (!retryAttempts || state.tries > retryAttempts) {
if (!retryAttempts || state.retries >= retryAttempts) {
throw errOrCloseEvent;
}
// looks good, please retry
// looks good, start retrying
state.retrying = true;
return true;

@@ -399,7 +432,4 @@ }

// return if shouldnt try again
if (!shouldRetryConnectOrThrow(errOrCloseEvent)) {
if (!shouldRetryConnectOrThrow(errOrCloseEvent))
return;
}
// if should try again, wait a bit and continue loop
await new Promise((resolve) => setTimeout(resolve, retryTimeout));
}

@@ -489,7 +519,4 @@ }

// return if shouldnt try again
if (!shouldRetryConnectOrThrow(errOrCloseEvent)) {
if (!shouldRetryConnectOrThrow(errOrCloseEvent))
return;
}
// if should try again, wait a bit and continue loop
await new Promise((resolve) => setTimeout(resolve, retryTimeout));
}

@@ -496,0 +523,0 @@ }

@@ -1,1 +0,1 @@

!function(e,t){"object"==typeof exports&&"undefined"!=typeof module?t(exports):"function"==typeof define&&define.amd?define(["exports"],t):t((e="undefined"!=typeof globalThis?globalThis:e||self).graphqlWs={})}(this,(function(e){"use strict";const t=Object.prototype.hasOwnProperty;function n(e){return"object"==typeof e&&null!==e}function o(e,n){return t.call(e,n)}function r(e,o){return t.call(e,o)&&n(e[o])}function c(e,n){return t.call(e,n)&&"string"==typeof e[n]}var i;function s(e){if(n(e)){if(!c(e,"type"))return!1;switch(e.type){case i.ConnectionInit:case i.ConnectionAck:return!o(e,"payload")||void 0===e.payload||n(e.payload);case i.Subscribe:return c(e,"id")&&r(e,"payload")&&(!o(e.payload,"operationName")||void 0===e.payload.operationName||null===e.payload.operationName||"string"==typeof e.payload.operationName)&&c(e.payload,"query")&&(!o(e.payload,"variables")||void 0===e.payload.variables||null===e.payload.variables||r(e.payload,"variables"));case i.Next:return c(e,"id")&&r(e,"payload");case i.Error:return c(e,"id")&&(t=e.payload,Array.isArray(t)&&t.length>0&&t.every((e=>"message"in e)));case i.Complete:return c(e,"id");default:return!1}}var t;return!1}function a(e){if(s(e))return e;if("string"!=typeof e)throw new Error("Message not parsable");const t=JSON.parse(e);if(!s(t))throw new Error("Invalid message");return t}function l(e){if(!s(e))throw new Error("Cannot stringify invalid message");return JSON.stringify(e)}!function(e){e.ConnectionInit="connection_init",e.ConnectionAck="connection_ack",e.Subscribe="subscribe",e.Next="next",e.Error="error",e.Complete="complete"}(i||(i={})),e.createClient=function(e){const{url:t,connectionParams:o,lazy:r=!0,keepAlive:c=0,retryAttempts:s=5,retryTimeout:u=3e3,on:d,webSocketImpl:f,generateID:p=function(){return"xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx".replace(/[xy]/g,(e=>{const t=16*Math.random()|0;return("x"==e?t:3&t|8).toString(16)}))}}=e;let y;if(f){if(!("function"==typeof(m=f)&&"constructor"in m&&"CLOSED"in m&&"CLOSING"in m&&"CONNECTING"in m&&"OPEN"in m))throw new Error("Invalid WebSocket implementation provided");y=f}else"undefined"!=typeof WebSocket?y=WebSocket:"undefined"!=typeof global?y=global.WebSocket||global.MozWebSocket:"undefined"!=typeof window&&(y=window.WebSocket||window.MozWebSocket);var m;if(!y)throw new Error("WebSocket implementation missing");const w=y,b=(()=>{const e={connecting:(null==d?void 0:d.connecting)?[d.connecting]:[],connected:(null==d?void 0:d.connected)?[d.connected]:[],closed:(null==d?void 0:d.closed)?[d.closed]:[]};return{on(t,n){const o=e[t];return o.push(n),()=>{o.splice(o.indexOf(n),1)}},emit(t,...n){for(const o of e[t])o(...n)},reset(){Object.keys(e).forEach((t=>{e[t]=[]}))}}})();let g,k,x={socket:null,acknowledged:!1,locks:0,tries:0};async function v(e,n=0){if(n>10)throw new Error("Kept trying to connect but the socket never settled.");if(x.socket)switch(x.socket.readyState){case w.OPEN:return x.acknowledged?h(x.socket,e):(await new Promise((e=>setTimeout(e,300))),v(e,n+1));case w.CONNECTING:return await new Promise((e=>setTimeout(e,300))),v(e,n+1);case w.CLOSED:break;case w.CLOSING:return await new Promise((e=>setTimeout(e,300))),v(e,n+1);default:throw new Error(`Impossible ready state ${x.socket.readyState}`)}const r=new w(t,"graphql-transport-ws");return x=Object.assign(Object.assign({},x),{acknowledged:!1,socket:r,tries:x.tries+1}),b.emit("connecting"),await new Promise(((t,n)=>{let c=!1;e.current=()=>c=!0;const s=setTimeout((()=>{r.close(3408,"Waited 5 seconds but socket connect never settled")}),5e3);r.onclose=e=>(r.onclose=null,clearTimeout(s),x=Object.assign(Object.assign({},x),{acknowledged:!1,socket:null}),b.emit("closed",e),n(e)),r.onmessage=e=>{if(r.onmessage=null,c)r.close(3499,"Client cancelled the socket before connecting");else try{const n=a(e.data);if(n.type!==i.ConnectionAck)throw new Error(`First message cannot be of type ${n.type}`);return clearTimeout(s),x=Object.assign(Object.assign({},x),{acknowledged:!0,socket:r,tries:0}),b.emit("connected",r,n.payload),t()}catch(e){r.close(4400,e instanceof Error?e.message:new Error(e).message)}},r.onopen=()=>{r.onopen=null,c?r.close(3499,"Client cancelled the socket before connecting"):(async()=>{try{r.send(l({type:i.ConnectionInit,payload:"function"==typeof o?await o():o}))}catch(e){r.close(4400,e instanceof Error?e.message:new Error(e).message)}})()}})),h(r,e)}async function h(e,t){return[e,n=>new Promise(((o,r)=>{if(e.readyState===w.CLOSED)return r(new Error("Socket has already been closed"));function i(n){return t.current=null,x.locks--,e.removeEventListener("close",i),r(n)}x.locks++,e.addEventListener("close",i),t.current=()=>(t.current=null,null==n||n(),x.locks--,x.locks||(c>0&&isFinite(c)?setTimeout((()=>{!x.locks&&e.OPEN&&e.close(1e3,"Normal Closure")}),c):e.close(1e3,"Normal Closure")),e.removeEventListener("close",i),o())}))]}function E(e){if(!function(e){return n(e)&&"code"in e&&"reason"in e}(e))throw e;if([1002,1011,4400,4401,4409,4429].includes(e.code))throw e;if(1e3===e.code)return!1;if(3499===e.code)return!1;if(!s||x.tries>s)throw e;return!0}return r||(async()=>{for(;;)try{const[,e]=await v({current:null});return void await e()}catch(e){if(!E(e))return;await new Promise((e=>setTimeout(e,u)))}})(),{on:b.on,subscribe(e,t){const n=p();let o=!1;const r={current:null},c=({data:e})=>{const c=function(e){return e!==g&&(k=a(e),g=e),k}(e);switch(c.type){case i.Next:return void(c.id===n&&t.next(c.payload));case i.Error:return void(c.id===n&&(t.error(c.payload),r.current()));case i.Complete:return void(c.id===n&&(o=!0,r.current()))}};return(async()=>{for(;;)try{const[t,s]=await v(r);return t.addEventListener("message",c),t.send(l({id:n,type:i.Subscribe,payload:e})),await s((()=>{o||t.send(l({id:n,type:i.Complete}))})),void t.removeEventListener("message",c)}catch(e){if(!E(e))return;await new Promise((e=>setTimeout(e,u)))}})().catch(t.error).then(t.complete),()=>{var e;null===(e=r.current)||void 0===e||e.call(r)}},dispose(){var e;null===(e=x.socket)||void 0===e||e.close(1e3,"Normal Closure"),b.reset()}}},Object.defineProperty(e,"__esModule",{value:!0})}));
!function(e,t){"object"==typeof exports&&"undefined"!=typeof module?t(exports):"function"==typeof define&&define.amd?define(["exports"],t):t((e="undefined"!=typeof globalThis?globalThis:e||self).graphqlWs={})}(this,(function(e){"use strict";const t=Object.prototype.hasOwnProperty;function n(e){return"object"==typeof e&&null!==e}function o(e,n){return t.call(e,n)}function r(e,o){return t.call(e,o)&&n(e[o])}function c(e,n){return t.call(e,n)&&"string"==typeof e[n]}var i;function a(e){if(n(e)){if(!c(e,"type"))return!1;switch(e.type){case i.ConnectionInit:case i.ConnectionAck:return!o(e,"payload")||void 0===e.payload||n(e.payload);case i.Subscribe:return c(e,"id")&&r(e,"payload")&&(!o(e.payload,"operationName")||void 0===e.payload.operationName||null===e.payload.operationName||"string"==typeof e.payload.operationName)&&c(e.payload,"query")&&(!o(e.payload,"variables")||void 0===e.payload.variables||null===e.payload.variables||r(e.payload,"variables"));case i.Next:return c(e,"id")&&r(e,"payload");case i.Error:return c(e,"id")&&(t=e.payload,Array.isArray(t)&&t.length>0&&t.every((e=>"message"in e)));case i.Complete:return c(e,"id");default:return!1}}var t;return!1}function s(e){if(a(e))return e;if("string"!=typeof e)throw new Error("Message not parsable");const t=JSON.parse(e);if(!a(t))throw new Error("Invalid message");return t}function l(e){if(!a(e))throw new Error("Cannot stringify invalid message");return JSON.stringify(e)}!function(e){e.ConnectionInit="connection_init",e.ConnectionAck="connection_ack",e.Subscribe="subscribe",e.Next="next",e.Error="error",e.Complete="complete"}(i||(i={})),e.createClient=function(e){const{url:t,connectionParams:o,lazy:r=!0,keepAlive:c=0,retryAttempts:a=5,retryWait:u=async function(e){let t=1e3;for(let n=0;n<e;n++)t*=2;await new Promise((e=>setTimeout(e,t+Math.floor(2700*Math.random()+300))))},on:d,webSocketImpl:f,generateID:p=function(){return"xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx".replace(/[xy]/g,(e=>{const t=16*Math.random()|0;return("x"==e?t:3&t|8).toString(16)}))}}=e;let y;if(f){if(!("function"==typeof(m=f)&&"constructor"in m&&"CLOSED"in m&&"CLOSING"in m&&"CONNECTING"in m&&"OPEN"in m))throw new Error("Invalid WebSocket implementation provided");y=f}else"undefined"!=typeof WebSocket?y=WebSocket:"undefined"!=typeof global?y=global.WebSocket||global.MozWebSocket:"undefined"!=typeof window&&(y=window.WebSocket||window.MozWebSocket);var m;if(!y)throw new Error("WebSocket implementation missing");const w=y,g=(()=>{const e={connecting:(null==d?void 0:d.connecting)?[d.connecting]:[],connected:(null==d?void 0:d.connected)?[d.connected]:[],closed:(null==d?void 0:d.closed)?[d.closed]:[]};return{on(t,n){const o=e[t];return o.push(n),()=>{o.splice(o.indexOf(n),1)}},emit(t,...n){for(const o of e[t])o(...n)},reset(){Object.keys(e).forEach((t=>{e[t]=[]}))}}})();let b={socket:null,acknowledged:!1,locks:0,retrying:!1,retries:0};const k=[];async function v(e,n=0){var r;if(n>10)throw new Error("Kept trying to connect but the socket never settled.");if(b.retrying&&0===n)if(k.length)await new Promise((e=>k.push(e)));else for(k.push((()=>{})),await u(b.retries++);k.length;)null===(r=k.pop())||void 0===r||r();if(await new Promise((e=>setTimeout(e,50*n))),b.socket)switch(b.socket.readyState){case w.OPEN:return b.acknowledged?x(b.socket,e):v(e,n+1);case w.CONNECTING:return v(e,n+1);case w.CLOSED:break;case w.CLOSING:return v(e,n+1);default:throw new Error(`Impossible ready state ${b.socket.readyState}`)}const c=new w(t,"graphql-transport-ws");return b=Object.assign(Object.assign({},b),{acknowledged:!1,socket:c}),g.emit("connecting"),await new Promise(((t,n)=>{let r=!1;e.current=()=>r=!0;const a=setTimeout((()=>{c.close(3408,"Waited 5 seconds but socket connect never settled")}),5e3);c.onclose=e=>(c.onclose=null,clearTimeout(a),b=Object.assign(Object.assign({},b),{acknowledged:!1,socket:null}),g.emit("closed",e),n(e)),c.onmessage=e=>{if(c.onmessage=null,r)c.close(3499,"Client cancelled the socket before connecting");else try{const n=s(e.data);if(n.type!==i.ConnectionAck)throw new Error(`First message cannot be of type ${n.type}`);return clearTimeout(a),b=Object.assign(Object.assign({},b),{acknowledged:!0,socket:c,retrying:!1,retries:0}),g.emit("connected",c,n.payload),t()}catch(e){c.close(4400,e instanceof Error?e.message:new Error(e).message)}},c.onopen=()=>{c.onopen=null,r?c.close(3499,"Client cancelled the socket before connecting"):(async()=>{try{c.send(l({type:i.ConnectionInit,payload:"function"==typeof o?await o():o}))}catch(e){c.close(4400,e instanceof Error?e.message:new Error(e).message)}})()}})),x(c,e)}async function x(e,t){return[e,n=>new Promise(((o,r)=>{if(e.readyState===w.CLOSED)return r(new Error("Socket has already been closed"));function i(n){return t.current=null,b.locks--,e.removeEventListener("close",i),r(n)}b.locks++,e.addEventListener("close",i),t.current=()=>(t.current=null,null==n||n(),b.locks--,b.locks||(c>0&&isFinite(c)?setTimeout((()=>{!b.locks&&e.OPEN&&e.close(1e3,"Normal Closure")}),c):e.close(1e3,"Normal Closure")),e.removeEventListener("close",i),o())}))]}function h(e){if(!function(e){return n(e)&&"code"in e&&"reason"in e}(e))throw e;if([1002,1011,4400,4401,4409,4429].includes(e.code))throw e;if(1e3===e.code)return!1;if(3499===e.code)return!1;if(!a||b.retries>=a)throw e;return b.retrying=!0,!0}let E,C;return r||(async()=>{for(;;)try{const[,e]=await v({current:null});return void await e()}catch(e){if(!h(e))return}})(),{on:g.on,subscribe(e,t){const n=p();let o=!1;const r={current:null},c=({data:e})=>{const c=function(e){return e!==E&&(C=s(e),E=e),C}(e);switch(c.type){case i.Next:return void(c.id===n&&t.next(c.payload));case i.Error:return void(c.id===n&&(t.error(c.payload),r.current()));case i.Complete:return void(c.id===n&&(o=!0,r.current()))}};return(async()=>{for(;;)try{const[t,a]=await v(r);return t.addEventListener("message",c),t.send(l({id:n,type:i.Subscribe,payload:e})),await a((()=>{o||t.send(l({id:n,type:i.Complete}))})),void t.removeEventListener("message",c)}catch(e){if(!h(e))return}})().catch(t.error).then(t.complete),()=>{var e;null===(e=r.current)||void 0===e||e.call(r)}},dispose(){var e;null===(e=b.socket)||void 0===e||e.close(1e3,"Normal Closure"),g.reset()}}},Object.defineProperty(e,"__esModule",{value:!0})}));

Sorry, the diff of this file is not supported yet

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc