@webiny/app-websockets 0.0.0-unstable.e6f0dc8ca7 → 0.0.0-unstable.eb81deee7e

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 (50) hide show
  1. package/WebsocketsContextProvider.js +134 -142
  2. package/WebsocketsContextProvider.js.map +1 -1
  3. package/domain/WebsocketsAction.js +17 -24
  4. package/domain/WebsocketsAction.js.map +1 -1
  5. package/domain/WebsocketsActions.js +52 -73
  6. package/domain/WebsocketsActions.js.map +1 -1
  7. package/domain/WebsocketsConnection.d.ts +30 -0
  8. package/domain/WebsocketsConnection.js +161 -102
  9. package/domain/WebsocketsConnection.js.map +1 -1
  10. package/domain/WebsocketsManager.js +33 -34
  11. package/domain/WebsocketsManager.js.map +1 -1
  12. package/domain/WebsocketsSubscriptionManager.js +57 -64
  13. package/domain/WebsocketsSubscriptionManager.js.map +1 -1
  14. package/domain/abstractions/IWebsocketsAction.js +0 -3
  15. package/domain/abstractions/IWebsocketsActions.js +0 -3
  16. package/domain/abstractions/IWebsocketsConnection.js +7 -6
  17. package/domain/abstractions/IWebsocketsConnection.js.map +1 -1
  18. package/domain/abstractions/IWebsocketsManager.js +0 -3
  19. package/domain/abstractions/IWebsocketsSubscriptionManager.js +0 -3
  20. package/domain/abstractions/types.js +19 -18
  21. package/domain/abstractions/types.js.map +1 -1
  22. package/domain/index.js +0 -2
  23. package/domain/types.js +0 -2
  24. package/events/WebsocketEvent.d.ts +10 -0
  25. package/events/WebsocketEvent.js +13 -0
  26. package/events/WebsocketEvent.js.map +1 -0
  27. package/events/abstractions.d.ts +13 -0
  28. package/events/abstractions.js +5 -0
  29. package/events/abstractions.js.map +1 -0
  30. package/exports/admin/websockets.d.ts +1 -0
  31. package/exports/admin/websockets.js +1 -0
  32. package/hooks/index.js +0 -2
  33. package/hooks/useWebsockets.js +5 -6
  34. package/hooks/useWebsockets.js.map +1 -1
  35. package/index.d.ts +4 -1
  36. package/index.js +11 -12
  37. package/index.js.map +1 -1
  38. package/package.json +13 -9
  39. package/types.js +0 -3
  40. package/domain/abstractions/IWebsocketsAction.js.map +0 -1
  41. package/domain/abstractions/IWebsocketsActions.js.map +0 -1
  42. package/domain/abstractions/IWebsocketsManager.js.map +0 -1
  43. package/domain/abstractions/IWebsocketsSubscriptionManager.js.map +0 -1
  44. package/domain/index.js.map +0 -1
  45. package/domain/types.js.map +0 -1
  46. package/hooks/index.js.map +0 -1
  47. package/types.js.map +0 -1
  48. package/utils/getUrl.d.ts +0 -1
  49. package/utils/getUrl.js +0 -6
  50. package/utils/getUrl.js.map +0 -1
@@ -1,114 +1,173 @@
1
1
  import { WebsocketsReadyState } from "./types.js";
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 = {
2
+ const defaultFactory = (url, protocol)=>new WebSocket(url, protocol);
3
+ if (!window.WebinyWebsocketsConnectionCache) window.WebinyWebsocketsConnectionCache = {
12
4
  ws: null
13
- };
14
- }
5
+ };
15
6
  const connectionCache = window.WebinyWebsocketsConnectionCache;
