@webiny/app-websockets 0.0.0-unstable.3bc8100a7f

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.
Files changed (60) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +12 -0
  3. package/WebsocketsContextProvider.d.ts +8 -0
  4. package/WebsocketsContextProvider.js +163 -0
  5. package/WebsocketsContextProvider.js.map +1 -0
  6. package/domain/WebsocketsAction.d.ts +8 -0
  7. package/domain/WebsocketsAction.js +28 -0
  8. package/domain/WebsocketsAction.js.map +1 -0
  9. package/domain/WebsocketsActions.d.ts +16 -0
  10. package/domain/WebsocketsActions.js +84 -0
  11. package/domain/WebsocketsActions.js.map +1 -0
  12. package/domain/WebsocketsConnection.d.ts +42 -0
  13. package/domain/WebsocketsConnection.js +118 -0
  14. package/domain/WebsocketsConnection.js.map +1 -0
  15. package/domain/WebsocketsManager.d.ts +15 -0
  16. package/domain/WebsocketsManager.js +37 -0
  17. package/domain/WebsocketsManager.js.map +1 -0
  18. package/domain/WebsocketsSubscriptionManager.d.ts +15 -0
  19. package/domain/WebsocketsSubscriptionManager.js +73 -0
  20. package/domain/WebsocketsSubscriptionManager.js.map +1 -0
  21. package/domain/abstractions/IWebsocketsAction.d.ts +25 -0
  22. package/domain/abstractions/IWebsocketsAction.js +3 -0
  23. package/domain/abstractions/IWebsocketsAction.js.map +1 -0
  24. package/domain/abstractions/IWebsocketsActions.d.ts +11 -0
  25. package/domain/abstractions/IWebsocketsActions.js +3 -0
  26. package/domain/abstractions/IWebsocketsActions.js.map +1 -0
  27. package/domain/abstractions/IWebsocketsConnection.d.ts +20 -0
  28. package/domain/abstractions/IWebsocketsConnection.js +9 -0
  29. package/domain/abstractions/IWebsocketsConnection.js.map +1 -0
  30. package/domain/abstractions/IWebsocketsManager.d.ts +40 -0
  31. package/domain/abstractions/IWebsocketsManager.js +3 -0
  32. package/domain/abstractions/IWebsocketsManager.js.map +1 -0
  33. package/domain/abstractions/IWebsocketsSubscriptionManager.d.ts +30 -0
  34. package/domain/abstractions/IWebsocketsSubscriptionManager.js +3 -0
  35. package/domain/abstractions/IWebsocketsSubscriptionManager.js.map +1 -0
  36. package/domain/abstractions/types.d.ts +24 -0
  37. package/domain/abstractions/types.js +21 -0
  38. package/domain/abstractions/types.js.map +1 -0
  39. package/domain/index.d.ts +5 -0
  40. package/domain/index.js +7 -0
  41. package/domain/index.js.map +1 -0
  42. package/domain/types.d.ts +6 -0
  43. package/domain/types.js +8 -0
  44. package/domain/types.js.map +1 -0
  45. package/hooks/index.d.ts +1 -0
  46. package/hooks/index.js +3 -0
  47. package/hooks/index.js.map +1 -0
  48. package/hooks/useWebsockets.d.ts +2 -0
  49. package/hooks/useWebsockets.js +11 -0
  50. package/hooks/useWebsockets.js.map +1 -0
  51. package/index.d.ts +7 -0
  52. package/index.js +18 -0
  53. package/index.js.map +1 -0
  54. package/package.json +38 -0
  55. package/types.d.ts +27 -0
  56. package/types.js +4 -0
  57. package/types.js.map +1 -0
  58. package/utils/getUrl.d.ts +1 -0
  59. package/utils/getUrl.js +6 -0
  60. package/utils/getUrl.js.map +1 -0
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) Webiny
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,12 @@
1
+ # @webiny/app-websockets
2
+ [![](https://img.shields.io/npm/dw/@webiny/app-websockets.svg)](https://www.npmjs.com/package/@webiny/app-websockets)
3
+ [![](https://img.shields.io/npm/v/@webiny/app-websockets.svg)](https://www.npmjs.com/package/@webiny/app-websockets)
4
+ [![code style: prettier](https://img.shields.io/badge/code_style-prettier-ff69b4.svg?style=flat-square)](https://github.com/prettier/prettier)
5
+ [![PRs Welcome](https://img.shields.io/badge/PRs-welcome-brightgreen.svg?style=flat-square)](http://makeapullrequest.com)
6
+
7
+ Exposes a simple `SocketsProvider` React provider component and enables you to quickly send socket messages via the `useSockets` React hook.
8
+
9
+ ## Install
10
+ ```
11
+ yarn add @webiny/app-websockets
12
+ ```
@@ -0,0 +1,8 @@
1
+ import React from "react";
2
+ import type { IWebsocketsContext } from "./types";
3
+ export interface IWebsocketsContextProviderProps {
4
+ loader?: React.ReactElement;
5
+ children: React.ReactNode;
6
+ }
7
+ export declare const WebsocketsContext: React.Context<IWebsocketsContext>;
8
+ export declare const WebsocketsContextProvider: (props: IWebsocketsContextProviderProps) => React.JSX.Element | null;
@@ -0,0 +1,163 @@
1
+ import React, { useCallback, useEffect, useMemo, useRef, useState } from "react";
2
+ import { useTenancy } from "@webiny/app-tenancy";
3
+ import { useI18N } from "@webiny/app-i18n";
4
+ import { useSecurity } from "@webiny/app-security";
5
+ import { WebsocketsCloseCode } from "./types";
6
+ import { createWebsocketsAction, createWebsocketsActions, createWebsocketsConnection, createWebsocketsManager, createWebsocketsSubscriptionManager } from "./domain";
7
+ import { getUrl } from "./utils/getUrl";
8
+ export const WebsocketsContext = /*#__PURE__*/React.createContext(undefined);
9
+ export const WebsocketsContextProvider = props => {
10
+ const {
11
+ tenant
12
+ } = useTenancy();
13
+ const {
14
+ getCurrentLocale
15
+ } = useI18N();
16
+ const {
17
+ getIdToken
18
+ } = useSecurity();
19
+ const locale = getCurrentLocale("default");
20
+ const socketsRef = useRef();
21
+ const [current, setCurrent] = useState({});
22
+ const getToken = useCallback(async () => {
23
+ return await getIdToken();
24
+ }, [getIdToken]);
25
+ const subscriptionManager = useMemo(() => {
26
+ const manager = createWebsocketsSubscriptionManager();
27
+ let currentIteration = 0;
28
+ manager.onClose(event => {
29
+ if (currentIteration > 5 || event.code !== WebsocketsCloseCode.GOING_AWAY) {
30
+ return;
31
+ }
32
+ currentIteration++;
33
+ setTimeout(() => {
34
+ if (!socketsRef.current) {
35
+ return;
36
+ } else if (socketsRef.current.isClosed()) {
37
+ console.log("Running auto-reconnect.");
38
+ socketsRef.current.connect();
39
+ }
40
+ }, 1000);
41
+ });
42
+ return manager;
43
+ }, []);
44
+
45
+ /**
46
+ * We need this useEffect to close the websocket connection and remove window focus event in case component is unmounted.
47
+ * This will, probably, happen only during the development phase.
48
+ *
49
+ * If we did not disconnect on component unmount, we would have a memory leak - multiple connections would be opened.
50
+ */
51
+ useEffect(() => {
52
+ /**
53
+ * We want to add a window event listener which will check if the connection is closed, and if its - it will connect again.
54
+ */
55
+ const abortController = new AbortController();
56
+ window.addEventListener("focus", () => {
57
+ if (!socketsRef.current) {
58
+ return;
59
+ } else if (socketsRef.current.isClosed()) {
60
+ console.log("Running auto-reconnect on focus.");
61
+ socketsRef.current.connect();
62
+ }
63
+ }, {
64
+ signal: abortController.signal
65
+ });
66
+ window.addEventListener("close", () => {
67
+ subscriptionManager.triggerOnClose(new CloseEvent("windowClose", {
68
+ code: WebsocketsCloseCode.GOING_AWAY,
69
+ reason: "Closing Window or Tab."
70
+ }));
71
+ }, {
72
+ signal: abortController.signal
73
+ });
74
+ return () => {
75
+ abortController.abort();
76
+ };
77
+ }, []);
78
+ useEffect(() => {
79
+ (async () => {
80
+ const token = await getToken();
81
+ if (!token || !tenant || !locale) {
82
+ return;
83
+ } else if (current.tenant === tenant && current.locale === locale) {
84
+ return;
85
+ } else if (socketsRef.current) {
86
+ await socketsRef.current.close(WebsocketsCloseCode.NORMAL, "Changing tenant/locale.");
87
+ }
88
+ const url = getUrl();
89
+ if (!url) {
90
+ console.error("Not possible to connect to the websocket without a valid URL.", {
91
+ tenant,
92
+ locale,
93
+ token
94
+ });
95
+ return;
96
+ }
97
+ socketsRef.current = createWebsocketsManager(createWebsocketsConnection({
98
+ subscriptionManager,
99
+ url,
100
+ tenant,
101
+ locale,
102
+ getToken,
103
+ protocol: ["webiny-ws-v1"]
104
+ }));
105
+ await socketsRef.current.connect();
106
+ setCurrent({
107
+ tenant,
108
+ locale
109
+ });
110
+ })();
111
+ }, [tenant, locale, subscriptionManager, getToken]);
112
+ const websocketActions = useMemo(() => {
113
+ return createWebsocketsActions({
114
+ manager: socketsRef.current,
115
+ tenant,
116
+ locale,
117
+ getToken
118
+ });
119
+ }, [socketsRef.current, tenant, locale, getToken]);
120
+ const send = useCallback(async (action, data, timeout) => {
121
+ return websocketActions.run({
122
+ action,
123
+ data,
124
+ timeout
125
+ });
126
+ }, [websocketActions]);
127
+ const createAction = useCallback(name => {
128
+ return createWebsocketsAction(websocketActions, name);
129
+ }, [websocketActions]);
130
+ const onMessage = useCallback((action, cb) => {
131
+ return socketsRef.current.onMessage(async event => {
132
+ if (event.data.action !== action) {
133
+ return;
134
+ }
135
+ cb(event.data);
136
+ });
137
+ }, [socketsRef.current]);
138
+ const onError = useCallback(cb => {
139
+ return socketsRef.current.onError(data => {
140
+ return cb(data);
141
+ });
142
+ }, [socketsRef.current]);
143
+ const onClose = useCallback(cb => {
144
+ return socketsRef.current.onClose(data => {
145
+ return cb(data);
146
+ });
147
+ }, [socketsRef.current]);
148
+ if (!socketsRef.current) {
149
+ return props.loader || null;
150
+ }
151
+ const value = {
152
+ send,
153
+ createAction,
154
+ onMessage,
155
+ onError,
156
+ onClose
157
+ };
158
+ return /*#__PURE__*/React.createElement(WebsocketsContext.Provider, Object.assign({
159
+ value: value
160
+ }, props));
161
+ };
162
+
163
+ //# sourceMappingURL=WebsocketsContextProvider.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"names":["React","useCallback","useEffect","useMemo","useRef","useState","useTenancy","useI18N","useSecurity","WebsocketsCloseCode","createWebsocketsAction","createWebsocketsActions","createWebsocketsConnection","createWebsocketsManager","createWebsocketsSubscriptionManager","getUrl","WebsocketsContext","createContext","undefined","WebsocketsContextProvider","props","tenant","getCurrentLocale","getIdToken","locale","socketsRef","current","setCurrent","getToken","subscriptionManager","manager","currentIteration","onClose","event","code","GOING_AWAY","setTimeout","isClosed","console","log","connect","abortController","AbortController","window","addEventListener","signal","triggerOnClose","CloseEvent","reason","abort","token","close","NORMAL","url","error","protocol","websocketActions","send","action","data","timeout","run","createAction","name","onMessage","cb","onError","loader","value","createElement","Provider","Object","assign"],"sources":["WebsocketsContextProvider.tsx"],"sourcesContent":["import React, { useCallback, useEffect, useMemo, useRef, useState } from \"react\";\nimport { useTenancy } from \"@webiny/app-tenancy\";\nimport { useI18N } from \"@webiny/app-i18n\";\nimport { useSecurity } from \"@webiny/app-security\";\nimport type {\n IncomingGenericData,\n IWebsocketsContext,\n IWebsocketsContextSendCallable,\n IWebsocketsManagerCloseEvent,\n IWebsocketsManagerErrorEvent\n} from \"~/types\";\nimport { WebsocketsCloseCode } from \"~/types\";\nimport {\n createWebsocketsAction,\n createWebsocketsActions,\n createWebsocketsConnection,\n createWebsocketsManager,\n createWebsocketsSubscriptionManager\n} from \"./domain\";\nimport type { IGenericData, IWebsocketsManager } from \"./domain/types\";\nimport { getUrl } from \"./utils/getUrl\";\n\nexport interface IWebsocketsContextProviderProps {\n loader?: React.ReactElement;\n children: React.ReactNode;\n}\n\nexport const WebsocketsContext = React.createContext<IWebsocketsContext>(\n undefined as unknown as IWebsocketsContext\n);\n\ninterface ICurrentData {\n tenant?: string;\n locale?: string;\n}\n\nexport const WebsocketsContextProvider = (props: IWebsocketsContextProviderProps) => {\n const { tenant } = useTenancy();\n const { getCurrentLocale } = useI18N();\n const { getIdToken } = useSecurity();\n const locale = getCurrentLocale(\"default\");\n\n const socketsRef = useRef<IWebsocketsManager>();\n\n const [current, setCurrent] = useState<ICurrentData>({});\n\n const getToken = useCallback(async () => {\n return await getIdToken();\n }, [getIdToken]);\n\n const subscriptionManager = useMemo(() => {\n const manager = createWebsocketsSubscriptionManager();\n\n let currentIteration = 0;\n manager.onClose(event => {\n if (currentIteration > 5 || event.code !== WebsocketsCloseCode.GOING_AWAY) {\n return;\n }\n currentIteration++;\n setTimeout(() => {\n if (!socketsRef.current) {\n return;\n } else if (socketsRef.current.isClosed()) {\n console.log(\"Running auto-reconnect.\");\n\n socketsRef.current.connect();\n }\n }, 1000);\n });\n\n return manager;\n }, []);\n\n /**\n * We need this useEffect to close the websocket connection and remove window focus event in case component is unmounted.\n * This will, probably, happen only during the development phase.\n *\n * If we did not disconnect on component unmount, we would have a memory leak - multiple connections would be opened.\n */\n useEffect(() => {\n /**\n * We want to add a window event listener which will check if the connection is closed, and if its - it will connect again.\n */\n const abortController = new AbortController();\n\n window.addEventListener(\n \"focus\",\n () => {\n if (!socketsRef.current) {\n return;\n } else if (socketsRef.current.isClosed()) {\n console.log(\"Running auto-reconnect on focus.\");\n socketsRef.current.connect();\n }\n },\n { signal: abortController.signal }\n );\n window.addEventListener(\n \"close\",\n () => {\n subscriptionManager.triggerOnClose(\n new CloseEvent(\"windowClose\", {\n code: WebsocketsCloseCode.GOING_AWAY,\n reason: \"Closing Window or Tab.\"\n })\n );\n },\n { signal: abortController.signal }\n );\n\n return () => {\n abortController.abort();\n };\n }, []);\n\n useEffect(() => {\n (async () => {\n const token = await getToken();\n if (!token || !tenant || !locale) {\n return;\n } else if (current.tenant === tenant && current.locale === locale) {\n return;\n } else if (socketsRef.current) {\n await socketsRef.current.close(\n WebsocketsCloseCode.NORMAL,\n \"Changing tenant/locale.\"\n );\n }\n const url = getUrl();\n\n if (!url) {\n console.error(\"Not possible to connect to the websocket without a valid URL.\", {\n tenant,\n locale,\n token\n });\n return;\n }\n\n socketsRef.current = createWebsocketsManager(\n createWebsocketsConnection({\n subscriptionManager,\n url,\n tenant,\n locale,\n getToken,\n protocol: [\"webiny-ws-v1\"]\n })\n );\n await socketsRef.current.connect();\n\n setCurrent({\n tenant,\n locale\n });\n })();\n }, [tenant, locale, subscriptionManager, getToken]);\n\n const websocketActions = useMemo(() => {\n return createWebsocketsActions({\n manager: socketsRef.current!,\n tenant,\n locale,\n getToken\n });\n }, [socketsRef.current, tenant, locale, getToken]);\n\n const send = useCallback<IWebsocketsContextSendCallable>(\n async (action, data, timeout) => {\n return websocketActions.run({\n action,\n data,\n timeout\n });\n },\n [websocketActions]\n );\n\n const createAction = useCallback(\n <T extends IGenericData = IGenericData, R extends IGenericData = IGenericData>(\n name: string\n ) => {\n return createWebsocketsAction<T, R>(websocketActions, name);\n },\n [websocketActions]\n );\n\n const onMessage = useCallback(\n <T extends IncomingGenericData = IncomingGenericData>(\n action: string,\n cb: (data: T) => void\n ) => {\n return socketsRef.current!.onMessage<T>(async event => {\n if (event.data.action !== action) {\n return;\n }\n cb(event.data);\n });\n },\n [socketsRef.current]\n );\n\n const onError = useCallback(\n (cb: (data: IWebsocketsManagerErrorEvent) => void) => {\n return socketsRef.current!.onError(data => {\n return cb(data);\n });\n },\n [socketsRef.current]\n );\n\n const onClose = useCallback(\n (cb: (data: IWebsocketsManagerCloseEvent) => void) => {\n return socketsRef.current!.onClose(data => {\n return cb(data);\n });\n },\n [socketsRef.current]\n );\n\n if (!socketsRef.current) {\n return props.loader || null;\n }\n\n const value: IWebsocketsContext = {\n send,\n createAction,\n onMessage,\n onError,\n onClose\n };\n return <WebsocketsContext.Provider value={value} {...props} />;\n};\n"],"mappings":"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","ignoreList":[]}
@@ -0,0 +1,8 @@
1
+ import type { IGenericData, IWebsocketsAction, IWebsocketsActions, IWebsocketsActionsTriggerParams } from "./types";
2
+ export declare class WebsocketsAction<T extends IGenericData = IGenericData, R extends IGenericData = IGenericData> implements IWebsocketsAction<T, R> {
3
+ private readonly actions;
4
+ private readonly name;
5
+ constructor(actions: IWebsocketsActions, name: string);
6
+ trigger(params?: IWebsocketsActionsTriggerParams<T, R>): Promise<R | null>;
7
+ }
8
+ export declare const createWebsocketsAction: <T extends IGenericData = IGenericData, R extends IGenericData = IGenericData>(actions: IWebsocketsActions, name: string) => IWebsocketsAction<T, R>;
@@ -0,0 +1,28 @@
1
+ export class WebsocketsAction {
2
+ constructor(actions, name) {
3
+ this.name = name;
4
+ this.actions = actions;
5
+ }
6
+ async trigger(params) {
7
+ const {
8
+ data,
9
+ onResponse,
10
+ timeout = 10000
11
+ } = params || {};
12
+ const promise = this.actions.run({
13
+ action: this.name,
14
+ data,
15
+ timeout: onResponse && timeout > 0 ? timeout : undefined
16
+ });
17
+ if (!onResponse) {
18
+ return null;
19
+ }
20
+ const result = await promise;
21
+ return onResponse(result);
22
+ }
23
+ }
24
+ export const createWebsocketsAction = (actions, name) => {
25
+ return new WebsocketsAction(actions, name);
26
+ };
27
+
28
+ //# sourceMappingURL=WebsocketsAction.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"names":["WebsocketsAction","constructor","actions","name","trigger","params","data","onResponse","timeout","promise","run","action","undefined","result","createWebsocketsAction"],"sources":["WebsocketsAction.ts"],"sourcesContent":["import type {\n IGenericData,\n IWebsocketsAction,\n IWebsocketsActions,\n IWebsocketsActionsTriggerParams\n} from \"./types\";\n\nexport class WebsocketsAction<\n T extends IGenericData = IGenericData,\n R extends IGenericData = IGenericData\n> implements IWebsocketsAction<T, R>\n{\n private readonly actions: IWebsocketsActions;\n private readonly name: string;\n\n public constructor(actions: IWebsocketsActions, name: string) {\n this.name = name;\n this.actions = actions;\n }\n\n public async trigger(params?: IWebsocketsActionsTriggerParams<T, R>): Promise<R | null> {\n const { data, onResponse, timeout = 10000 } = params || {};\n const promise = this.actions.run<T, R>({\n action: this.name,\n data,\n timeout: onResponse && timeout > 0 ? timeout : undefined\n });\n if (!onResponse) {\n return null;\n }\n const result = await promise;\n\n return onResponse(result);\n }\n}\n\nexport const createWebsocketsAction = <\n T extends IGenericData = IGenericData,\n R extends IGenericData = IGenericData\n>(\n actions: IWebsocketsActions,\n name: string\n): IWebsocketsAction<T, R> => {\n return new WebsocketsAction<T, R>(actions, name);\n};\n"],"mappings":"AAOA,OAAO,MAAMA,gBAAgB,CAI7B;EAIWC,WAAWA,CAACC,OAA2B,EAAEC,IAAY,EAAE;IAC1D,IAAI,CAACA,IAAI,GAAGA,IAAI;IAChB,IAAI,CAACD,OAAO,GAAGA,OAAO;EAC1B;EAEA,MAAaE,OAAOA,CAACC,MAA8C,EAAqB;IACpF,MAAM;MAAEC,IAAI;MAAEC,UAAU;MAAEC,OAAO,GAAG;IAAM,CAAC,GAAGH,MAAM,IAAI,CAAC,CAAC;IAC1D,MAAMI,OAAO,GAAG,IAAI,CAACP,OAAO,CAACQ,GAAG,CAAO;MACnCC,MAAM,EAAE,IAAI,CAACR,IAAI;MACjBG,IAAI;MACJE,OAAO,EAAED,UAAU,IAAIC,OAAO,GAAG,CAAC,GAAGA,OAAO,GAAGI;IACnD,CAAC,CAAC;IACF,IAAI,CAACL,UAAU,EAAE;MACb,OAAO,IAAI;IACf;IACA,MAAMM,MAAM,GAAG,MAAMJ,OAAO;IAE5B,OAAOF,UAAU,CAACM,MAAM,CAAC;EAC7B;AACJ;AAEA,OAAO,MAAMC,sBAAsB,GAAGA,CAIlCZ,OAA2B,EAC3BC,IAAY,KACc;EAC1B,OAAO,IAAIH,gBAAgB,CAAOE,OAAO,EAAEC,IAAI,CAAC;AACpD,CAAC","ignoreList":[]}
@@ -0,0 +1,16 @@
1
+ import type { IGenericData, IWebsocketsActions, IWebsocketsActionsRunParams, IWebsocketsManager } from "./types";
2
+ export interface IWebsocketActionsParams {
3
+ manager: IWebsocketsManager;
4
+ tenant: string | null;
5
+ locale: string | null;
6
+ getToken: () => Promise<string | undefined>;
7
+ }
8
+ export declare class WebsocketsActions implements IWebsocketsActions {
9
+ readonly manager: IWebsocketsManager;
10
+ private readonly getToken;
11
+ private readonly tenant;
12
+ private readonly locale;
13
+ constructor(params: IWebsocketActionsParams);
14
+ run<T extends IGenericData = IGenericData, R extends IGenericData = IGenericData>(params: IWebsocketsActionsRunParams<T>): Promise<R | null>;
15
+ }
16
+ export declare const createWebsocketsActions: (params: IWebsocketActionsParams) => IWebsocketsActions;
@@ -0,0 +1,84 @@
1
+ export class WebsocketsActions {
2
+ constructor(params) {
3
+ this.manager = params.manager;
4
+ this.tenant = params.tenant;
5
+ this.locale = params.locale;
6
+ this.getToken = params.getToken;
7
+ }
8
+ async run(params) {
9
+ const {
10
+ action,
11
+ timeout,
12
+ data
13
+ } = params;
14
+ const token = await this.getToken();
15
+ if (!token) {
16
+ console.error("Token is not set - cannot send a websocket message.");
17
+ return null;
18
+ } else if (!this.tenant) {
19
+ console.error("Tenant is not set - cannot send a websocket message.");
20
+ return null;
21
+ } else if (!this.locale) {
22
+ console.error("Locale is not set - cannot send a websocket message.");
23
+ return null;
24
+ }
25
+ /**
26
+ * If no timeout was sent, we will just send the message and return null.
27
+ * No waiting for the response.
28
+ */
29
+ if (!timeout || timeout < 0) {
30
+ this.manager.send({
31
+ /**
32
+ * It is ok to cast as we are checking the values a few lines above.
33
+ */
34
+ token,
35
+ tenant: this.tenant,
36
+ locale: this.locale,
37
+ action,
38
+ data: data || {}
39
+ });
40
+ return null;
41
+ }
42
+ /**
43
+ * In case of a timeout, we will send the message and wait for the response.
44
+ */
45
+ return await new Promise((resolve, reject) => {
46
+ let promiseTimeout = null;
47
+ const subscription = this.manager.onMessage(async event => {
48
+ if (event.data.messageId !== subscription.id) {
49
+ return;
50
+ }
51
+ resolve(event.data);
52
+ subscription.off();
53
+ if (!promiseTimeout) {
54
+ return;
55
+ }
56
+ clearTimeout(promiseTimeout);
57
+ });
58
+ promiseTimeout = setTimeout(() => {
59
+ const message = `Websocket action "${action}" timeout.`;
60
+ subscription.off();
61
+ reject(new Error(message));
62
+ }, timeout);
63
+ this.manager.send({
64
+ /**
65
+ * It is ok to cast as we are checking the values a few lines above.
66
+ */
67
+ token,
68
+ tenant: this.tenant,
69
+ locale: this.locale,
70
+ messageId: subscription.id,
71
+ action,
72
+ data: data || {}
73
+ });
74
+ }).catch(ex => {
75
+ console.error("Error while sending websocket message.", ex);
76
+ return null;
77
+ });
78
+ }
79
+ }
80
+ export const createWebsocketsActions = params => {
81
+ return new WebsocketsActions(params);
82
+ };
83
+
84
+ //# sourceMappingURL=WebsocketsActions.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"names":["WebsocketsActions","constructor","params","manager","tenant","locale","getToken","run","action","timeout","data","token","console","error","send","Promise","resolve","reject","promiseTimeout","subscription","onMessage","event","messageId","id","off","clearTimeout","setTimeout","message","Error","catch","ex","createWebsocketsActions"],"sources":["WebsocketsActions.ts"],"sourcesContent":["import type {\n IGenericData,\n IWebsocketsActions,\n IWebsocketsActionsRunParams,\n IWebsocketsManager,\n IWebsocketManagerSendData\n} from \"./types\";\n\nexport interface IWebsocketActionsParams {\n manager: IWebsocketsManager;\n tenant: string | null;\n locale: string | null;\n getToken: () => Promise<string | undefined>;\n}\n\nexport class WebsocketsActions implements IWebsocketsActions {\n public readonly manager: IWebsocketsManager;\n\n private readonly getToken: () => Promise<string | undefined>;\n private readonly tenant: string | null;\n private readonly locale: string | null;\n\n public constructor(params: IWebsocketActionsParams) {\n this.manager = params.manager;\n this.tenant = params.tenant;\n this.locale = params.locale;\n this.getToken = params.getToken;\n }\n\n public async run<T extends IGenericData = IGenericData, R extends IGenericData = IGenericData>(\n params: IWebsocketsActionsRunParams<T>\n ): Promise<R | null> {\n const { action, timeout, data } = params;\n const token = await this.getToken();\n if (!token) {\n console.error(\"Token is not set - cannot send a websocket message.\");\n return null;\n } else if (!this.tenant) {\n console.error(\"Tenant is not set - cannot send a websocket message.\");\n return null;\n } else if (!this.locale) {\n console.error(\"Locale is not set - cannot send a websocket message.\");\n return null;\n }\n /**\n * If no timeout was sent, we will just send the message and return null.\n * No waiting for the response.\n */\n if (!timeout || timeout < 0) {\n this.manager.send<IWebsocketManagerSendData<T>>({\n /**\n * It is ok to cast as we are checking the values a few lines above.\n */\n token,\n tenant: this.tenant as string,\n locale: this.locale as string,\n action,\n data: data || ({} as T)\n });\n return null;\n }\n /**\n * In case of a timeout, we will send the message and wait for the response.\n */\n return await new Promise<R>((resolve, reject) => {\n let promiseTimeout: NodeJS.Timeout | null = null;\n const subscription = this.manager.onMessage<R>(async event => {\n if (event.data.messageId !== subscription.id) {\n return;\n }\n resolve(event.data);\n subscription.off();\n if (!promiseTimeout) {\n return;\n }\n clearTimeout(promiseTimeout);\n });\n\n promiseTimeout = setTimeout(() => {\n const message = `Websocket action \"${action}\" timeout.`;\n subscription.off();\n reject(new Error(message));\n }, timeout);\n\n this.manager.send<IWebsocketManagerSendData<T>>({\n /**\n * It is ok to cast as we are checking the values a few lines above.\n */\n token,\n tenant: this.tenant as string,\n locale: this.locale as string,\n messageId: subscription.id,\n action,\n data: data || ({} as T)\n });\n }).catch(ex => {\n console.error(\"Error while sending websocket message.\", ex);\n return null;\n });\n }\n}\n\nexport const createWebsocketsActions = (params: IWebsocketActionsParams): IWebsocketsActions => {\n return new WebsocketsActions(params);\n};\n"],"mappings":"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","ignoreList":[]}
@@ -0,0 +1,42 @@
1
+ import type { IGenericData, IWebsocketsConnection, IWebsocketsConnectionFactory, IWebsocketsConnectProtocol, IWebsocketsSubscriptionManager, WebsocketsCloseCode } from "./types";
2
+ interface IConnection {
3
+ ws: WebSocket | null;
4
+ }
5
+ /**
6
+ * We need to attach the websockets cache to window object, or it will be reset on every hot reload.
7
+ */
8
+ declare global {
9
+ interface Window {
10
+ WebinyWebsocketsConnectionCache: IConnection;
11
+ }
12
+ }
13
+ export interface IWebsocketsConnectionParams {
14
+ url: string;
15
+ tenant: string;
16
+ locale: string;
17
+ getToken(): Promise<string | undefined>;
18
+ subscriptionManager: IWebsocketsSubscriptionManager;
19
+ protocol?: IWebsocketsConnectProtocol;
20
+ factory?: IWebsocketsConnectionFactory;
21
+ }
22
+ export declare class WebsocketsConnection implements IWebsocketsConnection {
23
+ private readonly url;
24
+ private readonly getToken;
25
+ private tenant;
26
+ private locale;
27
+ private readonly protocol;
28
+ readonly subscriptionManager: IWebsocketsSubscriptionManager;
29
+ private readonly factory;
30
+ constructor(params: IWebsocketsConnectionParams);
31
+ setTenant(tenant: string): void;
32
+ setLocale(locale: string): void;
33
+ connect(): Promise<void>;
34
+ close(code: WebsocketsCloseCode, reason: string): Promise<boolean>;
35
+ send<T extends IGenericData = IGenericData>(data: T): Promise<void>;
36
+ isConnected(): boolean;
37
+ isClosed(): boolean;
38
+ private createUrl;
39
+ private getConnection;
40
+ }
41
+ export declare const createWebsocketsConnection: (params: IWebsocketsConnectionParams) => IWebsocketsConnection;
42
+ export {};
@@ -0,0 +1,118 @@
1
+ import { WebsocketsReadyState } from "./types";
2
+ const defaultFactory = (url, protocol) => {
3
+ return new WebSocket(url, protocol);
4
+ };
5
+
6
+ /**
7
+ * We need to attach the websockets cache to window object, or it will be reset on every hot reload.
8
+ */
9
+
10
+ if (!window.WebinyWebsocketsConnectionCache) {
11
+ window.WebinyWebsocketsConnectionCache = {
12
+ ws: null
13
+ };
14
+ }
15
+ const connectionCache = window.WebinyWebsocketsConnectionCache;
16
+ export class WebsocketsConnection {
17
+ constructor(params) {
18
+ this.url = params.url;
19
+ this.tenant = params.tenant;
20
+ this.locale = params.locale;
21
+ this.getToken = params.getToken;
22
+ this.protocol = params.protocol;
23
+ this.subscriptionManager = params.subscriptionManager;
24
+ this.factory = params.factory || defaultFactory;
25
+ }
26
+ setTenant(tenant) {
27
+ this.tenant = tenant;
28
+ }
29
+ setLocale(locale) {
30
+ this.locale = locale;
31
+ }
32
+ async connect() {
33
+ await this.getConnection();
34
+ }
35
+ async close(code, reason) {
36
+ if (!connectionCache.ws || connectionCache.ws.readyState === WebsocketsReadyState.CLOSED || connectionCache.ws.readyState === WebsocketsReadyState.CLOSING) {
37
+ connectionCache.ws = undefined;
38
+ return true;
39
+ }
40
+ connectionCache.ws.close(code, reason);
41
+ connectionCache.ws = undefined;
42
+ return true;
43
+ }
44
+ async send(data) {
45
+ const connection = await this.getConnection();
46
+ if (connection.readyState !== WebsocketsReadyState.OPEN) {
47
+ console.info("Websocket connection is not open, cannot send any data.", data);
48
+ return;
49
+ }
50
+ connection.send(JSON.stringify(data));
51
+ }
52
+ isConnected() {
53
+ return connectionCache.ws?.readyState === WebsocketsReadyState.OPEN;
54
+ }
55
+ isClosed() {
56
+ return connectionCache.ws?.readyState === WebsocketsReadyState.CLOSED;
57
+ }
58
+ async createUrl() {
59
+ const token = await this.getToken();
60
+ if (!token) {
61
+ console.error(`Missing token to connect to websockets.`);
62
+ return null;
63
+ }
64
+ return {
65
+ token,
66
+ url: `${this.url}?token=${token}&tenant=${this.tenant}&locale=${this.locale}`
67
+ };
68
+ }
69
+ async getConnection() {
70
+ if (connectionCache.ws?.readyState === WebsocketsReadyState.OPEN) {
71
+ return connectionCache.ws;
72
+ } else if (connectionCache.ws?.readyState === WebsocketsReadyState.CONNECTING) {
73
+ return connectionCache.ws;
74
+ }
75
+ const result = await this.createUrl();
76
+ if (!result) {
77
+ throw new Error(`Missing URL for WebSocket to connect to.`);
78
+ }
79
+ const {
80
+ url
81
+ } = result;
82
+ connectionCache.ws = this.factory(url, this.protocol);
83
+ const start = new Date().getTime();
84
+ console.log(`Websockets connecting to ${this.url}...`);
85
+ connectionCache.ws.addEventListener("open", event => {
86
+ const end = new Date().getTime();
87
+ console.log(`...connected in ${end - start}ms.`);
88
+ return this.subscriptionManager.triggerOnOpen(event);
89
+ });
90
+ connectionCache.ws.addEventListener("close", event => {
91
+ return this.subscriptionManager.triggerOnClose(event);
92
+ });
93
+ connectionCache.ws.addEventListener("error", event => {
94
+ console.info(`Error in the Websocket connection.`, event);
95
+ /**
96
+ * Let's close it if possible.
97
+ * It will reopen automatically.
98
+ */
99
+ if (connectionCache.ws?.close) {
100
+ try {
101
+ connectionCache.ws.close();
102
+ } catch (ex) {
103
+ console.error(ex);
104
+ }
105
+ }
106
+ return this.subscriptionManager.triggerOnError(event);
107
+ });
108
+ connectionCache.ws.addEventListener("message", event => {
109
+ return this.subscriptionManager.triggerOnMessage(event);
110
+ });
111
+ return connectionCache.ws;
112
+ }
113
+ }
114
+ export const createWebsocketsConnection = params => {
115
+ return new WebsocketsConnection(params);
116
+ };
117
+
118
+ //# sourceMappingURL=WebsocketsConnection.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"names":["WebsocketsReadyState","defaultFactory","url","protocol","WebSocket","window","WebinyWebsocketsConnectionCache","ws","connectionCache","WebsocketsConnection","constructor","params","tenant","locale","getToken","subscriptionManager","factory","setTenant","setLocale","connect","getConnection","close","code","reason","readyState","CLOSED","CLOSING","undefined","send","data","connection","OPEN","console","info","JSON","stringify","isConnected","isClosed","createUrl","token","error","CONNECTING","result","Error","start","Date","getTime","log","addEventListener","event","end","triggerOnOpen","triggerOnClose","ex","triggerOnError","triggerOnMessage","createWebsocketsConnection"],"sources":["WebsocketsConnection.ts"],"sourcesContent":["import type {\n IGenericData,\n IWebsocketsConnection,\n IWebsocketsConnectionFactory,\n IWebsocketsConnectProtocol,\n IWebsocketsManagerMessageEvent,\n IWebsocketsSubscriptionManager,\n WebsocketsCloseCode\n} from \"./types\";\nimport { WebsocketsReadyState } from \"./types\";\n\ninterface ICreateUrlResult {\n token: string;\n url: string;\n}\n\nconst defaultFactory: IWebsocketsConnectionFactory = (url, protocol) => {\n return new WebSocket(url, protocol);\n};\n\ninterface IConnection {\n ws: WebSocket | null;\n}\n\n/**\n * We need to attach the websockets cache to window object, or it will be reset on every hot reload.\n */\ndeclare global {\n interface Window {\n WebinyWebsocketsConnectionCache: IConnection;\n }\n}\n\nif (!window.WebinyWebsocketsConnectionCache) {\n window.WebinyWebsocketsConnectionCache = {\n ws: null\n };\n}\n\nconst connectionCache = window.WebinyWebsocketsConnectionCache;\n\nexport interface IWebsocketsConnectionParams {\n url: string;\n tenant: string;\n locale: string;\n getToken(): Promise<string | undefined>;\n subscriptionManager: IWebsocketsSubscriptionManager;\n protocol?: IWebsocketsConnectProtocol;\n factory?: IWebsocketsConnectionFactory;\n}\n\nexport class WebsocketsConnection implements IWebsocketsConnection {\n private readonly url: string;\n private readonly getToken: () => Promise<string | undefined>;\n private tenant: string;\n private locale: string;\n private readonly protocol: IWebsocketsConnectProtocol;\n public readonly subscriptionManager: IWebsocketsSubscriptionManager;\n private readonly factory: IWebsocketsConnectionFactory;\n\n public constructor(params: IWebsocketsConnectionParams) {\n this.url = params.url;\n this.tenant = params.tenant;\n this.locale = params.locale;\n this.getToken = params.getToken;\n this.protocol = params.protocol;\n this.subscriptionManager = params.subscriptionManager;\n this.factory = params.factory || defaultFactory;\n }\n\n public setTenant(tenant: string): void {\n this.tenant = tenant;\n }\n\n public setLocale(locale: string): void {\n this.locale = locale;\n }\n\n public async connect(): Promise<void> {\n await this.getConnection();\n }\n\n public async close(code: WebsocketsCloseCode, reason: string): Promise<boolean> {\n if (\n !connectionCache.ws ||\n connectionCache.ws.readyState === WebsocketsReadyState.CLOSED ||\n connectionCache.ws.readyState === WebsocketsReadyState.CLOSING\n ) {\n connectionCache.ws = undefined as unknown as null;\n\n return true;\n }\n connectionCache.ws.close(code, reason);\n\n connectionCache.ws = undefined as unknown as null;\n return true;\n }\n\n public async send<T extends IGenericData = IGenericData>(data: T): Promise<void> {\n const connection = await this.getConnection();\n if (connection.readyState !== WebsocketsReadyState.OPEN) {\n console.info(\"Websocket connection is not open, cannot send any data.\", data);\n return;\n }\n connection.send(JSON.stringify(data));\n }\n\n public isConnected(): boolean {\n return connectionCache.ws?.readyState === WebsocketsReadyState.OPEN;\n }\n\n public isClosed(): boolean {\n return connectionCache.ws?.readyState === WebsocketsReadyState.CLOSED;\n }\n\n private async createUrl(): Promise<ICreateUrlResult | null> {\n const token = await this.getToken();\n if (!token) {\n console.error(`Missing token to connect to websockets.`);\n return null;\n }\n return {\n token,\n url: `${this.url}?token=${token}&tenant=${this.tenant}&locale=${this.locale}`\n };\n }\n\n private async getConnection(): Promise<WebSocket> {\n if (connectionCache.ws?.readyState === WebsocketsReadyState.OPEN) {\n return connectionCache.ws;\n } else if (connectionCache.ws?.readyState === WebsocketsReadyState.CONNECTING) {\n return connectionCache.ws;\n }\n\n const result = await this.createUrl();\n if (!result) {\n throw new Error(`Missing URL for WebSocket to connect to.`);\n }\n const { url } = result;\n\n connectionCache.ws = this.factory(url, this.protocol);\n\n const start = new Date().getTime();\n\n console.log(`Websockets connecting to ${this.url}...`);\n\n connectionCache.ws.addEventListener(\"open\", event => {\n const end = new Date().getTime();\n console.log(`...connected in ${end - start}ms.`);\n return this.subscriptionManager.triggerOnOpen(event);\n });\n connectionCache.ws.addEventListener(\"close\", event => {\n return this.subscriptionManager.triggerOnClose(event);\n });\n connectionCache.ws.addEventListener(\"error\", event => {\n console.info(`Error in the Websocket connection.`, event);\n /**\n * Let's close it if possible.\n * It will reopen automatically.\n */\n if (connectionCache.ws?.close) {\n try {\n connectionCache.ws.close();\n } catch (ex) {\n console.error(ex);\n }\n }\n return this.subscriptionManager.triggerOnError(event);\n });\n\n connectionCache.ws.addEventListener(\n \"message\",\n (event: IWebsocketsManagerMessageEvent<string>) => {\n return this.subscriptionManager.triggerOnMessage(event);\n }\n );\n\n return connectionCache.ws;\n }\n}\n\nexport const createWebsocketsConnection = (\n params: IWebsocketsConnectionParams\n): IWebsocketsConnection => {\n return new WebsocketsConnection(params);\n};\n"],"mappings":"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","ignoreList":[]}
@@ -0,0 +1,15 @@
1
+ import type { IGenericData, IWebsocketsConnection, IWebsocketsManager, IWebsocketsManagerCloseEvent, IWebsocketsManagerErrorEvent, IWebsocketsManagerMessageEvent, IWebsocketsManagerOpenEvent, IWebsocketManagerSendData, IWebsocketsSubscription, IWebsocketsSubscriptionCallback, WebsocketsCloseCode } from "./types";
2
+ export declare class WebsocketsManager implements IWebsocketsManager {
3
+ readonly connection: IWebsocketsConnection;
4
+ constructor(connection: IWebsocketsConnection);
5
+ onOpen(cb: IWebsocketsSubscriptionCallback<IWebsocketsManagerOpenEvent>): IWebsocketsSubscription<IWebsocketsManagerOpenEvent>;
6
+ onClose(cb: IWebsocketsSubscriptionCallback<IWebsocketsManagerCloseEvent>): IWebsocketsSubscription<IWebsocketsManagerCloseEvent>;
7
+ onMessage<T extends IGenericData = IGenericData>(cb: IWebsocketsSubscriptionCallback<IWebsocketsManagerMessageEvent<T>>): IWebsocketsSubscription<IWebsocketsManagerMessageEvent<T>>;
8
+ onError(cb: IWebsocketsSubscriptionCallback<IWebsocketsManagerErrorEvent>): IWebsocketsSubscription<IWebsocketsManagerErrorEvent>;
9
+ connect(): Promise<void>;
10
+ close(code: WebsocketsCloseCode, reason: string): Promise<boolean>;
11
+ send<T extends IWebsocketManagerSendData = IWebsocketManagerSendData>(data: T): void;
12
+ isConnected(): boolean;
13
+ isClosed(): boolean;
14
+ }
15
+ export declare const createWebsocketsManager: (connection: IWebsocketsConnection) => IWebsocketsManager;
@@ -0,0 +1,37 @@
1
+ export class WebsocketsManager {
2
+ constructor(connection) {
3
+ this.connection = connection;
4
+ }
5
+ onOpen(cb) {
6
+ return this.connection.subscriptionManager.onOpen(cb);
7
+ }
8
+ onClose(cb) {
9
+ return this.connection.subscriptionManager.onClose(cb);
10
+ }
11
+ onMessage(cb) {
12
+ return this.connection.subscriptionManager.onMessage(cb);
13
+ }
14
+ onError(cb) {
15
+ return this.connection.subscriptionManager.onError(cb);
16
+ }
17
+ async connect() {
18
+ return this.connection.connect();
19
+ }
20
+ async close(code, reason) {
21
+ return await this.connection.close(code, reason);
22
+ }
23
+ send(data) {
24
+ return this.connection.send(data);
25
+ }
26
+ isConnected() {
27
+ return this.connection.isConnected();
28
+ }
29
+ isClosed() {
30
+ return this.connection.isClosed();
31
+ }
32
+ }
33
+ export const createWebsocketsManager = connection => {
34
+ return new WebsocketsManager(connection);
35
+ };
36
+
37
+ //# sourceMappingURL=WebsocketsManager.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"names":["WebsocketsManager","constructor","connection","onOpen","cb","subscriptionManager","onClose","onMessage","onError","connect","close","code","reason","send","data","isConnected","isClosed","createWebsocketsManager"],"sources":["WebsocketsManager.ts"],"sourcesContent":["import type {\n IGenericData,\n IWebsocketsConnection,\n IWebsocketsManager,\n IWebsocketsManagerCloseEvent,\n IWebsocketsManagerErrorEvent,\n IWebsocketsManagerMessageEvent,\n IWebsocketsManagerOpenEvent,\n IWebsocketManagerSendData,\n IWebsocketsSubscription,\n IWebsocketsSubscriptionCallback,\n WebsocketsCloseCode\n} from \"./types\";\n\nexport class WebsocketsManager implements IWebsocketsManager {\n public readonly connection: IWebsocketsConnection;\n\n public constructor(connection: IWebsocketsConnection) {\n this.connection = connection;\n }\n\n public onOpen(\n cb: IWebsocketsSubscriptionCallback<IWebsocketsManagerOpenEvent>\n ): IWebsocketsSubscription<IWebsocketsManagerOpenEvent> {\n return this.connection.subscriptionManager.onOpen(cb);\n }\n\n public onClose(\n cb: IWebsocketsSubscriptionCallback<IWebsocketsManagerCloseEvent>\n ): IWebsocketsSubscription<IWebsocketsManagerCloseEvent> {\n return this.connection.subscriptionManager.onClose(cb);\n }\n\n public onMessage<T extends IGenericData = IGenericData>(\n cb: IWebsocketsSubscriptionCallback<IWebsocketsManagerMessageEvent<T>>\n ): IWebsocketsSubscription<IWebsocketsManagerMessageEvent<T>> {\n return this.connection.subscriptionManager.onMessage<T>(cb);\n }\n\n public onError(\n cb: IWebsocketsSubscriptionCallback<IWebsocketsManagerErrorEvent>\n ): IWebsocketsSubscription<IWebsocketsManagerErrorEvent> {\n return this.connection.subscriptionManager.onError(cb);\n }\n\n public async connect(): Promise<void> {\n return this.connection.connect();\n }\n\n public async close(code: WebsocketsCloseCode, reason: string): Promise<boolean> {\n return await this.connection.close(code, reason);\n }\n\n public send<T extends IWebsocketManagerSendData = IWebsocketManagerSendData>(data: T): void {\n return this.connection.send<T>(data);\n }\n\n public isConnected(): boolean {\n return this.connection.isConnected();\n }\n\n public isClosed(): boolean {\n return this.connection.isClosed();\n }\n}\n\nexport const createWebsocketsManager = (connection: IWebsocketsConnection): IWebsocketsManager => {\n return new WebsocketsManager(connection);\n};\n"],"mappings":"AAcA,OAAO,MAAMA,iBAAiB,CAA+B;EAGlDC,WAAWA,CAACC,UAAiC,EAAE;IAClD,IAAI,CAACA,UAAU,GAAGA,UAAU;EAChC;EAEOC,MAAMA,CACTC,EAAgE,EACZ;IACpD,OAAO,IAAI,CAACF,UAAU,CAACG,mBAAmB,CAACF,MAAM,CAACC,EAAE,CAAC;EACzD;EAEOE,OAAOA,CACVF,EAAiE,EACZ;IACrD,OAAO,IAAI,CAACF,UAAU,CAACG,mBAAmB,CAACC,OAAO,CAACF,EAAE,CAAC;EAC1D;EAEOG,SAASA,CACZH,EAAsE,EACZ;IAC1D,OAAO,IAAI,CAACF,UAAU,CAACG,mBAAmB,CAACE,SAAS,CAAIH,EAAE,CAAC;EAC/D;EAEOI,OAAOA,CACVJ,EAAiE,EACZ;IACrD,OAAO,IAAI,CAACF,UAAU,CAACG,mBAAmB,CAACG,OAAO,CAACJ,EAAE,CAAC;EAC1D;EAEA,MAAaK,OAAOA,CAAA,EAAkB;IAClC,OAAO,IAAI,CAACP,UAAU,CAACO,OAAO,CAAC,CAAC;EACpC;EAEA,MAAaC,KAAKA,CAACC,IAAyB,EAAEC,MAAc,EAAoB;IAC5E,OAAO,MAAM,IAAI,CAACV,UAAU,CAACQ,KAAK,CAACC,IAAI,EAAEC,MAAM,CAAC;EACpD;EAEOC,IAAIA,CAAkEC,IAAO,EAAQ;IACxF,OAAO,IAAI,CAACZ,UAAU,CAACW,IAAI,CAAIC,IAAI,CAAC;EACxC;EAEOC,WAAWA,CAAA,EAAY;IAC1B,OAAO,IAAI,CAACb,UAAU,CAACa,WAAW,CAAC,CAAC;EACxC;EAEOC,QAAQA,CAAA,EAAY;IACvB,OAAO,IAAI,CAACd,UAAU,CAACc,QAAQ,CAAC,CAAC;EACrC;AACJ;AAEA,OAAO,MAAMC,uBAAuB,GAAIf,UAAiC,IAAyB;EAC9F,OAAO,IAAIF,iBAAiB,CAACE,UAAU,CAAC;AAC5C,CAAC","ignoreList":[]}