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 5.6.4 to 5.7.0

13

lib/client.d.ts

@@ -346,2 +346,15 @@ /**

subscribe<Data = Record<string, unknown>, Extensions = unknown>(payload: SubscribePayload, sink: Sink<ExecutionResult<Data, Extensions>>): () => void;
/**
* Terminates the WebSocket abruptly and immediately.
*
* A close event `4499: Terminated` is issued to the current WebSocket and an
* artificial `{ code: 4499, reason: 'Terminated', wasClean: false }` close-event-like
* object is immediately emitted without waiting for the one coming from `WebSocket.onclose`.
*
* Terminating is not considered fatal and a connection retry will occur as expected.
*
* Useful in cases where the WebSocket is stuck and not emitting any events;
* can happen on iOS Safari, see: https://github.com/enisdenjo/graphql-ws/discussions/290.
*/
terminate(): void;
}

@@ -348,0 +361,0 @@ /**

@@ -175,2 +175,7 @@ "use strict";

denied(errOrEvent);
if (isLikeCloseEvent(errOrEvent) && errOrEvent.code === 4499) {
socket.close(4499, 'Terminated'); // close event is artificial and emitted manually, see `Client.terminate()` below
socket.onerror = null;
socket.onclose = null;
}
});

@@ -312,2 +317,3 @@ socket.onerror = (err) => emitter.emit('error', err);

common_1.CloseCode.TooManyInitialisationRequests,
// 4499, // Terminated, probably because the socket froze, we want to retry
].includes(errOrCloseEvent.code)))

@@ -439,2 +445,12 @@ throw errOrCloseEvent;

},
terminate() {
if (connecting) {
// only if there is a connection
emitter.emit('closed', {
code: 4499,
reason: 'Terminated',
wasClean: false,
});
}
},
};

@@ -441,0 +457,0 @@ }

18

package.json
{
"name": "graphql-ws",
"version": "5.6.4",
"version": "5.7.0",
"description": "Coherent, zero-dependency, lazy, simple, GraphQL over WebSocket Protocol compliant server and client",

@@ -85,3 +85,3 @@ "keywords": [

"devDependencies": {
"@babel/core": "^7.17.8",
"@babel/core": "^7.17.9",
"@babel/plugin-proposal-class-properties": "^7.16.7",

@@ -98,9 +98,9 @@ "@babel/plugin-proposal-nullish-coalescing-operator": "^7.16.7",

"@types/ws": "^8.5.3",
"@typescript-eslint/eslint-plugin": "^5.16.0",
"@typescript-eslint/parser": "^5.16.0",
"@typescript-eslint/eslint-plugin": "^5.18.0",
"@typescript-eslint/parser": "^5.18.0",
"babel-jest": "^27.5.1",
"eslint": "^8.11.0",
"eslint": "^8.12.0",
"eslint-config-prettier": "^8.5.0",
"eslint-plugin-prettier": "^4.0.0",
"fastify": "^3.27.4",
"fastify": "^3.28.0",
"fastify-websocket": "^4.2.1",

@@ -110,3 +110,3 @@ "glob": "^7.2.0",

"jest": "^27.5.1",
"prettier": "^2.6.0",
"prettier": "^2.6.2",
"replacestream": "^4.0.3",

@@ -118,5 +118,5 @@ "rollup": "^2.70.1",

"tslib": "^2.3.1",
"typedoc": "^0.22.13",
"typedoc": "^0.22.14",
"typedoc-plugin-markdown": "^3.11.14",
"typescript": "^4.6.2",
"typescript": "^4.6.3",
"uWebSockets.js": "uNetworking/uWebSockets.js#v20.6.0",

@@ -123,0 +123,0 @@ "ws": "^8.5.0",

@@ -19,2 +19,4 @@ # GraphQL over WebSocket Protocol

Multiple operations identified with separate IDs can be active at any time and their messages can be interleaved on the connection.
The server can close the socket (kick the client off) at any time. The close event dispatched by the server is used to describe the fatal error to the client.

@@ -102,4 +104,6 @@

If there is already an active subscriber for an operation matching the provided ID, regardless of the operation type, the server must close the socket immediately with the event `4409: Subscriber for <unique-operation-id> already exists`.
If there is already an active subscriber for an operation matching the provided ID, regardless of the operation type, the server **must** close the socket immediately with the event `4409: Subscriber for <unique-operation-id> already exists`.
The server needs only keep track of IDs for as long as the subscription is active. Once a client completes an operation, it is free to re-use that ID.
```typescript

@@ -140,3 +144,3 @@ interface SubscribeMessage {

Operation execution error(s) triggered by the `Next` message happening before the actual execution, usually due to validation errors.
Operation execution error(s) in response to the `Subscribe` message. This can occur _before_ execution starts, usually due to validation errors, or _during_ the execution of the request. This message terminates the operation and no further messages will be sent.

@@ -159,4 +163,6 @@ ```typescript

- **Client -> Server** indicates that the client has stopped listening and wants to complete the subscription. No further events, relevant to the original subscription, should be sent through. Even if the client completed a single result operation before it resolved, the result should not be sent through once it does.
- **Client -> Server** indicates that the client has stopped listening and wants to complete the subscription. No further events, relevant to the original subscription, should be sent through. Even if the client sent a `Complete` message for a _single-result-operation_ before it resolved, the result should not be sent through once it does.
Note: The asynchronous nature of the full-duplex connection means that a client can send a `Complete` message to the server even when messages are in-flight to the client, or when the server has itself completed the operation (via a `Error` or `Complete` message). Both client and server must therefore be prepared to receive (and ignore) messages for operations that they consider already completed.
```typescript

@@ -175,2 +181,4 @@ interface CompleteMessage {

Receiving a message (other than `Subscribe`) with an ID that belongs to an operation that has been previously completed does not constitute an error. It is permissable to simply ignore all _unknown_ IDs without closing the connection.
## Examples

@@ -197,15 +205,2 @@

### Single result operation
#### `query` and `mutation` operations without streaming directives
_The client and the server has already gone through [successful connection initialisation](#successful-connection-initialisation)._
1. _Client_ generates a unique ID for the following operation
1. _Client_ dispatches the `Subscribe` message with the generated ID through the `id` field and the requested operation passed through the `payload` field
<br>_All future communication is linked through this unique ID_
1. _Server_ executes the single result GraphQL operation
1. _Server_ dispatches the result with the `Next` message
1. _Server_ dispatches the `Complete` message indicating that the execution has completed
### Streaming operation

@@ -226,7 +221,37 @@

1. _Server_ _optionally_ checks if the operation is valid before starting executing it, e.g. checking permissions
- If **not** valid, the _server_ sends an `Error` message and deems the operation complete.
- If valid, continue...
1. _Server_ dispatches results over time with the `Next` message
1. - _Client_ stops the subscription by dispatching a `Complete` message
- _Server_ completes the source stream
<br>_or_
1. - _Server_ dispatches the `Complete` message indicating that the source stream has completed
- _Client_ completes the stream observer
<br>**or**
- _Client_ stops the subscription by dispatching a `Complete` message
- _Server_ receives `Complete` message and completes the source stream
- _Client_ ignores all further messages that it recives with this ID
<br>**or**
- _Server_ dispatches the `Complete` message indicating that the source stream has completed
- _Client_ completes the stream observer
- **Simultaneously** _client_ stops the subscription by dispatching a `Complete` message
- _Client_ ignores all further messages that it recives with this ID
- _Server_ ignores the `Complete` message from the client
### Single result operation
#### `query` and `mutation` operations without streaming directives
A single result operation is identical to a streaming operation except that _at most one_ `Next` message is sent.
It shares the same name-space for IDs as streaming operations and can be multiplexed with other operations on the connection.
_The client and the server has already gone through [successful connection initialisation](#successful-connection-initialisation)._
1. _Client_ generates a unique ID for the following operation
1. _Client_ dispatches the `Subscribe` message with the generated ID through the `id` field and the requested operation passed through the `payload` field
<br>_All future communication is linked through this unique ID_
1. _Server_ executes the single result GraphQL operation
1. _Server_ dispatches the result with the `Next` message
1. _Server_ dispatches the `Complete` message indicating that the execution has completed
The _client_ may dispatch a `Complete` message at any time, just as shown in the streaming operations examples above, and the same interactions ensue.

@@ -423,16 +423,18 @@ <div align="center">

// to define your own GraphQLWsLink.
import { GraphQLWsLink } from "@apollo/client/link/subscriptions";
import { GraphQLWsLink } from '@apollo/client/link/subscriptions';
const link = new GraphQLWsLink(createClient({
url: 'ws://where.is:4000/graphql',
connectionParams: () => {
const session = getSession();
if (!session) {
return {};
}
return {
Authorization: `Bearer ${session.token}`,
};
},
});
const link = new GraphQLWsLink(
createClient({
url: 'ws://where.is:4000/graphql',
connectionParams: () => {
const session = getSession();
if (!session) {
return {};
}
return {
Authorization: `Bearer ${session.token}`,
};
},
}),
);
```

@@ -475,3 +477,3 @@

</details>
<details id="kotlin">

@@ -693,2 +695,38 @@ <summary><a href="#kotlin">🔗</a> Client usage with <a href="https://github.com/apollographql/apollo-kotlin">Apollo Kotlin</a></summary>

<details id="client-terminate">
<summary><a href="#client-terminate">🔗</a> Client usage with abrupt termination on pong timeout</summary>
```typescript
import { createClient } from 'graphql-ws';
let timedOut;
const client = createClient({
url: 'ws://terminate.me:4000/on-pong-timeout',
keepAlive: 10_000, // ping server every 10 seconds
on: {
ping: (received) => {
if (!received /* sent */) {
timedOut = setTimeout(() => {
// a close event `4499: Terminated` is issued to the current WebSocket and an
// artificial `{ code: 4499, reason: 'Terminated', wasClean: false }` close-event-like
// object is immediately emitted without waiting for the one coming from `WebSocket.onclose`
//
// calling terminate is not considered fatal and a connection retry will occur as expected
//
// see: https://github.com/enisdenjo/graphql-ws/discussions/290
client.terminate();
}, 5_000);
}
},
pong: (received) => {
if (received) {
clearTimeout(timedOut);
}
},
},
});
```
</details>
<details id="custom-client-pinger">

@@ -1173,3 +1211,3 @@ <summary><a href="#custom-client-pinger">🔗</a> Client usage with manual pings and pongs</summary>

// create apollo server
const server = new ApolloServer({
const apolloServer = new ApolloServer({
schema,

@@ -1757,4 +1795,4 @@ plugins: [

This library and the [GraphQL over WebSocket Protocol](https://github.com/enisdenjo/graphql-ws/blob/master/PROTOCOL.md) are **not** cross-compatible with the legacy [`subscriptions-transport-ws`](https://github.com/apollographql/subscriptions-transport-ws) and its [accompanying Protocol](https://github.com/apollographql/subscriptions-transport-ws/blob/master/PROTOCOL.md).
This library and the [GraphQL over WebSocket Protocol](https://github.com/enisdenjo/graphql-ws/blob/master/PROTOCOL.md) are **not** cross-compatible with the [deprecated `subscriptions-transport-ws`](https://github.com/apollographql/subscriptions-transport-ws) and its [accompanying Protocol](https://github.com/apollographql/subscriptions-transport-ws/blob/master/PROTOCOL.md).
You must use `graphql-ws` coherently and implement the [GraphQL over WebSocket Protocol](https://github.com/enisdenjo/graphql-ws/blob/master/PROTOCOL.md) on both sides, server and the client.

@@ -334,2 +334,7 @@ (function (global, factory) {

denied(errOrEvent);
if (isLikeCloseEvent(errOrEvent) && errOrEvent.code === 4499) {
socket.close(4499, 'Terminated'); // close event is artificial and emitted manually, see `Client.terminate()` below
socket.onerror = null;
socket.onclose = null;
}
});

@@ -471,2 +476,3 @@ socket.onerror = (err) => emitter.emit('error', err);

exports.CloseCode.TooManyInitialisationRequests,
// 4499, // Terminated, probably because the socket froze, we want to retry
].includes(errOrCloseEvent.code)))

@@ -598,2 +604,12 @@ throw errOrCloseEvent;

},
terminate() {
if (connecting) {
// only if there is a connection
emitter.emit('closed', {
code: 4499,
reason: 'Terminated',
wasClean: false,
});
}
},
};

@@ -600,0 +616,0 @@ }

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

!function(e,o){"object"==typeof exports&&"undefined"!=typeof module?o(exports):"function"==typeof define&&define.amd?define(["exports"],o):o((e="undefined"!=typeof globalThis?globalThis:e||self).graphqlWs={})}(this,(function(e){"use strict";const o=Object.prototype.hasOwnProperty;function n(e){return"object"==typeof e&&null!==e}function t(e,n){return o.call(e,n)}function r(e,t){return o.call(e,t)&&n(e[t])}function i(e,n){return o.call(e,n)&&"string"==typeof e[n]}function a(e,o){return e.length<124?e:o}const s="graphql-transport-ws";var c,l;function d(o){if(n(o)){if(!i(o,"type"))return!1;switch(o.type){case e.MessageType.ConnectionInit:case e.MessageType.ConnectionAck:case e.MessageType.Ping:case e.MessageType.Pong:return!t(o,"payload")||void 0===o.payload||n(o.payload);case e.MessageType.Subscribe:return i(o,"id")&&r(o,"payload")&&(!t(o.payload,"operationName")||void 0===o.payload.operationName||null===o.payload.operationName||"string"==typeof o.payload.operationName)&&i(o.payload,"query")&&(!t(o.payload,"variables")||void 0===o.payload.variables||null===o.payload.variables||r(o.payload,"variables"))&&(!t(o.payload,"extensions")||void 0===o.payload.extensions||null===o.payload.extensions||r(o.payload,"extensions"));case e.MessageType.Next:return i(o,"id")&&r(o,"payload");case e.MessageType.Error:return i(o,"id")&&(a=o.payload,Array.isArray(a)&&a.length>0&&a.every((e=>"message"in e)));case e.MessageType.Complete:return i(o,"id");default:return!1}}var a;return!1}function p(e,o){if(d(e))return e;if("string"!=typeof e)throw new Error("Message not parsable");const n=JSON.parse(e,o);if(!d(n))throw new Error("Invalid message");return n}function u(e,o){if(!d(e))throw new Error("Cannot stringify invalid message");return JSON.stringify(e,o)}function y(e){return n(e)&&"code"in e&&"reason"in e}e.CloseCode=void 0,(c=e.CloseCode||(e.CloseCode={}))[c.InternalServerError=4500]="InternalServerError",c[c.InternalClientError=4005]="InternalClientError",c[c.BadRequest=4400]="BadRequest",c[c.BadResponse=4004]="BadResponse",c[c.Unauthorized=4401]="Unauthorized",c[c.Forbidden=4403]="Forbidden",c[c.SubprotocolNotAcceptable=4406]="SubprotocolNotAcceptable",c[c.ConnectionInitialisationTimeout=4408]="ConnectionInitialisationTimeout",c[c.ConnectionAcknowledgementTimeout=4504]="ConnectionAcknowledgementTimeout",c[c.SubscriberAlreadyExists=4409]="SubscriberAlreadyExists",c[c.TooManyInitialisationRequests=4429]="TooManyInitialisationRequests",e.MessageType=void 0,(l=e.MessageType||(e.MessageType={})).ConnectionInit="connection_init",l.ConnectionAck="connection_ack",l.Ping="ping",l.Pong="pong",l.Subscribe="subscribe",l.Next="next",l.Error="error",l.Complete="complete",e.DEPRECATED_GRAPHQL_WS_PROTOCOL="graphql-ws",e.GRAPHQL_TRANSPORT_WS_PROTOCOL=s,e.createClient=function(o){const{url:n,connectionParams:t,lazy:r=!0,onNonLazyError:i=console.error,lazyCloseTimeout:c=0,keepAlive:l=0,disablePong:d,connectionAckWaitTimeout:g=0,retryAttempts:f=5,retryWait:m=async function(e){let o=1e3;for(let n=0;n<e;n++)o*=2;await new Promise((e=>setTimeout(e,o+Math.floor(2700*Math.random()+300))))},isFatalConnectionProblem:C=(e=>!y(e)),on:b,webSocketImpl:w,generateID:x=function(){return"xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx".replace(/[xy]/g,(e=>{const o=16*Math.random()|0;return("x"==e?o:3&o|8).toString(16)}))},jsonMessageReplacer:T,jsonMessageReviver:v}=o;let M;if(w){if(!("function"==typeof(S=w)&&"constructor"in S&&"CLOSED"in S&&"CLOSING"in S&&"CONNECTING"in S&&"OPEN"in S))throw new Error("Invalid WebSocket implementation provided");M=w}else"undefined"!=typeof WebSocket?M=WebSocket:"undefined"!=typeof global?M=global.WebSocket||global.MozWebSocket:"undefined"!=typeof window&&(M=window.WebSocket||window.MozWebSocket);var S;if(!M)throw new Error("WebSocket implementation missing; on Node you can `import WebSocket from 'ws';` and pass `webSocketImpl: WebSocket` to `createClient`");const h=M,E=(()=>{const e=(()=>{const e={};return{on:(o,n)=>(e[o]=n,()=>{delete e[o]}),emit(o){var n;"id"in o&&(null===(n=e[o.id])||void 0===n||n.call(e,o))}}})(),o={connecting:(null==b?void 0:b.connecting)?[b.connecting]:[],opened:(null==b?void 0:b.opened)?[b.opened]:[],connected:(null==b?void 0:b.connected)?[b.connected]:[],ping:(null==b?void 0:b.ping)?[b.ping]:[],pong:(null==b?void 0:b.pong)?[b.pong]:[],message:(null==b?void 0:b.message)?[e.emit,b.message]:[e.emit],closed:(null==b?void 0:b.closed)?[b.closed]:[],error:(null==b?void 0:b.error)?[b.error]:[]};return{onMessage:e.on,on(e,n){const t=o[e];return t.push(n),()=>{t.splice(t.indexOf(n),1)}},emit(e,...n){for(const t of[...o[e]])t(...n)}}})();function P(e){const o=[E.on("error",(n=>{o.forEach((e=>e())),e(n)})),E.on("closed",(n=>{o.forEach((e=>e())),e(n)}))]}let N,I=0,k=!1,A=0,O=!1;async function R(){const[o,r]=await(null!=N?N:N=new Promise(((o,r)=>(async()=>{if(k){if(await m(A),!I)return N=void 0,r({code:1e3,reason:"All Subscriptions Gone"});A++}E.emit("connecting");const i=new h("function"==typeof n?await n():n,s);let c,y;function f(){isFinite(l)&&l>0&&(clearTimeout(y),y=setTimeout((()=>{i.readyState===h.OPEN&&(i.send(u({type:e.MessageType.Ping})),E.emit("ping",!1,void 0))}),l))}P((e=>{N=void 0,clearTimeout(c),clearTimeout(y),r(e)})),i.onerror=e=>E.emit("error",e),i.onclose=e=>E.emit("closed",e),i.onopen=async()=>{try{E.emit("opened",i);const o="function"==typeof t?await t():t;if(i.readyState!==h.OPEN)return;i.send(u(o?{type:e.MessageType.ConnectionInit,payload:o}:{type:e.MessageType.ConnectionInit},T)),isFinite(g)&&g>0&&(c=setTimeout((()=>{i.close(e.CloseCode.ConnectionAcknowledgementTimeout,"Connection acknowledgement timeout")}),g)),f()}catch(o){E.emit("error",o),i.close(e.CloseCode.InternalClientError,a(o instanceof Error?o.message:new Error(o).message,"Internal client error"))}};let C=!1;i.onmessage=({data:n})=>{try{const t=p(n,v);if(E.emit("message",t),"ping"===t.type||"pong"===t.type)return E.emit(t.type,!0,t.payload),void("pong"===t.type?f():d||(i.send(u(t.payload?{type:e.MessageType.Pong,payload:t.payload}:{type:e.MessageType.Pong})),E.emit("pong",!1,t.payload)));if(C)return;if(t.type!==e.MessageType.ConnectionAck)throw new Error(`First message cannot be of type ${t.type}`);clearTimeout(c),C=!0,E.emit("connected",i,t.payload),k=!1,A=0,o([i,new Promise(((e,o)=>P(o)))])}catch(o){i.onmessage=null,E.emit("error",o),i.close(e.CloseCode.BadResponse,a(o instanceof Error?o.message:new Error(o).message,"Bad response"))}}})())));o.readyState===h.CLOSING&&await r;let i=()=>{};const y=new Promise((e=>i=e));return[o,i,Promise.race([y.then((()=>{if(!I){const e=()=>o.close(1e3,"Normal Closure");isFinite(c)&&c>0?setTimeout((()=>{I||o.readyState!==h.OPEN||e()}),c):e()}})),r])]}function W(o){if(y(o)&&(n=o.code,![1e3,1001,1006,1005,1012,1013,1013].includes(n)&&n>=1e3&&n<=1999||[e.CloseCode.InternalServerError,e.CloseCode.InternalClientError,e.CloseCode.BadRequest,e.CloseCode.BadResponse,e.CloseCode.Unauthorized,e.CloseCode.SubprotocolNotAcceptable,e.CloseCode.SubscriberAlreadyExists,e.CloseCode.TooManyInitialisationRequests].includes(o.code)))throw o;var n;if(O)return!1;if(y(o)&&1e3===o.code)return I>0;if(!f||A>=f)throw o;if(C(o))throw o;return k=!0}return r||(async()=>{for(I++;;)try{const[,,e]=await R();await e}catch(e){try{if(!W(e))return}catch(e){return null==i?void 0:i(e)}}})(),{on:E.on,subscribe(o,n){const t=x();let r=!1,i=!1,a=()=>{I--,r=!0};return(async()=>{for(I++;;)try{const[s,c,l]=await R();if(r)return c();const d=E.onMessage(t,(o=>{switch(o.type){case e.MessageType.Next:return void n.next(o.payload);case e.MessageType.Error:return i=!0,r=!0,n.error(o.payload),void a();case e.MessageType.Complete:return r=!0,void a()}}));return s.send(u({id:t,type:e.MessageType.Subscribe,payload:o},T)),a=()=>{r||s.readyState!==h.OPEN||s.send(u({id:t,type:e.MessageType.Complete},T)),I--,r=!0,c()},void await l.finally(d)}catch(e){if(!W(e))return}})().then((()=>{i||n.complete()})).catch((e=>{n.error(e)})),()=>{r||a()}},async dispose(){if(O=!0,N){const[e]=await N;e.close(1e3,"Normal Closure")}}}},e.isMessage=d,e.parseMessage=p,e.stringifyMessage=u,Object.defineProperty(e,"__esModule",{value:!0})}));
!function(e,o){"object"==typeof exports&&"undefined"!=typeof module?o(exports):"function"==typeof define&&define.amd?define(["exports"],o):o((e="undefined"!=typeof globalThis?globalThis:e||self).graphqlWs={})}(this,(function(e){"use strict";const o=Object.prototype.hasOwnProperty;function n(e){return"object"==typeof e&&null!==e}function t(e,n){return o.call(e,n)}function r(e,t){return o.call(e,t)&&n(e[t])}function i(e,n){return o.call(e,n)&&"string"==typeof e[n]}function a(e,o){return e.length<124?e:o}const s="graphql-transport-ws";var l,c;function d(o){if(n(o)){if(!i(o,"type"))return!1;switch(o.type){case e.MessageType.ConnectionInit:case e.MessageType.ConnectionAck:case e.MessageType.Ping:case e.MessageType.Pong:return!t(o,"payload")||void 0===o.payload||n(o.payload);case e.MessageType.Subscribe:return i(o,"id")&&r(o,"payload")&&(!t(o.payload,"operationName")||void 0===o.payload.operationName||null===o.payload.operationName||"string"==typeof o.payload.operationName)&&i(o.payload,"query")&&(!t(o.payload,"variables")||void 0===o.payload.variables||null===o.payload.variables||r(o.payload,"variables"))&&(!t(o.payload,"extensions")||void 0===o.payload.extensions||null===o.payload.extensions||r(o.payload,"extensions"));case e.MessageType.Next:return i(o,"id")&&r(o,"payload");case e.MessageType.Error:return i(o,"id")&&(a=o.payload,Array.isArray(a)&&a.length>0&&a.every((e=>"message"in e)));case e.MessageType.Complete:return i(o,"id");default:return!1}}var a;return!1}function p(e,o){if(d(e))return e;if("string"!=typeof e)throw new Error("Message not parsable");const n=JSON.parse(e,o);if(!d(n))throw new Error("Invalid message");return n}function u(e,o){if(!d(e))throw new Error("Cannot stringify invalid message");return JSON.stringify(e,o)}function y(e){return n(e)&&"code"in e&&"reason"in e}e.CloseCode=void 0,(l=e.CloseCode||(e.CloseCode={}))[l.InternalServerError=4500]="InternalServerError",l[l.InternalClientError=4005]="InternalClientError",l[l.BadRequest=4400]="BadRequest",l[l.BadResponse=4004]="BadResponse",l[l.Unauthorized=4401]="Unauthorized",l[l.Forbidden=4403]="Forbidden",l[l.SubprotocolNotAcceptable=4406]="SubprotocolNotAcceptable",l[l.ConnectionInitialisationTimeout=4408]="ConnectionInitialisationTimeout",l[l.ConnectionAcknowledgementTimeout=4504]="ConnectionAcknowledgementTimeout",l[l.SubscriberAlreadyExists=4409]="SubscriberAlreadyExists",l[l.TooManyInitialisationRequests=4429]="TooManyInitialisationRequests",e.MessageType=void 0,(c=e.MessageType||(e.MessageType={})).ConnectionInit="connection_init",c.ConnectionAck="connection_ack",c.Ping="ping",c.Pong="pong",c.Subscribe="subscribe",c.Next="next",c.Error="error",c.Complete="complete",e.DEPRECATED_GRAPHQL_WS_PROTOCOL="graphql-ws",e.GRAPHQL_TRANSPORT_WS_PROTOCOL=s,e.createClient=function(o){const{url:n,connectionParams:t,lazy:r=!0,onNonLazyError:i=console.error,lazyCloseTimeout:l=0,keepAlive:c=0,disablePong:d,connectionAckWaitTimeout:g=0,retryAttempts:f=5,retryWait:m=async function(e){let o=1e3;for(let n=0;n<e;n++)o*=2;await new Promise((e=>setTimeout(e,o+Math.floor(2700*Math.random()+300))))},isFatalConnectionProblem:C=(e=>!y(e)),on:b,webSocketImpl:w,generateID:T=function(){return"xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx".replace(/[xy]/g,(e=>{const o=16*Math.random()|0;return("x"==e?o:3&o|8).toString(16)}))},jsonMessageReplacer:x,jsonMessageReviver:v}=o;let M;if(w){if(!("function"==typeof(S=w)&&"constructor"in S&&"CLOSED"in S&&"CLOSING"in S&&"CONNECTING"in S&&"OPEN"in S))throw new Error("Invalid WebSocket implementation provided");M=w}else"undefined"!=typeof WebSocket?M=WebSocket:"undefined"!=typeof global?M=global.WebSocket||global.MozWebSocket:"undefined"!=typeof window&&(M=window.WebSocket||window.MozWebSocket);var S;if(!M)throw new Error("WebSocket implementation missing; on Node you can `import WebSocket from 'ws';` and pass `webSocketImpl: WebSocket` to `createClient`");const h=M,E=(()=>{const e=(()=>{const e={};return{on:(o,n)=>(e[o]=n,()=>{delete e[o]}),emit(o){var n;"id"in o&&(null===(n=e[o.id])||void 0===n||n.call(e,o))}}})(),o={connecting:(null==b?void 0:b.connecting)?[b.connecting]:[],opened:(null==b?void 0:b.opened)?[b.opened]:[],connected:(null==b?void 0:b.connected)?[b.connected]:[],ping:(null==b?void 0:b.ping)?[b.ping]:[],pong:(null==b?void 0:b.pong)?[b.pong]:[],message:(null==b?void 0:b.message)?[e.emit,b.message]:[e.emit],closed:(null==b?void 0:b.closed)?[b.closed]:[],error:(null==b?void 0:b.error)?[b.error]:[]};return{onMessage:e.on,on(e,n){const t=o[e];return t.push(n),()=>{t.splice(t.indexOf(n),1)}},emit(e,...n){for(const t of[...o[e]])t(...n)}}})();function P(e){const o=[E.on("error",(n=>{o.forEach((e=>e())),e(n)})),E.on("closed",(n=>{o.forEach((e=>e())),e(n)}))]}let N,I=0,k=!1,A=0,O=!1;async function R(){const[o,r]=await(null!=N?N:N=new Promise(((o,r)=>(async()=>{if(k){if(await m(A),!I)return N=void 0,r({code:1e3,reason:"All Subscriptions Gone"});A++}E.emit("connecting");const i=new h("function"==typeof n?await n():n,s);let l,f;function C(){isFinite(c)&&c>0&&(clearTimeout(f),f=setTimeout((()=>{i.readyState===h.OPEN&&(i.send(u({type:e.MessageType.Ping})),E.emit("ping",!1,void 0))}),c))}P((e=>{N=void 0,clearTimeout(l),clearTimeout(f),r(e),y(e)&&4499===e.code&&(i.close(4499,"Terminated"),i.onerror=null,i.onclose=null)})),i.onerror=e=>E.emit("error",e),i.onclose=e=>E.emit("closed",e),i.onopen=async()=>{try{E.emit("opened",i);const o="function"==typeof t?await t():t;if(i.readyState!==h.OPEN)return;i.send(u(o?{type:e.MessageType.ConnectionInit,payload:o}:{type:e.MessageType.ConnectionInit},x)),isFinite(g)&&g>0&&(l=setTimeout((()=>{i.close(e.CloseCode.ConnectionAcknowledgementTimeout,"Connection acknowledgement timeout")}),g)),C()}catch(o){E.emit("error",o),i.close(e.CloseCode.InternalClientError,a(o instanceof Error?o.message:new Error(o).message,"Internal client error"))}};let b=!1;i.onmessage=({data:n})=>{try{const t=p(n,v);if(E.emit("message",t),"ping"===t.type||"pong"===t.type)return E.emit(t.type,!0,t.payload),void("pong"===t.type?C():d||(i.send(u(t.payload?{type:e.MessageType.Pong,payload:t.payload}:{type:e.MessageType.Pong})),E.emit("pong",!1,t.payload)));if(b)return;if(t.type!==e.MessageType.ConnectionAck)throw new Error(`First message cannot be of type ${t.type}`);clearTimeout(l),b=!0,E.emit("connected",i,t.payload),k=!1,A=0,o([i,new Promise(((e,o)=>P(o)))])}catch(o){i.onmessage=null,E.emit("error",o),i.close(e.CloseCode.BadResponse,a(o instanceof Error?o.message:new Error(o).message,"Bad response"))}}})())));o.readyState===h.CLOSING&&await r;let i=()=>{};const f=new Promise((e=>i=e));return[o,i,Promise.race([f.then((()=>{if(!I){const e=()=>o.close(1e3,"Normal Closure");isFinite(l)&&l>0?setTimeout((()=>{I||o.readyState!==h.OPEN||e()}),l):e()}})),r])]}function W(o){if(y(o)&&(n=o.code,![1e3,1001,1006,1005,1012,1013,1013].includes(n)&&n>=1e3&&n<=1999||[e.CloseCode.InternalServerError,e.CloseCode.InternalClientError,e.CloseCode.BadRequest,e.CloseCode.BadResponse,e.CloseCode.Unauthorized,e.CloseCode.SubprotocolNotAcceptable,e.CloseCode.SubscriberAlreadyExists,e.CloseCode.TooManyInitialisationRequests].includes(o.code)))throw o;var n;if(O)return!1;if(y(o)&&1e3===o.code)return I>0;if(!f||A>=f)throw o;if(C(o))throw o;return k=!0}return r||(async()=>{for(I++;;)try{const[,,e]=await R();await e}catch(e){try{if(!W(e))return}catch(e){return null==i?void 0:i(e)}}})(),{on:E.on,subscribe(o,n){const t=T();let r=!1,i=!1,a=()=>{I--,r=!0};return(async()=>{for(I++;;)try{const[s,l,c]=await R();if(r)return l();const d=E.onMessage(t,(o=>{switch(o.type){case e.MessageType.Next:return void n.next(o.payload);case e.MessageType.Error:return i=!0,r=!0,n.error(o.payload),void a();case e.MessageType.Complete:return r=!0,void a()}}));return s.send(u({id:t,type:e.MessageType.Subscribe,payload:o},x)),a=()=>{r||s.readyState!==h.OPEN||s.send(u({id:t,type:e.MessageType.Complete},x)),I--,r=!0,l()},void await c.finally(d)}catch(e){if(!W(e))return}})().then((()=>{i||n.complete()})).catch((e=>{n.error(e)})),()=>{r||a()}},async dispose(){if(O=!0,N){const[e]=await N;e.close(1e3,"Normal Closure")}},terminate(){N&&E.emit("closed",{code:4499,reason:"Terminated",wasClean:!1})}}},e.isMessage=d,e.parseMessage=p,e.stringifyMessage=u,Object.defineProperty(e,"__esModule",{value:!0})}));

Sorry, the diff of this file is not supported yet

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