16
- export class WebsocketsConnection {
17
- constructor(params) {
18
- this.url = params.url;
19
- this.tenant = params.tenant;
20
- this.getToken = params.getToken;
21
- this.protocol = params.protocol;
22
- this.subscriptionManager = params.subscriptionManager;
23
- this.factory = params.factory || defaultFactory;
24
- }
25
- setTenant(tenant) {
26
- this.tenant = tenant;
27
- }
28
- async connect() {
29
- await this.getConnection();
30
- }
31
- async close(code, reason) {
32
- if (!connectionCache.ws || connectionCache.ws.readyState === WebsocketsReadyState.CLOSED || connectionCache.ws.readyState === WebsocketsReadyState.CLOSING) {
33
- connectionCache.ws = undefined;
34
- return true;
7
+ const WEBSOCKETS_HEARTBEAT_INTERVAL = 300000;
8
+ const WEBSOCKETS_HEARTBEAT_ACTION = "ping";
9
+ const MAX_RECONNECT_DELAY = 30000;
10
+ const defaultReconnectDelay = (attempt)=>Math.min(1000 * 2 ** attempt, MAX_RECONNECT_DELAY);
11
+ class WebsocketsConnection {
12
+ constructor(params){
13
+ this.reconnectAttempt = 0;
14
+ this.reconnectTimer = null;
15
+ this.heartbeatTimer = null;
16
+ this.connecting = null;
17
+ this.generation = 0;
18
+ this.url = params.url;
19
+ this.tenant = params.tenant;
20
+ this.getToken = params.getToken;
21
+ this.protocol = params.protocol;
22
+ this.subscriptionManager = params.subscriptionManager;
23
+ this.factory = params.factory || defaultFactory;
24
+ this.heartbeatInterval = params.heartbeatInterval ?? WEBSOCKETS_HEARTBEAT_INTERVAL;
25
+ this.reconnectDelay = params.reconnectDelay ?? defaultReconnectDelay;
26
+ }
27
+ setTenant(tenant) {
28
+ this.tenant = tenant;
29
+ }
30
+ async connect() {
31
+ await this.getConnection();
32
+ }
33
+ async close(code, reason) {
34
+ this.generation++;
35
+ this.connecting = null;
36
+ this.stopHeartbeat();
37
+ this.cancelReconnect();
38
+ if (!connectionCache.ws || connectionCache.ws.readyState === WebsocketsReadyState.CLOSED || connectionCache.ws.readyState === WebsocketsReadyState.CLOSING) {
39
+ connectionCache.ws = void 0;
40
+ return true;
41
+ }
42
+ const ws = connectionCache.ws;
43
+ connectionCache.ws = void 0;
44
+ ws.close(code, reason);
45
+ return true;
35
46
  }
36
- connectionCache.ws.close(code, reason);
37
- connectionCache.ws = undefined;
38
- return true;
39
- }
40
- async send(data) {
41
- const connection = await this.getConnection();
42
- if (connection.readyState !== WebsocketsReadyState.OPEN) {
43
- console.info("Websocket connection is not open, cannot send any data.", data);
44
- return;
47
+ async send(data) {
48
+ const connection = await this.getConnection();
49
+ if (!connection || connection.readyState !== WebsocketsReadyState.OPEN) return void console.info("Websocket connection is not open, cannot send any data.", data);
50
+ connection.send(JSON.stringify(data));
45
51
  }
46
- connection.send(JSON.stringify(data));
47
- }
48
- isConnected() {
49
- return connectionCache.ws?.readyState === WebsocketsReadyState.OPEN;
50
- }
51
- isClosed() {
52
- return connectionCache.ws?.readyState === WebsocketsReadyState.CLOSED;
53
- }
54
- async createUrl() {
55
- const token = await this.getToken();
56
- if (!token) {
57
- console.error(`Missing token to connect to websockets.`);
58
- return null;
52
+ isConnected() {
53
+ return connectionCache.ws?.readyState === WebsocketsReadyState.OPEN;
59
54
  }
60
- return {
61
- token,
62
- url: `${this.url}?token=${token}&tenant=${this.tenant}`
63
- };
64
- }
65
- async getConnection() {
66
- if (connectionCache.ws?.readyState === WebsocketsReadyState.OPEN) {
67
- return connectionCache.ws;
68
- } else if (connectionCache.ws?.readyState === WebsocketsReadyState.CONNECTING) {
69
- return connectionCache.ws;
55
+ isClosed() {
56
+ return connectionCache.ws?.readyState === WebsocketsReadyState.CLOSED;
70
57
  }
71
- const result = await this.createUrl();
72
- if (!result) {
73
- throw new Error(`Missing URL for WebSocket to connect to.`);
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}`
67
+ };
74
68
  }
75
- const {
76
- url
77
- } = result;
78
- connectionCache.ws = this.factory(url, this.protocol);
79
- const start = new Date().getTime();
80
- console.log(`Websockets connecting to ${this.url}...`);
81
- connectionCache.ws.addEventListener("open", event => {
82
- const end = new Date().getTime();
83
- console.log(`...connected in ${end - start}ms.`);
84
- return this.subscriptionManager.triggerOnOpen(event);
85
- });
86
- connectionCache.ws.addEventListener("close", event => {
87
- return this.subscriptionManager.triggerOnClose(event);
88
- });
89
- connectionCache.ws.addEventListener("error", event => {
90
- console.info(`Error in the Websocket connection.`, event);
91
- /**
92
- * Let's close it if possible.
93
- * It will reopen automatically.
94
- */
95
- if (connectionCache.ws?.close) {
96
- try {
97
- connectionCache.ws.close();
98
- } catch (ex) {
99
- console.error(ex);
69
+ getConnection() {
70
+ const cached = connectionCache.ws;
71
+ if (cached?.readyState === WebsocketsReadyState.OPEN || cached?.readyState === WebsocketsReadyState.CONNECTING) return Promise.resolve(cached);
72
+ if (!this.connecting) {
73
+ const attempt = this.openConnection();
74
+ const clear = ()=>{
75
+ if (this.connecting === attempt) this.connecting = null;
76
+ };
77
+ attempt.then(clear, clear);
78
+ this.connecting = attempt;
100
79
  }
101
- }
102
- return this.subscriptionManager.triggerOnError(event);
103
- });
104
- connectionCache.ws.addEventListener("message", event => {
105
- return this.subscriptionManager.triggerOnMessage(event);
106
- });
107
- return connectionCache.ws;
108
- }
80
+ return this.connecting;
81
+ }
82
+ async openConnection() {
83
+ const generation = this.generation;
84
+ const result = await this.createUrl();
85
+ if (generation !== this.generation) return null;
86
+ if (!result) throw new Error("Missing URL for WebSocket to connect to.");
87
+ const { url } = result;
88
+ const ws = this.factory(url, this.protocol);
89
+ connectionCache.ws = ws;
90
+ const start = new Date().getTime();
91
+ console.log(`Websockets connecting to ${this.url}...`);
92
+ ws.addEventListener("open", (event)=>{
93
+ const end = new Date().getTime();
94
+ console.log(`...connected in ${end - start}ms.`);
95
+ this.reconnectAttempt = 0;
96
+ this.startHeartbeat();
97
+ return this.subscriptionManager.triggerOnOpen(event);
98
+ });
99
+ ws.addEventListener("close", (event)=>{
100
+ console.warn("Websocket connection closed.", {
101
+ code: event.code,
102
+ reason: event.reason,
103
+ wasClean: event.wasClean,
104
+ at: new Date().toISOString()
105
+ });
106
+ if (connectionCache.ws === ws) {
107
+ this.stopHeartbeat();
108
+ this.scheduleReconnect();
109
+ }
110
+ return this.subscriptionManager.triggerOnClose(event);
111
+ });
112
+ ws.addEventListener("error", (event)=>{
113
+ console.info("Error in the Websocket connection.", event);
114
+ try {
115
+ ws.close();
116
+ } catch (ex) {
117
+ console.error(ex);
118
+ }
119
+ return this.subscriptionManager.triggerOnError(event);
120
+ });
121
+ ws.addEventListener("message", (event)=>this.subscriptionManager.triggerOnMessage(event));
122
+ return ws;
123
+ }
124
+ scheduleReconnect() {
125
+ if (this.reconnectTimer) return;
126
+ const delay = this.reconnectDelay(this.reconnectAttempt);
127
+ this.reconnectAttempt++;
128
+ console.log(`Websockets reconnecting in ${delay}ms (attempt ${this.reconnectAttempt}).`);
129
+ const generation = this.generation;
130
+ this.reconnectTimer = setTimeout(async ()=>{
131
+ this.reconnectTimer = null;
132
+ try {
133
+ await this.connect();
134
+ } catch (ex) {
135
+ if (generation !== this.generation) return;
136
+ console.error("Websockets reconnect failed.", ex);
137
+ this.scheduleReconnect();
138
+ }
139
+ }, delay);
140
+ }
141
+ cancelReconnect() {
142
+ if (!this.reconnectTimer) return;
143
+ clearTimeout(this.reconnectTimer);
144
+ this.reconnectTimer = null;
145
+ }
146
+ startHeartbeat() {
147
+ this.stopHeartbeat();
148
+ this.heartbeatTimer = setInterval(()=>{
149
+ this.sendHeartbeat().catch((ex)=>{
150
+ console.error("Websockets heartbeat failed.", ex);
151
+ });
152
+ }, this.heartbeatInterval);
153
+ }
154
+ stopHeartbeat() {
155
+ if (!this.heartbeatTimer) return;
156
+ clearInterval(this.heartbeatTimer);
157
+ this.heartbeatTimer = null;
158
+ }
159
+ async sendHeartbeat() {
160
+ if (!this.isConnected()) return;
161
+ const token = await this.getToken();
162
+ if (!token || !this.isConnected()) return;
163
+ connectionCache.ws.send(JSON.stringify({
164
+ action: WEBSOCKETS_HEARTBEAT_ACTION,
165
+ token,
166
+ tenant: this.tenant
167
+ }));
168
+ }
109
169
  }
110
- export const createWebsocketsConnection = params => {
111
- return new WebsocketsConnection(params);
112
- };
170
+ const createWebsocketsConnection = (params)=>new WebsocketsConnection(params);
171
+ export { WEBSOCKETS_HEARTBEAT_ACTION, WEBSOCKETS_HEARTBEAT_INTERVAL, WebsocketsConnection, createWebsocketsConnection };
113
172
 
114
173
  //# sourceMappingURL=WebsocketsConnection.js.map
@@ -1 +1 @@
1
- {"version":3,"names":["WebsocketsReadyState","defaultFactory","url","protocol","WebSocket","window","WebinyWebsocketsConnectionCache","ws","connectionCache","WebsocketsConnection","constructor","params","tenant","getToken","subscriptionManager","factory","setTenant","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.js\";\nimport { WebsocketsReadyState } from \"./types.js\";\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 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 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.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 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}`\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":[]}
1
+ {"version":3,"file":"domain/WebsocketsConnection.js","sources":["../../src/domain/WebsocketsConnection.ts"],"sourcesContent":["import type {\n IGenericData,\n IWebsocketsConnection,\n IWebsocketsConnectionFactory,\n IWebsocketsConnectProtocol,\n IWebsocketsManagerMessageEvent,\n IWebsocketsSubscriptionManager,\n WebsocketsCloseCode\n} from \"./types.js\";\nimport { WebsocketsReadyState } from \"./types.js\";\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\n/**\n * API Gateway closes a WebSocket after 10 minutes without traffic (and after 2 hours regardless), so\n * we ping well inside that window. The ping has no route of its own and lands on `$default`.\n */\nexport const WEBSOCKETS_HEARTBEAT_INTERVAL = 5 * 60 * 1000;\nexport const WEBSOCKETS_HEARTBEAT_ACTION = \"ping\";\n\nconst MAX_RECONNECT_DELAY = 30 * 1000;\n\nconst defaultReconnectDelay = (attempt: number): number => {\n return Math.min(1000 * 2 ** attempt, MAX_RECONNECT_DELAY);\n};\n\nexport interface IWebsocketsConnectionParams {\n url: string;\n tenant: string;\n getToken(): Promise<string | undefined>;\n subscriptionManager: IWebsocketsSubscriptionManager;\n protocol?: IWebsocketsConnectProtocol;\n factory?: IWebsocketsConnectionFactory;\n heartbeatInterval?: number;\n reconnectDelay?: (attempt: number) => number;\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 readonly protocol: IWebsocketsConnectProtocol;\n public readonly subscriptionManager: IWebsocketsSubscriptionManager;\n private readonly factory: IWebsocketsConnectionFactory;\n private readonly heartbeatInterval: number;\n private readonly reconnectDelay: (attempt: number) => number;\n private reconnectAttempt = 0;\n private reconnectTimer: ReturnType<typeof setTimeout> | null = null;\n private heartbeatTimer: ReturnType<typeof setInterval> | null = null;\n /**\n * Opening a socket waits for a token first. `connecting` lets concurrent callers (a reconnect\n * timer, the window-focus handler, `send()`) share that one attempt instead of each creating a\n * socket, and `generation` lets `close()` invalidate an attempt that is already waiting.\n */\n private connecting: Promise<WebSocket | null> | null = null;\n private generation = 0;\n\n public constructor(params: IWebsocketsConnectionParams) {\n this.url = params.url;\n this.tenant = params.tenant;\n this.getToken = params.getToken;\n this.protocol = params.protocol;\n this.subscriptionManager = params.subscriptionManager;\n this.factory = params.factory || defaultFactory;\n this.heartbeatInterval = params.heartbeatInterval ?? WEBSOCKETS_HEARTBEAT_INTERVAL;\n this.reconnectDelay = params.reconnectDelay ?? defaultReconnectDelay;\n }\n\n public setTenant(tenant: string): void {\n this.tenant = tenant;\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 this.generation++;\n this.connecting = null;\n this.stopHeartbeat();\n this.cancelReconnect();\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 // Detach first: the close handler reconnects only while the closing socket is still the\n // cached one, and this close is intentional.\n const ws = connectionCache.ws;\n connectionCache.ws = undefined as unknown as null;\n ws.close(code, reason);\n\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 || 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}`\n };\n }\n\n private getConnection(): Promise<WebSocket | null> {\n const cached = connectionCache.ws;\n if (\n cached?.readyState === WebsocketsReadyState.OPEN ||\n cached?.readyState === WebsocketsReadyState.CONNECTING\n ) {\n return Promise.resolve(cached);\n }\n\n if (!this.connecting) {\n const attempt = this.openConnection();\n const clear = () => {\n if (this.connecting === attempt) {\n this.connecting = null;\n }\n };\n attempt.then(clear, clear);\n this.connecting = attempt;\n }\n return this.connecting;\n }\n\n /**\n * Resolves to `null` when `close()` ran while the token was being fetched: the attempt is\n * abandoned rather than opening a socket nobody asked for any more.\n */\n private async openConnection(): Promise<WebSocket | null> {\n const generation = this.generation;\n const result = await this.createUrl();\n if (generation !== this.generation) {\n return null;\n }\n if (!result) {\n throw new Error(`Missing URL for WebSocket to connect to.`);\n }\n const { url } = result;\n\n const ws = this.factory(url, this.protocol);\n connectionCache.ws = ws;\n\n const start = new Date().getTime();\n\n console.log(`Websockets connecting to ${this.url}...`);\n\n ws.addEventListener(\"open\", event => {\n const end = new Date().getTime();\n console.log(`...connected in ${end - start}ms.`);\n this.reconnectAttempt = 0;\n this.startHeartbeat();\n return this.subscriptionManager.triggerOnOpen(event);\n });\n ws.addEventListener(\"close\", event => {\n console.warn(\"Websocket connection closed.\", {\n code: event.code,\n reason: event.reason,\n wasClean: event.wasClean,\n at: new Date().toISOString()\n });\n /**\n * `close()` detaches the socket from the cache before closing it, so a socket that is no\n * longer the cached one was either closed on purpose or already replaced. Only the\n * current socket closing on its own warrants a reconnect: while it is down, the server\n * has no registered connection for this identity and every push to it is dropped.\n */\n if (connectionCache.ws === ws) {\n this.stopHeartbeat();\n this.scheduleReconnect();\n }\n return this.subscriptionManager.triggerOnClose(event);\n });\n ws.addEventListener(\"error\", event => {\n console.info(`Error in the Websocket connection.`, event);\n /**\n * Close this socket (not whatever is cached by now); the close handler reconnects if\n * it is still the current one.\n */\n try {\n ws.close();\n } catch (ex) {\n console.error(ex);\n }\n return this.subscriptionManager.triggerOnError(event);\n });\n\n ws.addEventListener(\"message\", (event: IWebsocketsManagerMessageEvent<string>) => {\n return this.subscriptionManager.triggerOnMessage(event);\n });\n\n return ws;\n }\n\n private scheduleReconnect(): void {\n if (this.reconnectTimer) {\n return;\n }\n const delay = this.reconnectDelay(this.reconnectAttempt);\n this.reconnectAttempt++;\n console.log(`Websockets reconnecting in ${delay}ms (attempt ${this.reconnectAttempt}).`);\n\n const generation = this.generation;\n this.reconnectTimer = setTimeout(async () => {\n this.reconnectTimer = null;\n try {\n await this.connect();\n } catch (ex) {\n if (generation !== this.generation) {\n // close() ran while this attempt was in flight: it was meant to stop here.\n return;\n }\n // No token yet (e.g. mid-refresh) or the socket could not be created: try again.\n console.error(\"Websockets reconnect failed.\", ex);\n this.scheduleReconnect();\n }\n }, delay);\n }\n\n private cancelReconnect(): void {\n if (!this.reconnectTimer) {\n return;\n }\n clearTimeout(this.reconnectTimer);\n this.reconnectTimer = null;\n }\n\n private startHeartbeat(): void {\n this.stopHeartbeat();\n this.heartbeatTimer = setInterval(() => {\n this.sendHeartbeat().catch(ex => {\n console.error(\"Websockets heartbeat failed.\", ex);\n });\n }, this.heartbeatInterval);\n }\n\n private stopHeartbeat(): void {\n if (!this.heartbeatTimer) {\n return;\n }\n clearInterval(this.heartbeatTimer);\n this.heartbeatTimer = null;\n }\n\n private async sendHeartbeat(): Promise<void> {\n if (!this.isConnected()) {\n return;\n }\n const token = await this.getToken();\n if (!token || !this.isConnected()) {\n return;\n }\n // Same envelope as WebsocketsActions: the `$default` route authenticates every message.\n connectionCache.ws!.send(\n JSON.stringify({ action: WEBSOCKETS_HEARTBEAT_ACTION, token, tenant: this.tenant })\n );\n }\n}\n\nexport const createWebsocketsConnection = (\n params: IWebsocketsConnectionParams\n): IWebsocketsConnection => {\n return new WebsocketsConnection(params);\n};\n"],"names":["defaultFactory","url","protocol","WebSocket","window","connectionCache","WEBSOCKETS_HEARTBEAT_INTERVAL","WEBSOCKETS_HEARTBEAT_ACTION","MAX_RECONNECT_DELAY","defaultReconnectDelay","attempt","Math","WebsocketsConnection","params","tenant","code","reason","WebsocketsReadyState","undefined","ws","data","connection","console","JSON","token","cached","Promise","clear","generation","result","Error","start","Date","event","end","ex","delay","setTimeout","clearTimeout","setInterval","clearInterval","createWebsocketsConnection"],"mappings":";AAgBA,MAAMA,iBAA+C,CAACC,KAAKC,WAChD,IAAIC,UAAUF,KAAKC;AAgB9B,IAAI,CAACE,OAAO,+BAA+B,EACvCA,OAAO,+BAA+B,GAAG;IACrC,IAAI;AACR;AAGJ,MAAMC,kBAAkBD,OAAO,+BAA+B;AAMvD,MAAME,gCAAgC;AACtC,MAAMC,8BAA8B;AAE3C,MAAMC,sBAAsB;AAE5B,MAAMC,wBAAwB,CAACC,UACpBC,KAAK,GAAG,CAAC,OAAO,KAAKD,SAASF;AAclC,MAAMI;IAoBT,YAAmBC,MAAmC,CAAE;aAXhD,gBAAgB,GAAG;aACnB,cAAc,GAAyC;aACvD,cAAc,GAA0C;QAK/D,KACO,UAAU,GAAqC;aAC/C,UAAU,GAAG;QAGjB,IAAI,CAAC,GAAG,GAAGA,OAAO,GAAG;QACrB,IAAI,CAAC,MAAM,GAAGA,OAAO,MAAM;QAC3B,IAAI,CAAC,QAAQ,GAAGA,OAAO,QAAQ;QAC/B,IAAI,CAAC,QAAQ,GAAGA,OAAO,QAAQ;QAC/B,IAAI,CAAC,mBAAmB,GAAGA,OAAO,mBAAmB;QACrD,IAAI,CAAC,OAAO,GAAGA,OAAO,OAAO,IAAIb;QACjC,IAAI,CAAC,iBAAiB,GAAGa,OAAO,iBAAiB,IAAIP;QACrD,IAAI,CAAC,cAAc,GAAGO,OAAO,cAAc,IAAIJ;IACnD;IAEO,UAAUK,MAAc,EAAQ;QACnC,IAAI,CAAC,MAAM,GAAGA;IAClB;IAEA,MAAa,UAAyB;QAClC,MAAM,IAAI,CAAC,aAAa;IAC5B;IAEA,MAAa,MAAMC,IAAyB,EAAEC,MAAc,EAAoB;QAC5E,IAAI,CAAC,UAAU;QACf,IAAI,CAAC,UAAU,GAAG;QAClB,IAAI,CAAC,aAAa;QAClB,IAAI,CAAC,eAAe;QACpB,IACI,CAACX,gBAAgB,EAAE,IACnBA,gBAAgB,EAAE,CAAC,UAAU,KAAKY,qBAAqB,MAAM,IAC7DZ,gBAAgB,EAAE,CAAC,UAAU,KAAKY,qBAAqB,OAAO,EAChE;YACEZ,gBAAgB,EAAE,GAAGa;YAErB,OAAO;QACX;QAGA,MAAMC,KAAKd,gBAAgB,EAAE;QAC7BA,gBAAgB,EAAE,GAAGa;QACrBC,GAAG,KAAK,CAACJ,MAAMC;QAEf,OAAO;IACX;IAEA,MAAa,KAA4CI,IAAO,EAAiB;QAC7E,MAAMC,aAAa,MAAM,IAAI,CAAC,aAAa;QAC3C,IAAI,CAACA,cAAcA,WAAW,UAAU,KAAKJ,qBAAqB,IAAI,EAAE,YACpEK,QAAQ,IAAI,CAAC,2DAA2DF;QAG5EC,WAAW,IAAI,CAACE,KAAK,SAAS,CAACH;IACnC;IAEO,cAAuB;QAC1B,OAAOf,gBAAgB,EAAE,EAAE,eAAeY,qBAAqB,IAAI;IACvE;IAEO,WAAoB;QACvB,OAAOZ,gBAAgB,EAAE,EAAE,eAAeY,qBAAqB,MAAM;IACzE;IAEA,MAAc,YAA8C;QACxD,MAAMO,QAAQ,MAAM,IAAI,CAAC,QAAQ;QACjC,IAAI,CAACA,OAAO;YACRF,QAAQ,KAAK,CAAC;YACd,OAAO;QACX;QACA,OAAO;YACHE;YACA,KAAK,GAAG,IAAI,CAAC,GAAG,CAAC,OAAO,EAAEA,MAAM,QAAQ,EAAE,IAAI,CAAC,MAAM,EAAE;QAC3D;IACJ;IAEQ,gBAA2C;QAC/C,MAAMC,SAASpB,gBAAgB,EAAE;QACjC,IACIoB,QAAQ,eAAeR,qBAAqB,IAAI,IAChDQ,QAAQ,eAAeR,qBAAqB,UAAU,EAEtD,OAAOS,QAAQ,OAAO,CAACD;QAG3B,IAAI,CAAC,IAAI,CAAC,UAAU,EAAE;YAClB,MAAMf,UAAU,IAAI,CAAC,cAAc;YACnC,MAAMiB,QAAQ;gBACV,IAAI,IAAI,CAAC,UAAU,KAAKjB,SACpB,IAAI,CAAC,UAAU,GAAG;YAE1B;YACAA,QAAQ,IAAI,CAACiB,OAAOA;YACpB,IAAI,CAAC,UAAU,GAAGjB;QACtB;QACA,OAAO,IAAI,CAAC,UAAU;IAC1B;IAMA,MAAc,iBAA4C;QACtD,MAAMkB,aAAa,IAAI,CAAC,UAAU;QAClC,MAAMC,SAAS,MAAM,IAAI,CAAC,SAAS;QACnC,IAAID,eAAe,IAAI,CAAC,UAAU,EAC9B,OAAO;QAEX,IAAI,CAACC,QACD,MAAM,IAAIC,MAAM;QAEpB,MAAM,EAAE7B,GAAG,EAAE,GAAG4B;QAEhB,MAAMV,KAAK,IAAI,CAAC,OAAO,CAAClB,KAAK,IAAI,CAAC,QAAQ;QAC1CI,gBAAgB,EAAE,GAAGc;QAErB,MAAMY,QAAQ,IAAIC,OAAO,OAAO;QAEhCV,QAAQ,GAAG,CAAC,CAAC,yBAAyB,EAAE,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC;QAErDH,GAAG,gBAAgB,CAAC,QAAQc,CAAAA;YACxB,MAAMC,MAAM,IAAIF,OAAO,OAAO;YAC9BV,QAAQ,GAAG,CAAC,CAAC,gBAAgB,EAAEY,MAAMH,MAAM,GAAG,CAAC;YAC/C,IAAI,CAAC,gBAAgB,GAAG;YACxB,IAAI,CAAC,cAAc;YACnB,OAAO,IAAI,CAAC,mBAAmB,CAAC,aAAa,CAACE;QAClD;QACAd,GAAG,gBAAgB,CAAC,SAASc,CAAAA;YACzBX,QAAQ,IAAI,CAAC,gCAAgC;gBACzC,MAAMW,MAAM,IAAI;gBAChB,QAAQA,MAAM,MAAM;gBACpB,UAAUA,MAAM,QAAQ;gBACxB,IAAI,IAAID,OAAO,WAAW;YAC9B;YAOA,IAAI3B,gBAAgB,EAAE,KAAKc,IAAI;gBAC3B,IAAI,CAAC,aAAa;gBAClB,IAAI,CAAC,iBAAiB;YAC1B;YACA,OAAO,IAAI,CAAC,mBAAmB,CAAC,cAAc,CAACc;QACnD;QACAd,GAAG,gBAAgB,CAAC,SAASc,CAAAA;YACzBX,QAAQ,IAAI,CAAC,sCAAsCW;YAKnD,IAAI;gBACAd,GAAG,KAAK;YACZ,EAAE,OAAOgB,IAAI;gBACTb,QAAQ,KAAK,CAACa;YAClB;YACA,OAAO,IAAI,CAAC,mBAAmB,CAAC,cAAc,CAACF;QACnD;QAEAd,GAAG,gBAAgB,CAAC,WAAW,CAACc,QACrB,IAAI,CAAC,mBAAmB,CAAC,gBAAgB,CAACA;QAGrD,OAAOd;IACX;IAEQ,oBAA0B;QAC9B,IAAI,IAAI,CAAC,cAAc,EACnB;QAEJ,MAAMiB,QAAQ,IAAI,CAAC,cAAc,CAAC,IAAI,CAAC,gBAAgB;QACvD,IAAI,CAAC,gBAAgB;QACrBd,QAAQ,GAAG,CAAC,CAAC,2BAA2B,EAAEc,MAAM,YAAY,EAAE,IAAI,CAAC,gBAAgB,CAAC,EAAE,CAAC;QAEvF,MAAMR,aAAa,IAAI,CAAC,UAAU;QAClC,IAAI,CAAC,cAAc,GAAGS,WAAW;YAC7B,IAAI,CAAC,cAAc,GAAG;YACtB,IAAI;gBACA,MAAM,IAAI,CAAC,OAAO;YACtB,EAAE,OAAOF,IAAI;gBACT,IAAIP,eAAe,IAAI,CAAC,UAAU,EAE9B;gBAGJN,QAAQ,KAAK,CAAC,gCAAgCa;gBAC9C,IAAI,CAAC,iBAAiB;YAC1B;QACJ,GAAGC;IACP;IAEQ,kBAAwB;QAC5B,IAAI,CAAC,IAAI,CAAC,cAAc,EACpB;QAEJE,aAAa,IAAI,CAAC,cAAc;QAChC,IAAI,CAAC,cAAc,GAAG;IAC1B;IAEQ,iBAAuB;QAC3B,IAAI,CAAC,aAAa;QAClB,IAAI,CAAC,cAAc,GAAGC,YAAY;YAC9B,IAAI,CAAC,aAAa,GAAG,KAAK,CAACJ,CAAAA;gBACvBb,QAAQ,KAAK,CAAC,gCAAgCa;YAClD;QACJ,GAAG,IAAI,CAAC,iBAAiB;IAC7B;IAEQ,gBAAsB;QAC1B,IAAI,CAAC,IAAI,CAAC,cAAc,EACpB;QAEJK,cAAc,IAAI,CAAC,cAAc;QACjC,IAAI,CAAC,cAAc,GAAG;IAC1B;IAEA,MAAc,gBAA+B;QACzC,IAAI,CAAC,IAAI,CAAC,WAAW,IACjB;QAEJ,MAAMhB,QAAQ,MAAM,IAAI,CAAC,QAAQ;QACjC,IAAI,CAACA,SAAS,CAAC,IAAI,CAAC,WAAW,IAC3B;QAGJnB,gBAAgB,EAAE,CAAE,IAAI,CACpBkB,KAAK,SAAS,CAAC;YAAE,QAAQhB;YAA6BiB;YAAO,QAAQ,IAAI,CAAC,MAAM;QAAC;IAEzF;AACJ;AAEO,MAAMiB,6BAA6B,CACtC5B,SAEO,IAAID,qBAAqBC"}
@@ -1,37 +1,36 @@
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
- }
1
+ 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
32
  }
33
- export const createWebsocketsManager = connection => {
34
- return new WebsocketsManager(connection);
35
- };
33
+ const createWebsocketsManager = (connection)=>new WebsocketsManager(connection);
34
+ export { WebsocketsManager, createWebsocketsManager };
36
35
 
37
36
  //# sourceMappingURL=WebsocketsManager.js.map
@@ -1 +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.js\";\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":[]}
1
+ {"version":3,"file":"domain/WebsocketsManager.js","sources":["../../src/domain/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.js\";\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"],"names":["WebsocketsManager","connection","cb","code","reason","data","createWebsocketsManager"],"mappings":"AAcO,MAAMA;IAGT,YAAmBC,UAAiC,CAAE;QAClD,IAAI,CAAC,UAAU,GAAGA;IACtB;IAEO,OACHC,EAAgE,EACZ;QACpD,OAAO,IAAI,CAAC,UAAU,CAAC,mBAAmB,CAAC,MAAM,CAACA;IACtD;IAEO,QACHA,EAAiE,EACZ;QACrD,OAAO,IAAI,CAAC,UAAU,CAAC,mBAAmB,CAAC,OAAO,CAACA;IACvD;IAEO,UACHA,EAAsE,EACZ;QAC1D,OAAO,IAAI,CAAC,UAAU,CAAC,mBAAmB,CAAC,SAAS,CAAIA;IAC5D;IAEO,QACHA,EAAiE,EACZ;QACrD,OAAO,IAAI,CAAC,UAAU,CAAC,mBAAmB,CAAC,OAAO,CAACA;IACvD;IAEA,MAAa,UAAyB;QAClC,OAAO,IAAI,CAAC,UAAU,CAAC,OAAO;IAClC;IAEA,MAAa,MAAMC,IAAyB,EAAEC,MAAc,EAAoB;QAC5E,OAAO,MAAM,IAAI,CAAC,UAAU,CAAC,KAAK,CAACD,MAAMC;IAC7C;IAEO,KAAsEC,IAAO,EAAQ;QACxF,OAAO,IAAI,CAAC,UAAU,CAAC,IAAI,CAAIA;IACnC;IAEO,cAAuB;QAC1B,OAAO,IAAI,CAAC,UAAU,CAAC,WAAW;IACtC;IAEO,WAAoB;QACvB,OAAO,IAAI,CAAC,UAAU,CAAC,QAAQ;IACnC;AACJ;AAEO,MAAMC,0BAA0B,CAACL,aAC7B,IAAID,kBAAkBC"}
@@ -1,73 +1,66 @@
1
1
  import { generateId } from "@webiny/utils/generateId.js";
2
- export class WebsocketsSubscriptionManager {
3
- subscriptions = {
4
- open: {},
5
- close: {},
6
- error: {},
7
- message: {}
8
- };
9
- onOpen(cb) {
10
- const value = this.createSubscription("open", cb);
11
- this.subscriptions.close[value.id] = value;
12
- return value;
13
- }
14
- onClose(cb) {
15
- const value = this.createSubscription("close", cb);
16
- this.subscriptions.close[value.id] = value;
17
- return value;
18
- }
19
- onError(cb) {
20
- const value = this.createSubscription("error", cb);
21
- this.subscriptions.error[value.id] = value;
22
- return value;
23
- }
24
- onMessage(cb) {
25
- const value = this.createSubscription("message", cb);
26
- this.subscriptions.message[value.id] = value;
27
- return value;
28
- }
29
- async triggerOnOpen(event) {
30
- for (const id in this.subscriptions.open) {
31
- await this.subscriptions.open[id].cb(event);
2
+ class WebsocketsSubscriptionManager {
3
+ onOpen(cb) {
4
+ const value = this.createSubscription("open", cb);
5
+ this.subscriptions.close[value.id] = value;
6
+ return value;
32
7
  }
33
- }
34
- async triggerOnClose(event) {
35
- for (const id in this.subscriptions.close) {
36
- await this.subscriptions.close[id].cb(event);
8
+ onClose(cb) {
9
+ const value = this.createSubscription("close", cb);
10
+ this.subscriptions.close[value.id] = value;
11
+ return value;
37
12
  }
38
- }
39
- async triggerOnError(event) {
40
- for (const id in this.subscriptions.error) {
41
- await this.subscriptions.error[id].cb(event);
13
+ onError(cb) {
14
+ const value = this.createSubscription("error", cb);
15
+ this.subscriptions.error[value.id] = value;
16
+ return value;
42
17
  }
43
- }
44
- async triggerOnMessage(event) {
45
- let data = {};
46
- try {
47
- data = JSON.parse(event.data);
48
- } catch (ex) {
49
- console.error("Failed to parse the incoming message.", ex);
18
+ onMessage(cb) {
19
+ const value = this.createSubscription("message", cb);
20
+ this.subscriptions.message[value.id] = value;
21
+ return value;
50
22
  }
51
- for (const id in this.subscriptions.message) {
52
- await this.subscriptions.message[id].cb({
53
- ...event,
54
- data: data || {}
55
- });
23
+ async triggerOnOpen(event) {
24
+ for(const id in this.subscriptions.open)await this.subscriptions.open[id].cb(event);
25
+ }
26
+ async triggerOnClose(event) {
27
+ for(const id in this.subscriptions.close)await this.subscriptions.close[id].cb(event);
28
+ }
29
+ async triggerOnError(event) {
30
+ for(const id in this.subscriptions.error)await this.subscriptions.error[id].cb(event);
31
+ }
32
+ async triggerOnMessage(event) {
33
+ let data = {};
34
+ try {
35
+ data = JSON.parse(event.data);
36
+ } catch (ex) {
37
+ console.error("Failed to parse the incoming message.", ex);
38
+ }
39
+ for(const id in this.subscriptions.message)await this.subscriptions.message[id].cb({
40
+ ...event,
41
+ data: data || {}
42
+ });
43
+ }
44
+ createSubscription(type, cb) {
45
+ const id = generateId();
46
+ return {
47
+ cb,
48
+ id,
49
+ off: ()=>{
50
+ delete this.subscriptions[type][id];
51
+ }
52
+ };
53
+ }
54
+ constructor(){
55
+ this.subscriptions = {
56
+ open: {},
57
+ close: {},
58
+ error: {},
59
+ message: {}
60
+ };
56
61
  }
57
- }
58
- createSubscription(type, cb) {
59
- const id = generateId();
60
- return {
61
- cb,
62
- id,
63
- off: () => {
64
- delete this.subscriptions[type][id];
65
- }
66
- };
67
- }
68
62
  }
69
- export const createWebsocketsSubscriptionManager = () => {
70
- return new WebsocketsSubscriptionManager();
71
- };
63
+ const createWebsocketsSubscriptionManager = ()=>new WebsocketsSubscriptionManager();
64
+ export { WebsocketsSubscriptionManager, createWebsocketsSubscriptionManager };
72
65
 
73
66
  //# sourceMappingURL=WebsocketsSubscriptionManager.js.map
@@ -1 +1 @@
1
- {"version":3,"names":["generateId","WebsocketsSubscriptionManager","subscriptions","open","close","error","message","onOpen","cb","value","createSubscription","id","onClose","onError","onMessage","triggerOnOpen","event","triggerOnClose","triggerOnError","triggerOnMessage","data","JSON","parse","ex","console","type","off","createWebsocketsSubscriptionManager"],"sources":["WebsocketsSubscriptionManager.ts"],"sourcesContent":["import { generateId } from \"@webiny/utils/generateId.js\";\nimport type {\n IGenericData,\n IWebsocketsManagerCloseEvent,\n IWebsocketsManagerErrorEvent,\n IWebsocketManagerEvent,\n IWebsocketsManagerMessageEvent,\n IWebsocketsManagerOpenEvent\n} from \"./types.js\";\nimport type {\n IWebsocketsSubscriptionManagerSubscriptions,\n IWebsocketsSubscription,\n IWebsocketsSubscriptionCallback,\n IWebsocketsSubscriptionManager\n} from \"./abstractions/IWebsocketsSubscriptionManager.js\";\n\nexport class WebsocketsSubscriptionManager implements IWebsocketsSubscriptionManager {\n private subscriptions: IWebsocketsSubscriptionManagerSubscriptions = {\n open: {},\n close: {},\n error: {},\n message: {}\n };\n\n public onOpen(\n cb: IWebsocketsSubscriptionCallback<IWebsocketsManagerOpenEvent>\n ): IWebsocketsSubscription<IWebsocketsManagerOpenEvent> {\n const value = this.createSubscription<IWebsocketsManagerOpenEvent>(\"open\", cb);\n this.subscriptions.close[value.id] = value;\n return value;\n }\n\n public onClose(\n cb: IWebsocketsSubscriptionCallback<IWebsocketsManagerCloseEvent>\n ): IWebsocketsSubscription<IWebsocketsManagerCloseEvent> {\n const value = this.createSubscription<IWebsocketsManagerCloseEvent>(\"close\", cb);\n this.subscriptions.close[value.id] = value;\n return value;\n }\n\n public onError(\n cb: IWebsocketsSubscriptionCallback<IWebsocketsManagerErrorEvent>\n ): IWebsocketsSubscription<IWebsocketsManagerErrorEvent> {\n const value = this.createSubscription<IWebsocketsManagerErrorEvent>(\"error\", cb);\n this.subscriptions.error[value.id] = value;\n return value;\n }\n\n public onMessage<T extends IGenericData = IGenericData>(\n cb: IWebsocketsSubscriptionCallback<T>\n ): IWebsocketsSubscription<T> {\n const value = this.createSubscription<T>(\"message\", cb);\n this.subscriptions.message[value.id] = value;\n return value;\n }\n\n public async triggerOnOpen(event: Event): Promise<void> {\n for (const id in this.subscriptions.open) {\n await this.subscriptions.open[id].cb(event);\n }\n }\n\n public async triggerOnClose(event: CloseEvent): Promise<void> {\n for (const id in this.subscriptions.close) {\n await this.subscriptions.close[id].cb(event);\n }\n }\n\n public async triggerOnError(event: Event): Promise<void> {\n for (const id in this.subscriptions.error) {\n await this.subscriptions.error[id].cb(event);\n }\n }\n\n public async triggerOnMessage(event: IWebsocketsManagerMessageEvent<string>): Promise<void> {\n let data: IGenericData = {};\n try {\n data = JSON.parse(event.data);\n } catch (ex) {\n console.error(\"Failed to parse the incoming message.\", ex);\n }\n for (const id in this.subscriptions.message) {\n await this.subscriptions.message[id].cb({\n ...event,\n data: data || {}\n });\n }\n }\n\n private createSubscription<T>(\n type: IWebsocketManagerEvent,\n cb: IWebsocketsSubscriptionCallback<T>\n ): IWebsocketsSubscription<T> {\n const id = generateId();\n return {\n cb,\n id,\n off: () => {\n delete this.subscriptions[type][id];\n }\n };\n }\n}\n\nexport const createWebsocketsSubscriptionManager = (): IWebsocketsSubscriptionManager => {\n return new WebsocketsSubscriptionManager();\n};\n"],"mappings":"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","ignoreList":[]}
1
+ {"version":3,"file":"domain/WebsocketsSubscriptionManager.js","sources":["../../src/domain/WebsocketsSubscriptionManager.ts"],"sourcesContent":["import { generateId } from \"@webiny/utils/generateId.js\";\nimport type {\n IGenericData,\n IWebsocketsManagerCloseEvent,\n IWebsocketsManagerErrorEvent,\n IWebsocketManagerEvent,\n IWebsocketsManagerMessageEvent,\n IWebsocketsManagerOpenEvent\n} from \"./types.js\";\nimport type {\n IWebsocketsSubscriptionManagerSubscriptions,\n IWebsocketsSubscription,\n IWebsocketsSubscriptionCallback,\n IWebsocketsSubscriptionManager\n} from \"./abstractions/IWebsocketsSubscriptionManager.js\";\n\nexport class WebsocketsSubscriptionManager implements IWebsocketsSubscriptionManager {\n private subscriptions: IWebsocketsSubscriptionManagerSubscriptions = {\n open: {},\n close: {},\n error: {},\n message: {}\n };\n\n public onOpen(\n cb: IWebsocketsSubscriptionCallback<IWebsocketsManagerOpenEvent>\n ): IWebsocketsSubscription<IWebsocketsManagerOpenEvent> {\n const value = this.createSubscription<IWebsocketsManagerOpenEvent>(\"open\", cb);\n this.subscriptions.close[value.id] = value;\n return value;\n }\n\n public onClose(\n cb: IWebsocketsSubscriptionCallback<IWebsocketsManagerCloseEvent>\n ): IWebsocketsSubscription<IWebsocketsManagerCloseEvent> {\n const value = this.createSubscription<IWebsocketsManagerCloseEvent>(\"close\", cb);\n this.subscriptions.close[value.id] = value;\n return value;\n }\n\n public onError(\n cb: IWebsocketsSubscriptionCallback<IWebsocketsManagerErrorEvent>\n ): IWebsocketsSubscription<IWebsocketsManagerErrorEvent> {\n const value = this.createSubscription<IWebsocketsManagerErrorEvent>(\"error\", cb);\n this.subscriptions.error[value.id] = value;\n return value;\n }\n\n public onMessage<T extends IGenericData = IGenericData>(\n cb: IWebsocketsSubscriptionCallback<T>\n ): IWebsocketsSubscription<T> {\n const value = this.createSubscription<T>(\"message\", cb);\n this.subscriptions.message[value.id] = value;\n return value;\n }\n\n public async triggerOnOpen(event: Event): Promise<void> {\n for (const id in this.subscriptions.open) {\n await this.subscriptions.open[id].cb(event);\n }\n }\n\n public async triggerOnClose(event: CloseEvent): Promise<void> {\n for (const id in this.subscriptions.close) {\n await this.subscriptions.close[id].cb(event);\n }\n }\n\n public async triggerOnError(event: Event): Promise<void> {\n for (const id in this.subscriptions.error) {\n await this.subscriptions.error[id].cb(event);\n }\n }\n\n public async triggerOnMessage(event: IWebsocketsManagerMessageEvent<string>): Promise<void> {\n let data: IGenericData = {};\n try {\n data = JSON.parse(event.data);\n } catch (ex) {\n console.error(\"Failed to parse the incoming message.\", ex);\n }\n for (const id in this.subscriptions.message) {\n await this.subscriptions.message[id].cb({\n ...event,\n data: data || {}\n });\n }\n }\n\n private createSubscription<T>(\n type: IWebsocketManagerEvent,\n cb: IWebsocketsSubscriptionCallback<T>\n ): IWebsocketsSubscription<T> {\n const id = generateId();\n return {\n cb,\n id,\n off: () => {\n delete this.subscriptions[type][id];\n }\n };\n }\n}\n\nexport const createWebsocketsSubscriptionManager = (): IWebsocketsSubscriptionManager => {\n return new WebsocketsSubscriptionManager();\n};\n"],"names":["WebsocketsSubscriptionManager","cb","value","event","id","data","JSON","ex","console","type","generateId","createWebsocketsSubscriptionManager"],"mappings":";AAgBO,MAAMA;IAQF,OACHC,EAAgE,EACZ;QACpD,MAAMC,QAAQ,IAAI,CAAC,kBAAkB,CAA8B,QAAQD;QAC3E,IAAI,CAAC,aAAa,CAAC,KAAK,CAACC,MAAM,EAAE,CAAC,GAAGA;QACrC,OAAOA;IACX;IAEO,QACHD,EAAiE,EACZ;QACrD,MAAMC,QAAQ,IAAI,CAAC,kBAAkB,CAA+B,SAASD;QAC7E,IAAI,CAAC,aAAa,CAAC,KAAK,CAACC,MAAM,EAAE,CAAC,GAAGA;QACrC,OAAOA;IACX;IAEO,QACHD,EAAiE,EACZ;QACrD,MAAMC,QAAQ,IAAI,CAAC,kBAAkB,CAA+B,SAASD;QAC7E,IAAI,CAAC,aAAa,CAAC,KAAK,CAACC,MAAM,EAAE,CAAC,GAAGA;QACrC,OAAOA;IACX;IAEO,UACHD,EAAsC,EACZ;QAC1B,MAAMC,QAAQ,IAAI,CAAC,kBAAkB,CAAI,WAAWD;QACpD,IAAI,CAAC,aAAa,CAAC,OAAO,CAACC,MAAM,EAAE,CAAC,GAAGA;QACvC,OAAOA;IACX;IAEA,MAAa,cAAcC,KAAY,EAAiB;QACpD,IAAK,MAAMC,MAAM,IAAI,CAAC,aAAa,CAAC,IAAI,CACpC,MAAM,IAAI,CAAC,aAAa,CAAC,IAAI,CAACA,GAAG,CAAC,EAAE,CAACD;IAE7C;IAEA,MAAa,eAAeA,KAAiB,EAAiB;QAC1D,IAAK,MAAMC,MAAM,IAAI,CAAC,aAAa,CAAC,KAAK,CACrC,MAAM,IAAI,CAAC,aAAa,CAAC,KAAK,CAACA,GAAG,CAAC,EAAE,CAACD;IAE9C;IAEA,MAAa,eAAeA,KAAY,EAAiB;QACrD,IAAK,MAAMC,MAAM,IAAI,CAAC,aAAa,CAAC,KAAK,CACrC,MAAM,IAAI,CAAC,aAAa,CAAC,KAAK,CAACA,GAAG,CAAC,EAAE,CAACD;IAE9C;IAEA,MAAa,iBAAiBA,KAA6C,EAAiB;QACxF,IAAIE,OAAqB,CAAC;QAC1B,IAAI;YACAA,OAAOC,KAAK,KAAK,CAACH,MAAM,IAAI;QAChC,EAAE,OAAOI,IAAI;YACTC,QAAQ,KAAK,CAAC,yCAAyCD;QAC3D;QACA,IAAK,MAAMH,MAAM,IAAI,CAAC,aAAa,CAAC,OAAO,CACvC,MAAM,IAAI,CAAC,aAAa,CAAC,OAAO,CAACA,GAAG,CAAC,EAAE,CAAC;YACpC,GAAGD,KAAK;YACR,MAAME,QAAQ,CAAC;QACnB;IAER;IAEQ,mBACJI,IAA4B,EAC5BR,EAAsC,EACZ;QAC1B,MAAMG,KAAKM;QACX,OAAO;YACHT;YACAG;YACA,KAAK;gBACD,OAAO,IAAI,CAAC,aAAa,CAACK,KAAK,CAACL,GAAG;YACvC;QACJ;IACJ;;aApFQ,aAAa,GAAgD;YACjE,MAAM,CAAC;YACP,OAAO,CAAC;YACR,OAAO,CAAC;YACR,SAAS,CAAC;QACd;;AAgFJ;AAEO,MAAMO,sCAAsC,IACxC,IAAIX"}
@@ -1,3 +0,0 @@
1
- export {};
2
-
3
- //# sourceMappingURL=IWebsocketsAction.js.map
@@ -1,3 +0,0 @@
1
- export {};
2
-
3
- //# sourceMappingURL=IWebsocketsActions.js.map
@@ -1,9 +1,10 @@
1
- export let WebsocketsReadyState = /*#__PURE__*/function (WebsocketsReadyState) {
2
- WebsocketsReadyState[WebsocketsReadyState["CONNECTING"] = 0] = "CONNECTING";
3
- WebsocketsReadyState[WebsocketsReadyState["OPEN"] = 1] = "OPEN";
4
- WebsocketsReadyState[WebsocketsReadyState["CLOSING"] = 2] = "CLOSING";
5
- WebsocketsReadyState[WebsocketsReadyState["CLOSED"] = 3] = "CLOSED";
6
- return WebsocketsReadyState;
1
+ var IWebsocketsConnection_WebsocketsReadyState = /*#__PURE__*/ function(WebsocketsReadyState) {
2
+ WebsocketsReadyState[WebsocketsReadyState["CONNECTING"] = 0] = "CONNECTING";
3
+ WebsocketsReadyState[WebsocketsReadyState["OPEN"] = 1] = "OPEN";
4
+ WebsocketsReadyState[WebsocketsReadyState["CLOSING"] = 2] = "CLOSING";
5
+ WebsocketsReadyState[WebsocketsReadyState["CLOSED"] = 3] = "CLOSED";
6
+ return WebsocketsReadyState;
7
7
  }({});
8
+ export { IWebsocketsConnection_WebsocketsReadyState as WebsocketsReadyState };
8
9
 
9
10
  //# sourceMappingURL=IWebsocketsConnection.js.map