graphql-ws
Advanced tools
Comparing version 1.11.0 to 1.12.0
@@ -0,1 +1,13 @@ | ||
# [1.12.0](https://github.com/enisdenjo/graphql-ws/compare/v1.11.0...v1.12.0) (2020-11-07) | ||
### Bug Fixes | ||
* **client:** Close with error message during connecting issues ([f8ecdd7](https://github.com/enisdenjo/graphql-ws/commit/f8ecdd78e200a6a752ec1e72fb14d83e6103dd02)) | ||
### Features | ||
* Send optional payload with the `ConnectionAck` message ([#60](https://github.com/enisdenjo/graphql-ws/issues/60)) ([1327e77](https://github.com/enisdenjo/graphql-ws/commit/1327e7735fc52f8318644b0f4cec86d3288a0e68)) | ||
# [1.11.0](https://github.com/enisdenjo/graphql-ws/compare/v1.10.0...v1.11.0) (2020-11-04) | ||
@@ -2,0 +14,0 @@ |
@@ -13,7 +13,10 @@ /** | ||
/** | ||
* The argument is actually the `WebSocket`, but to avoid bundling DOM typings | ||
* because the client can run in Node env too, you should assert | ||
* the websocket type during implementation. | ||
* The first argument is actually the `WebSocket`, but to avoid | ||
* bundling DOM typings because the client can run in Node env too, | ||
* you should assert the websocket type during implementation. | ||
* | ||
* Also, the second argument is the optional payload that the server may | ||
* send through the `ConnectionAck` message. | ||
*/ | ||
export declare type EventConnectedListener = (socket: unknown) => void; | ||
export declare type EventConnectedListener = (socket: unknown, payload?: Record<string, unknown>) => void; | ||
export declare type EventConnectingListener = () => void; | ||
@@ -20,0 +23,0 @@ /** |
@@ -67,6 +67,6 @@ "use strict"; | ||
emit(event, ...args) { | ||
listeners[event].forEach((listener) => { | ||
for (const listener of listeners[event]) { | ||
// @ts-expect-error: The args should fit | ||
listener(...args); | ||
}); | ||
} | ||
}, | ||
@@ -184,7 +184,7 @@ reset() { | ||
state = Object.assign(Object.assign({}, state), { acknowledged: true, socket, tries: 0 }); | ||
emitter.emit('connected', socket); // connected = socket opened + acknowledged | ||
emitter.emit('connected', socket, message.payload); // connected = socket opened + acknowledged | ||
return resolve(); | ||
} | ||
catch (err) { | ||
socket.close(4400, err); | ||
socket.close(4400, err instanceof Error ? err.message : new Error(err).message); | ||
} | ||
@@ -191,0 +191,0 @@ }; |
@@ -22,2 +22,3 @@ /** | ||
readonly type: MessageType.ConnectionAck; | ||
readonly payload?: Record<string, unknown>; | ||
} | ||
@@ -24,0 +25,0 @@ export interface SubscribeMessage { |
@@ -35,3 +35,6 @@ "use strict"; | ||
case MessageType.ConnectionAck: | ||
return true; | ||
// the connection ack message can have optional payload object too | ||
return (!utils_1.hasOwnProperty(val, 'payload') || | ||
val.payload === undefined || | ||
utils_1.isObject(val.payload)); | ||
case MessageType.Subscribe: | ||
@@ -38,0 +41,0 @@ return (utils_1.hasOwnStringProperty(val, 'id') && |
@@ -117,2 +117,7 @@ /** | ||
* | ||
* - Returning a `Record` from the callback will | ||
* allow the client to connect and pass the returned | ||
* value to the client through the optional `payload` | ||
* field in the `ConnectionAck` message. | ||
* | ||
* Throwing an error from within this function will | ||
@@ -122,3 +127,3 @@ * close the socket with the `Error` message | ||
*/ | ||
onConnect?: (ctx: Context) => Promise<boolean | void> | boolean | void; | ||
onConnect?: (ctx: Context) => Promise<Record<string, unknown> | boolean | void> | Record<string, unknown> | boolean | void; | ||
/** | ||
@@ -125,0 +130,0 @@ * The subscribe callback executed right after |
@@ -161,11 +161,14 @@ "use strict"; | ||
} | ||
if (onConnect) { | ||
const permitted = await onConnect(ctx); | ||
if (permitted === false) { | ||
return ctx.socket.close(4403, 'Forbidden'); | ||
const permittedOrPayload = await (onConnect === null || onConnect === void 0 ? void 0 : onConnect(ctx)); | ||
if (permittedOrPayload === false) { | ||
return ctx.socket.close(4403, 'Forbidden'); | ||
} | ||
await sendMessage(ctx, utils_1.isObject(permittedOrPayload) | ||
? { | ||
type: message_1.MessageType.ConnectionAck, | ||
payload: permittedOrPayload, | ||
} | ||
} | ||
await sendMessage(ctx, { | ||
type: message_1.MessageType.ConnectionAck, | ||
}); | ||
: { | ||
type: message_1.MessageType.ConnectionAck, | ||
}); | ||
ctx.acknowledged = true; | ||
@@ -172,0 +175,0 @@ break; |
@@ -13,7 +13,10 @@ /** | ||
/** | ||
* The argument is actually the `WebSocket`, but to avoid bundling DOM typings | ||
* because the client can run in Node env too, you should assert | ||
* the websocket type during implementation. | ||
* The first argument is actually the `WebSocket`, but to avoid | ||
* bundling DOM typings because the client can run in Node env too, | ||
* you should assert the websocket type during implementation. | ||
* | ||
* Also, the second argument is the optional payload that the server may | ||
* send through the `ConnectionAck` message. | ||
*/ | ||
export declare type EventConnectedListener = (socket: unknown) => void; | ||
export declare type EventConnectedListener = (socket: unknown, payload?: Record<string, unknown>) => void; | ||
export declare type EventConnectingListener = () => void; | ||
@@ -20,0 +23,0 @@ /** |
@@ -64,6 +64,6 @@ /** | ||
emit(event, ...args) { | ||
listeners[event].forEach((listener) => { | ||
for (const listener of listeners[event]) { | ||
// @ts-expect-error: The args should fit | ||
listener(...args); | ||
}); | ||
} | ||
}, | ||
@@ -181,7 +181,7 @@ reset() { | ||
state = Object.assign(Object.assign({}, state), { acknowledged: true, socket, tries: 0 }); | ||
emitter.emit('connected', socket); // connected = socket opened + acknowledged | ||
emitter.emit('connected', socket, message.payload); // connected = socket opened + acknowledged | ||
return resolve(); | ||
} | ||
catch (err) { | ||
socket.close(4400, err); | ||
socket.close(4400, err instanceof Error ? err.message : new Error(err).message); | ||
} | ||
@@ -188,0 +188,0 @@ }; |
@@ -22,2 +22,3 @@ /** | ||
readonly type: MessageType.ConnectionAck; | ||
readonly payload?: Record<string, unknown>; | ||
} | ||
@@ -24,0 +25,0 @@ export interface SubscribeMessage { |
@@ -32,3 +32,6 @@ /** | ||
case MessageType.ConnectionAck: | ||
return true; | ||
// the connection ack message can have optional payload object too | ||
return (!hasOwnProperty(val, 'payload') || | ||
val.payload === undefined || | ||
isObject(val.payload)); | ||
case MessageType.Subscribe: | ||
@@ -35,0 +38,0 @@ return (hasOwnStringProperty(val, 'id') && |
@@ -117,2 +117,7 @@ /** | ||
* | ||
* - Returning a `Record` from the callback will | ||
* allow the client to connect and pass the returned | ||
* value to the client through the optional `payload` | ||
* field in the `ConnectionAck` message. | ||
* | ||
* Throwing an error from within this function will | ||
@@ -122,3 +127,3 @@ * close the socket with the `Error` message | ||
*/ | ||
onConnect?: (ctx: Context) => Promise<boolean | void> | boolean | void; | ||
onConnect?: (ctx: Context) => Promise<Record<string, unknown> | boolean | void> | Record<string, unknown> | boolean | void; | ||
/** | ||
@@ -125,0 +130,0 @@ * The subscribe callback executed right after |
@@ -139,11 +139,14 @@ /** | ||
} | ||
if (onConnect) { | ||
const permitted = await onConnect(ctx); | ||
if (permitted === false) { | ||
return ctx.socket.close(4403, 'Forbidden'); | ||
const permittedOrPayload = await (onConnect === null || onConnect === void 0 ? void 0 : onConnect(ctx)); | ||
if (permittedOrPayload === false) { | ||
return ctx.socket.close(4403, 'Forbidden'); | ||
} | ||
await sendMessage(ctx, isObject(permittedOrPayload) | ||
? { | ||
type: MessageType.ConnectionAck, | ||
payload: permittedOrPayload, | ||
} | ||
} | ||
await sendMessage(ctx, { | ||
type: MessageType.ConnectionAck, | ||
}); | ||
: { | ||
type: MessageType.ConnectionAck, | ||
}); | ||
ctx.acknowledged = true; | ||
@@ -150,0 +153,0 @@ break; |
{ | ||
"name": "graphql-ws", | ||
"version": "1.11.0", | ||
"version": "1.12.0", | ||
"description": "Coherent, zero-dependency, lazy, simple, GraphQL over WebSocket Protocol compliant server and client", | ||
@@ -5,0 +5,0 @@ "keywords": [ |
@@ -48,5 +48,8 @@ # GraphQL over WebSocket Protocol | ||
The server can use the optional `payload` field to transfer additional details about the connection. | ||
```typescript | ||
interface ConnectionAckMessage { | ||
type: 'connection_ack'; | ||
payload?: Record<string, unknown>; | ||
} | ||
@@ -53,0 +56,0 @@ ``` |
132
README.md
@@ -143,3 +143,3 @@ <div align="center"> | ||
async function execute<T>(payload: SubscribePayload) { | ||
return new Promise((resolve, reject) => { | ||
return new Promise<T>((resolve, reject) => { | ||
let result: T; | ||
@@ -171,2 +171,70 @@ client.subscribe<T>(payload, { | ||
<details> | ||
<summary>Client usage with <a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Symbol/asyncIterator">AsyncIterator</a></summary> | ||
```ts | ||
import { createClient, SubscribePayload } from 'graphql-ws'; | ||
const client = createClient({ | ||
url: 'wss://iterators.ftw/graphql', | ||
}); | ||
function subscribe<T>(payload: SubscribePayload): AsyncIterableIterator<T> { | ||
let deferred: { | ||
resolve: (done: boolean) => void; | ||
reject: (err: unknown) => void; | ||
} | null = null; | ||
const pending: T[] = []; | ||
let throwMe: unknown = null, | ||
done = false; | ||
const dispose = client.subscribe<T>(payload, { | ||
next: (data) => { | ||
pending.push(data); | ||
deferred?.resolve(false); | ||
}, | ||
error: (err) => { | ||
throwMe = err; | ||
deferred?.reject(throwMe); | ||
}, | ||
complete: () => { | ||
done = true; | ||
deferred?.resolve(true); | ||
}, | ||
}); | ||
return { | ||
[Symbol.asyncIterator]() { | ||
return this; | ||
}, | ||
async next() { | ||
if (done) return { done: true, value: undefined }; | ||
if (throwMe) throw throwMe; | ||
if (pending.length) return { value: pending.shift()! }; | ||
return (await new Promise<boolean>( | ||
(resolve, reject) => (deferred = { resolve, reject }), | ||
)) | ||
? { done: true, value: undefined } | ||
: { value: pending.shift()! }; | ||
}, | ||
async return() { | ||
dispose(); | ||
return { done: true, value: undefined }; | ||
}, | ||
}; | ||
} | ||
(async () => { | ||
const subscription = subscribe({ | ||
query: 'subscription { greetings }', | ||
}); | ||
// subscription.return() to dispose | ||
for await (const result of subscription) { | ||
// next = result = { data: { greetings: 5x } } | ||
} | ||
// complete | ||
})(); | ||
``` | ||
</details> | ||
<details> | ||
<summary>Client usage with <a href="https://github.com/tc39/proposal-observable">Observable</a></summary> | ||
@@ -211,2 +279,3 @@ | ||
```ts | ||
import { GraphQLError } from 'graphql'; | ||
import { | ||
@@ -259,4 +328,9 @@ Network, | ||
} else { | ||
// GraphQLError[] | ||
sink.error(new Error(err.map(({ message }) => message).join(', '))); | ||
sink.error( | ||
new Error( | ||
(err as GraphQLError[]) | ||
.map(({ message }) => message) | ||
.join(', '), | ||
), | ||
); | ||
} | ||
@@ -275,2 +349,35 @@ }, | ||
<details> | ||
<summary>Client usage with <a href="https://formidable.com/open-source/urql/">urql</a></summary> | ||
```ts | ||
import { createClient, defaultExchanges, subscriptionExchange } from 'urql'; | ||
import { createClient as createWSClient } from 'graphql-ws'; | ||
const wsClient = createWSClient({ | ||
url: 'wss://its.urql/graphql', | ||
}); | ||
const client = createClient({ | ||
url: '/graphql', | ||
exchanges: [ | ||
...defaultExchanges, | ||
subscriptionExchange({ | ||
forwardSubscription(operation) { | ||
return { | ||
subscribe: (sink) => { | ||
const dispose = wsClient.subscribe(operation, sink); | ||
return { | ||
unsubscribe: dispose, | ||
}; | ||
}, | ||
}; | ||
}, | ||
}), | ||
], | ||
}); | ||
``` | ||
</details> | ||
<details> | ||
<summary>Client usage with <a href="https://www.apollographql.com">Apollo</a></summary> | ||
@@ -280,3 +387,3 @@ | ||
import { ApolloLink, Operation, FetchResult, Observable } from '@apollo/client'; | ||
import { print } from 'graphql'; | ||
import { print, GraphQLError } from 'graphql'; | ||
import { createClient, ClientOptions, Client } from 'graphql-ws'; | ||
@@ -311,5 +418,8 @@ | ||
} else { | ||
// GraphQLError[] | ||
sink.error( | ||
new Error(err.map(({ message }) => message).join(', ')), | ||
new Error( | ||
(err as GraphQLError[]) | ||
.map(({ message }) => message) | ||
.join(', '), | ||
), | ||
); | ||
@@ -356,9 +466,7 @@ } | ||
<script type="text/javascript"> | ||
(function () { | ||
const client = graphqlWs.createClient({ | ||
url: 'wss://umdfor.the/win/graphql', | ||
}); | ||
const client = graphqlWs.createClient({ | ||
url: 'wss://umdfor.the/win/graphql', | ||
}); | ||
// consider other recipes for usage inspiration | ||
})(); | ||
// consider other recipes for usage inspiration | ||
</script> | ||
@@ -365,0 +473,0 @@ </body> |
@@ -67,3 +67,6 @@ (function (global, factory) { | ||
case MessageType.ConnectionAck: | ||
return true; | ||
// the connection ack message can have optional payload object too | ||
return (!hasOwnProperty(val, 'payload') || | ||
val.payload === undefined || | ||
isObject(val.payload)); | ||
case MessageType.Subscribe: | ||
@@ -179,6 +182,6 @@ return (hasOwnStringProperty(val, 'id') && | ||
emit(event, ...args) { | ||
listeners[event].forEach((listener) => { | ||
for (const listener of listeners[event]) { | ||
// @ts-expect-error: The args should fit | ||
listener(...args); | ||
}); | ||
} | ||
}, | ||
@@ -296,7 +299,7 @@ reset() { | ||
state = Object.assign(Object.assign({}, state), { acknowledged: true, socket, tries: 0 }); | ||
emitter.emit('connected', socket); // connected = socket opened + acknowledged | ||
emitter.emit('connected', socket, message.payload); // connected = socket opened + acknowledged | ||
return resolve(); | ||
} | ||
catch (err) { | ||
socket.close(4400, err); | ||
socket.close(4400, err instanceof Error ? err.message : new Error(err).message); | ||
} | ||
@@ -303,0 +306,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:return!o(e,"payload")||void 0===e.payload||n(e.payload);case i.ConnectionAck:return!0;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")&&(r(e.payload,"data")||r(e.payload,"errors"));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 u(e){return n(e)&&"code"in e&&"reason"in e&&"wasClean"in 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:n,lazy:o=!0,retryAttempts:r=5,retryTimeout:c=3e3,on:s,webSocketImpl:d,generateID:f=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 p;if(d){if(!("function"==typeof(y=d)&&"constructor"in y&&"CLOSED"in y&&"CLOSING"in y&&"CONNECTING"in y&&"OPEN"in y))throw new Error("Invalid WebSocket implementation provided");p=d}else"undefined"!=typeof WebSocket?p=WebSocket:"undefined"!=typeof global?p=global.WebSocket||global.MozWebSocket:"undefined"!=typeof window&&(p=window.WebSocket||window.MozWebSocket);var y;if(!p)throw new Error("WebSocket implementation missing");const m=p,w=(()=>{const e={connecting:(null==s?void 0:s.connecting)?[s.connecting]:[],connected:(null==s?void 0:s.connected)?[s.connected]:[],closed:(null==s?void 0:s.closed)?[s.closed]:[]};return{on(t,n){const o=e[t];return o.push(n),()=>{o.splice(o.indexOf(n),1)}},emit(t,...n){e[t].forEach((e=>{e(...n)}))},reset(){Object.keys(e).forEach((t=>{e[t]=[]}))}}})();let k,b,v={socket:null,acknowledged:!1,locks:0,tries:0};async function g(e,o=0){if(o>10)throw new Error("Kept trying to connect but the socket never settled.");if(v.socket)switch(v.socket.readyState){case m.OPEN:return v.acknowledged?[v.socket,t=>new Promise(((n,o)=>{if(!v.socket)return o(new Error("Socket closed unexpectedly"));if(v.socket.readyState===m.CLOSED)return o(new Error("Socket has already been closed"));function r(e){var t;return v.locks--,null===(t=v.socket)||void 0===t||t.removeEventListener("close",r),o(e)}v.locks++,v.socket.addEventListener("close",r),e.current=()=>{var e,o;return null==t||t(),v.locks--,v.locks||null===(e=v.socket)||void 0===e||e.close(1e3,"Normal Closure"),null===(o=v.socket)||void 0===o||o.removeEventListener("close",r),n()}}))]:(await new Promise((e=>setTimeout(e,300))),g(e,o+1));case m.CONNECTING:return await new Promise((e=>setTimeout(e,300))),g(e,o+1);case m.CLOSED:break;case m.CLOSING:return await new Promise((e=>setTimeout(e,300))),g(e,o+1);default:throw new Error("Impossible ready state "+v.socket.readyState)}const r=new m(t,"graphql-transport-ws");return v=Object.assign(Object.assign({},v),{acknowledged:!1,socket:r,tries:v.tries+1}),w.emit("connecting"),await new Promise(((t,o)=>{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),v=Object.assign(Object.assign({},v),{acknowledged:!1,socket:null}),w.emit("closed",e),o(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),v=Object.assign(Object.assign({},v),{acknowledged:!0,socket:r,tries:0}),w.emit("connected",r),t()}catch(e){r.close(4400,e)}},r.onopen=()=>{r.onopen=null,c?r.close(3499,"Client cancelled the socket before connecting"):r.send(l({type:i.ConnectionInit,payload:"function"==typeof n?n():n}))}})),[r,t=>new Promise(((n,o)=>{if(r.readyState===m.CLOSED)return o(new Error("Socket has already been closed"));function c(e){return v.locks--,r.removeEventListener("close",c),o(e)}v.locks++,r.addEventListener("close",c),e.current=()=>(null==t||t(),v.locks--,v.locks||r.close(1e3,"Normal Closure"),r.removeEventListener("close",c),n())}))]}return o||(async()=>{for(;;)try{const[,e]=await g({current:null});return void await e()}catch(e){if(!u(e))throw e;if(1e3===e.code)return;if(!r||v.tries>r)return;await new Promise((e=>setTimeout(e,c)))}})(),{on:w.on,subscribe(e,t){const n=f(),o={current:null},s=({data:e})=>{const r=function(e){return e!==k&&(b=a(e),k=e),b}(e);switch(r.type){case i.Next:return void(r.id===n&&t.next(r.payload));case i.Error:return void(r.id===n&&(t.error(r.payload),o.current()));case i.Complete:return void(r.id===n&&o.current())}};return(async()=>{for(;;)try{const[t,r]=await g(o);return t.addEventListener("message",s),t.send(l({id:n,type:i.Subscribe,payload:e})),await r((()=>{t.send(l({id:n,type:i.Complete}))})),void t.removeEventListener("message",s)}catch(e){if(!u(e))throw e;if(1e3===e.code)return;if(3499===e.code)return;if(!r||v.tries>r)throw e;await new Promise((e=>setTimeout(e,c)))}})().catch(t.error).then(t.complete).finally((()=>o.current=null)),()=>{var e;null===(e=o.current)||void 0===e||e.call(o)}},dispose(){var e;null===(e=v.socket)||void 0===e||e.close(1e3,"Normal Closure"),w.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 s;function i(e){if(n(e)){if(!c(e,"type"))return!1;switch(e.type){case s.ConnectionInit:case s.ConnectionAck:return!o(e,"payload")||void 0===e.payload||n(e.payload);case s.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 s.Next:return c(e,"id")&&r(e,"payload")&&(r(e.payload,"data")||r(e.payload,"errors"));case s.Error:return c(e,"id")&&(t=e.payload,Array.isArray(t)&&t.length>0&&t.every((e=>"message"in e)));case s.Complete:return c(e,"id");default:return!1}}var t;return!1}function a(e){if(i(e))return e;if("string"!=typeof e)throw new Error("Message not parsable");const t=JSON.parse(e);if(!i(t))throw new Error("Invalid message");return t}function l(e){if(!i(e))throw new Error("Cannot stringify invalid message");return JSON.stringify(e)}function d(e){return n(e)&&"code"in e&&"reason"in e&&"wasClean"in e}!function(e){e.ConnectionInit="connection_init",e.ConnectionAck="connection_ack",e.Subscribe="subscribe",e.Next="next",e.Error="error",e.Complete="complete"}(s||(s={})),e.createClient=function(e){const{url:t,connectionParams:n,lazy:o=!0,retryAttempts:r=5,retryTimeout:c=3e3,on:i,webSocketImpl:u,generateID:f=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 p;if(u){if(!("function"==typeof(y=u)&&"constructor"in y&&"CLOSED"in y&&"CLOSING"in y&&"CONNECTING"in y&&"OPEN"in y))throw new Error("Invalid WebSocket implementation provided");p=u}else"undefined"!=typeof WebSocket?p=WebSocket:"undefined"!=typeof global?p=global.WebSocket||global.MozWebSocket:"undefined"!=typeof window&&(p=window.WebSocket||window.MozWebSocket);var y;if(!p)throw new Error("WebSocket implementation missing");const m=p,w=(()=>{const e={connecting:(null==i?void 0:i.connecting)?[i.connecting]:[],connected:(null==i?void 0:i.connected)?[i.connected]:[],closed:(null==i?void 0:i.closed)?[i.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 k,b,v={socket:null,acknowledged:!1,locks:0,tries:0};async function g(e,o=0){if(o>10)throw new Error("Kept trying to connect but the socket never settled.");if(v.socket)switch(v.socket.readyState){case m.OPEN:return v.acknowledged?[v.socket,t=>new Promise(((n,o)=>{if(!v.socket)return o(new Error("Socket closed unexpectedly"));if(v.socket.readyState===m.CLOSED)return o(new Error("Socket has already been closed"));function r(e){var t;return v.locks--,null===(t=v.socket)||void 0===t||t.removeEventListener("close",r),o(e)}v.locks++,v.socket.addEventListener("close",r),e.current=()=>{var e,o;return null==t||t(),v.locks--,v.locks||null===(e=v.socket)||void 0===e||e.close(1e3,"Normal Closure"),null===(o=v.socket)||void 0===o||o.removeEventListener("close",r),n()}}))]:(await new Promise((e=>setTimeout(e,300))),g(e,o+1));case m.CONNECTING:return await new Promise((e=>setTimeout(e,300))),g(e,o+1);case m.CLOSED:break;case m.CLOSING:return await new Promise((e=>setTimeout(e,300))),g(e,o+1);default:throw new Error("Impossible ready state "+v.socket.readyState)}const r=new m(t,"graphql-transport-ws");return v=Object.assign(Object.assign({},v),{acknowledged:!1,socket:r,tries:v.tries+1}),w.emit("connecting"),await new Promise(((t,o)=>{let c=!1;e.current=()=>c=!0;const i=setTimeout((()=>{r.close(3408,"Waited 5 seconds but socket connect never settled")}),5e3);r.onclose=e=>(r.onclose=null,clearTimeout(i),v=Object.assign(Object.assign({},v),{acknowledged:!1,socket:null}),w.emit("closed",e),o(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!==s.ConnectionAck)throw new Error("First message cannot be of type "+n.type);return clearTimeout(i),v=Object.assign(Object.assign({},v),{acknowledged:!0,socket:r,tries:0}),w.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"):r.send(l({type:s.ConnectionInit,payload:"function"==typeof n?n():n}))}})),[r,t=>new Promise(((n,o)=>{if(r.readyState===m.CLOSED)return o(new Error("Socket has already been closed"));function c(e){return v.locks--,r.removeEventListener("close",c),o(e)}v.locks++,r.addEventListener("close",c),e.current=()=>(null==t||t(),v.locks--,v.locks||r.close(1e3,"Normal Closure"),r.removeEventListener("close",c),n())}))]}return o||(async()=>{for(;;)try{const[,e]=await g({current:null});return void await e()}catch(e){if(!d(e))throw e;if(1e3===e.code)return;if(!r||v.tries>r)return;await new Promise((e=>setTimeout(e,c)))}})(),{on:w.on,subscribe(e,t){const n=f(),o={current:null},i=({data:e})=>{const r=function(e){return e!==k&&(b=a(e),k=e),b}(e);switch(r.type){case s.Next:return void(r.id===n&&t.next(r.payload));case s.Error:return void(r.id===n&&(t.error(r.payload),o.current()));case s.Complete:return void(r.id===n&&o.current())}};return(async()=>{for(;;)try{const[t,r]=await g(o);return t.addEventListener("message",i),t.send(l({id:n,type:s.Subscribe,payload:e})),await r((()=>{t.send(l({id:n,type:s.Complete}))})),void t.removeEventListener("message",i)}catch(e){if(!d(e))throw e;if(1e3===e.code)return;if(3499===e.code)return;if(!r||v.tries>r)throw e;await new Promise((e=>setTimeout(e,c)))}})().catch(t.error).then(t.complete).finally((()=>o.current=null)),()=>{var e;null===(e=o.current)||void 0===e||e.call(o)}},dispose(){var e;null===(e=v.socket)||void 0===e||e.close(1e3,"Normal Closure"),w.reset()}}},Object.defineProperty(e,"__esModule",{value:!0})})); |
Sorry, the diff of this file is not supported yet
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
Major refactor
Supply chain riskPackage has recently undergone a major refactor. It may be unstable or indicate significant internal changes. Use caution when updating to versions that include significant changes.
Found 1 instance in 1 package
200463
3189
791
0