@webiny/app-websockets 6.4.12-beta.5 → 6.5.0-beta.1

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.
@@ -1,6 +1,8 @@
1
1
  import react, { useCallback, useEffect, useMemo, useRef, useState } from "react";
2
2
  import { useFeature, useTenantContext } from "@webiny/app-admin";
3
3
  import { AuthenticationContextFeature } from "@webiny/app-admin/features/security/AuthenticationContext/feature.js";
4
+ import { EventPublisherFeature } from "@webiny/app/features/eventPublisher/feature.js";
5
+ import { WebsocketEvent } from "./events/WebsocketEvent.js";
4
6
  import { WebsocketsCloseCode } from "./types.js";
5
7
  import { createWebsocketsAction, createWebsocketsActions, createWebsocketsConnection, createWebsocketsManager, createWebsocketsSubscriptionManager } from "./domain/index.js";
6
8
  import { getUrl } from "./utils/getUrl.js";
@@ -8,6 +10,7 @@ const WebsocketsContext = /*#__PURE__*/ react.createContext(void 0);
8
10
  const WebsocketsContextProvider = (props)=>{
9
11
  const { tenant } = useTenantContext();
10
12
  const { authenticationContext } = useFeature(AuthenticationContextFeature);
13
+ const { eventPublisher } = useFeature(EventPublisherFeature);
11
14
  const socketsRef = useRef(null);
12
15
  const [current, setCurrent] = useState({});
13
16
  const getToken = useCallback(async ()=>await authenticationContext.getIdToken(), [
@@ -21,7 +24,7 @@ const WebsocketsContextProvider = (props)=>{
21
24
  currentIteration++;
22
25
  setTimeout(()=>{
23
26
  if (!socketsRef.current) return;
24
- else if (socketsRef.current.isClosed()) {
27
+ if (socketsRef.current.isClosed()) {
25
28
  console.log("Running auto-reconnect.");
26
29
  socketsRef.current.connect();
27
30
  }
@@ -33,7 +36,7 @@ const WebsocketsContextProvider = (props)=>{
33
36
  const abortController = new AbortController();
34
37
  window.addEventListener("focus", ()=>{
35
38
  if (!socketsRef.current) return;
36
- else if (socketsRef.current.isClosed()) {
39
+ if (socketsRef.current.isClosed()) {
37
40
  console.log("Running auto-reconnect on focus.");
38
41
  socketsRef.current.connect();
39
42
  }
@@ -56,8 +59,8 @@ const WebsocketsContextProvider = (props)=>{
56
59
  (async ()=>{
57
60
  const token = await getToken();
58
61
  if (!token || !tenant) return;
59
- else if (current.tenant === tenant) return;
60
- else if (socketsRef.current) await socketsRef.current.close(WebsocketsCloseCode.NORMAL, "Changing tenant.");
62
+ if (current.tenant === tenant) return;
63
+ if (socketsRef.current) await socketsRef.current.close(WebsocketsCloseCode.NORMAL, "Changing tenant.");
61
64
  const url = getUrl();
62
65
  if (!url) return void console.error("Not possible to connect to the websocket without a valid URL.", {
63
66
  tenant,
@@ -82,6 +85,18 @@ const WebsocketsContextProvider = (props)=>{
82
85
  subscriptionManager,
83
86
  getToken
84
87
  ]);
88
+ useEffect(()=>{
89
+ if (!socketsRef.current) return;
90
+ const subscription = socketsRef.current.onMessage(async (event)=>{
91
+ await eventPublisher.publish(new WebsocketEvent(event.data));
92
+ });
93
+ return ()=>{
94
+ subscription.off();
95
+ };
96
+ }, [
97
+ current.tenant,
98
+ eventPublisher
99
+ ]);
85
100
  const websocketActions = useMemo(()=>createWebsocketsActions({
86
101
  manager: socketsRef.current,
87
102
  tenant,
@@ -1 +1 @@
1
- {"version":3,"file":"WebsocketsContextProvider.js","sources":["../src/WebsocketsContextProvider.tsx"],"sourcesContent":["import React, { useCallback, useEffect, useMemo, useRef, useState } from \"react\";\nimport { useFeature, useTenantContext } from \"@webiny/app-admin\";\nimport { AuthenticationContextFeature } from \"@webiny/app-admin/features/security/AuthenticationContext/feature.js\";\nimport type {\n IncomingGenericData,\n IWebsocketsContext,\n IWebsocketsContextSendCallable,\n IWebsocketsManagerCloseEvent,\n IWebsocketsManagerErrorEvent\n} from \"~/types.js\";\nimport { WebsocketsCloseCode } from \"~/types.js\";\nimport {\n createWebsocketsAction,\n createWebsocketsActions,\n createWebsocketsConnection,\n createWebsocketsManager,\n createWebsocketsSubscriptionManager\n} from \"./domain/index.js\";\nimport type { IGenericData, IWebsocketsManager } from \"./domain/types.js\";\nimport { getUrl } from \"./utils/getUrl.js\";\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}\n\nexport const WebsocketsContextProvider = (props: IWebsocketsContextProviderProps) => {\n const { tenant } = useTenantContext();\n const { authenticationContext } = useFeature(AuthenticationContextFeature);\n\n const socketsRef = useRef<IWebsocketsManager | null>(null);\n\n const [current, setCurrent] = useState<ICurrentData>({});\n\n const getToken = useCallback(async () => {\n return await authenticationContext.getIdToken();\n }, [authenticationContext]);\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) {\n return;\n } else if (current.tenant === tenant) {\n return;\n } else if (socketsRef.current) {\n await socketsRef.current.close(WebsocketsCloseCode.NORMAL, \"Changing tenant.\");\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 token\n });\n return;\n }\n\n socketsRef.current = createWebsocketsManager(\n createWebsocketsConnection({\n subscriptionManager,\n url,\n tenant,\n getToken,\n protocol: [\"webiny-ws-v1\"]\n })\n );\n await socketsRef.current.connect();\n\n setCurrent({ tenant });\n })();\n }, [tenant, subscriptionManager, getToken]);\n\n const websocketActions = useMemo(() => {\n return createWebsocketsActions({\n manager: socketsRef.current!,\n tenant,\n getToken\n });\n }, [socketsRef.current, tenant, 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"],"names":["WebsocketsContext","React","undefined","WebsocketsContextProvider","props","tenant","useTenantContext","authenticationContext","useFeature","AuthenticationContextFeature","socketsRef","useRef","current","setCurrent","useState","getToken","useCallback","subscriptionManager","useMemo","manager","createWebsocketsSubscriptionManager","currentIteration","event","WebsocketsCloseCode","setTimeout","console","useEffect","abortController","AbortController","window","CloseEvent","token","url","getUrl","createWebsocketsManager","createWebsocketsConnection","websocketActions","createWebsocketsActions","send","action","data","timeout","createAction","name","createWebsocketsAction","onMessage","cb","onError","onClose","value"],"mappings":"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"}
1
+ {"version":3,"file":"WebsocketsContextProvider.js","sources":["../src/WebsocketsContextProvider.tsx"],"sourcesContent":["import React, { useCallback, useEffect, useMemo, useRef, useState } from \"react\";\nimport { useFeature, useTenantContext } from \"@webiny/app-admin\";\nimport { AuthenticationContextFeature } from \"@webiny/app-admin/features/security/AuthenticationContext/feature.js\";\nimport { EventPublisherFeature } from \"@webiny/app/features/eventPublisher/feature.js\";\nimport { WebsocketEvent } from \"./events/WebsocketEvent.js\";\nimport type {\n IncomingGenericData,\n IWebsocketsContext,\n IWebsocketsContextSendCallable,\n IWebsocketsManagerCloseEvent,\n IWebsocketsManagerErrorEvent\n} from \"~/types.js\";\nimport { WebsocketsCloseCode } from \"~/types.js\";\nimport {\n createWebsocketsAction,\n createWebsocketsActions,\n createWebsocketsConnection,\n createWebsocketsManager,\n createWebsocketsSubscriptionManager\n} from \"./domain/index.js\";\nimport type { IGenericData, IWebsocketsManager } from \"./domain/types.js\";\nimport { getUrl } from \"./utils/getUrl.js\";\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}\n\nexport const WebsocketsContextProvider = (props: IWebsocketsContextProviderProps) => {\n const { tenant } = useTenantContext();\n const { authenticationContext } = useFeature(AuthenticationContextFeature);\n const { eventPublisher } = useFeature(EventPublisherFeature);\n\n const socketsRef = useRef<IWebsocketsManager | null>(null);\n\n const [current, setCurrent] = useState<ICurrentData>({});\n\n const getToken = useCallback(async () => {\n return await authenticationContext.getIdToken();\n }, [authenticationContext]);\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) {\n return;\n } else if (current.tenant === tenant) {\n return;\n } else if (socketsRef.current) {\n await socketsRef.current.close(WebsocketsCloseCode.NORMAL, \"Changing tenant.\");\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 token\n });\n return;\n }\n\n socketsRef.current = createWebsocketsManager(\n createWebsocketsConnection({\n subscriptionManager,\n url,\n tenant,\n getToken,\n protocol: [\"webiny-ws-v1\"]\n })\n );\n await socketsRef.current.connect();\n\n setCurrent({ tenant });\n })();\n }, [tenant, subscriptionManager, getToken]);\n\n /**\n * Bridge: subscribe once to ALL incoming websocket messages and re-publish each one through\n * the EventPublisher as a `WebsocketEvent`. Feature code registers `WebsocketEventHandler`\n * handlers instead of subscribing to the websocket service directly.\n */\n useEffect(() => {\n if (!socketsRef.current) {\n return;\n }\n const subscription = socketsRef.current.onMessage<IncomingGenericData>(async event => {\n await eventPublisher.publish(new WebsocketEvent(event.data));\n });\n return () => {\n subscription.off();\n };\n }, [current.tenant, eventPublisher]);\n\n const websocketActions = useMemo(() => {\n return createWebsocketsActions({\n manager: socketsRef.current!,\n tenant,\n getToken\n });\n }, [socketsRef.current, tenant, 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"],"names":["WebsocketsContext","React","undefined","WebsocketsContextProvider","props","tenant","useTenantContext","authenticationContext","useFeature","AuthenticationContextFeature","eventPublisher","EventPublisherFeature","socketsRef","useRef","current","setCurrent","useState","getToken","useCallback","subscriptionManager","useMemo","manager","createWebsocketsSubscriptionManager","currentIteration","event","WebsocketsCloseCode","setTimeout","console","useEffect","abortController","AbortController","window","CloseEvent","token","url","getUrl","createWebsocketsManager","createWebsocketsConnection","subscription","WebsocketEvent","websocketActions","createWebsocketsActions","send","action","data","timeout","createAction","name","createWebsocketsAction","onMessage","cb","onError","onClose","value"],"mappings":"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"}
@@ -52,7 +52,7 @@ class WebsocketsConnection {
52
52
  }
53
53
  async getConnection() {
54
54
  if (connectionCache.ws?.readyState === WebsocketsReadyState.OPEN) return connectionCache.ws;
55
- else if (connectionCache.ws?.readyState === WebsocketsReadyState.CONNECTING) return connectionCache.ws;
55
+ if (connectionCache.ws?.readyState === WebsocketsReadyState.CONNECTING) return connectionCache.ws;
56
56
  const result = await this.createUrl();
57
57
  if (!result) throw new Error("Missing URL for WebSocket to connect to.");
58
58
  const { url } = result;
@@ -1 +1 @@
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\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"],"names":["defaultFactory","url","protocol","WebSocket","window","connectionCache","WebsocketsConnection","params","tenant","code","reason","WebsocketsReadyState","undefined","data","connection","console","JSON","token","result","Error","start","Date","event","end","ex","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;AAWvD,MAAME;IAQT,YAAmBC,MAAmC,CAAE;QACpD,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,IAAIP;IACrC;IAEO,UAAUQ,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,IACI,CAACL,gBAAgB,EAAE,IACnBA,gBAAgB,EAAE,CAAC,UAAU,KAAKM,qBAAqB,MAAM,IAC7DN,gBAAgB,EAAE,CAAC,UAAU,KAAKM,qBAAqB,OAAO,EAChE;YACEN,gBAAgB,EAAE,GAAGO;YAErB,OAAO;QACX;QACAP,gBAAgB,EAAE,CAAC,KAAK,CAACI,MAAMC;QAE/BL,gBAAgB,EAAE,GAAGO;QACrB,OAAO;IACX;IAEA,MAAa,KAA4CC,IAAO,EAAiB;QAC7E,MAAMC,aAAa,MAAM,IAAI,CAAC,aAAa;QAC3C,IAAIA,WAAW,UAAU,KAAKH,qBAAqB,IAAI,EAAE,YACrDI,QAAQ,IAAI,CAAC,2DAA2DF;QAG5EC,WAAW,IAAI,CAACE,KAAK,SAAS,CAACH;IACnC;IAEO,cAAuB;QAC1B,OAAOR,gBAAgB,EAAE,EAAE,eAAeM,qBAAqB,IAAI;IACvE;IAEO,WAAoB;QACvB,OAAON,gBAAgB,EAAE,EAAE,eAAeM,qBAAqB,MAAM;IACzE;IAEA,MAAc,YAA8C;QACxD,MAAMM,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;IAEA,MAAc,gBAAoC;QAC9C,IAAIZ,gBAAgB,EAAE,EAAE,eAAeM,qBAAqB,IAAI,EAC5D,OAAON,gBAAgB,EAAE;aACtB,IAAIA,gBAAgB,EAAE,EAAE,eAAeM,qBAAqB,UAAU,EACzE,OAAON,gBAAgB,EAAE;QAG7B,MAAMa,SAAS,MAAM,IAAI,CAAC,SAAS;QACnC,IAAI,CAACA,QACD,MAAM,IAAIC,MAAM;QAEpB,MAAM,EAAElB,GAAG,EAAE,GAAGiB;QAEhBb,gBAAgB,EAAE,GAAG,IAAI,CAAC,OAAO,CAACJ,KAAK,IAAI,CAAC,QAAQ;QAEpD,MAAMmB,QAAQ,IAAIC,OAAO,OAAO;QAEhCN,QAAQ,GAAG,CAAC,CAAC,yBAAyB,EAAE,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC;QAErDV,gBAAgB,EAAE,CAAC,gBAAgB,CAAC,QAAQiB,CAAAA;YACxC,MAAMC,MAAM,IAAIF,OAAO,OAAO;YAC9BN,QAAQ,GAAG,CAAC,CAAC,gBAAgB,EAAEQ,MAAMH,MAAM,GAAG,CAAC;YAC/C,OAAO,IAAI,CAAC,mBAAmB,CAAC,aAAa,CAACE;QAClD;QACAjB,gBAAgB,EAAE,CAAC,gBAAgB,CAAC,SAASiB,CAAAA,QAClC,IAAI,CAAC,mBAAmB,CAAC,cAAc,CAACA;QAEnDjB,gBAAgB,EAAE,CAAC,gBAAgB,CAAC,SAASiB,CAAAA;YACzCP,QAAQ,IAAI,CAAC,sCAAsCO;YAKnD,IAAIjB,gBAAgB,EAAE,EAAE,OACpB,IAAI;gBACAA,gBAAgB,EAAE,CAAC,KAAK;YAC5B,EAAE,OAAOmB,IAAI;gBACTT,QAAQ,KAAK,CAACS;YAClB;YAEJ,OAAO,IAAI,CAAC,mBAAmB,CAAC,cAAc,CAACF;QACnD;QAEAjB,gBAAgB,EAAE,CAAC,gBAAgB,CAC/B,WACA,CAACiB,QACU,IAAI,CAAC,mBAAmB,CAAC,gBAAgB,CAACA;QAIzD,OAAOjB,gBAAgB,EAAE;IAC7B;AACJ;AAEO,MAAMoB,6BAA6B,CACtClB,SAEO,IAAID,qBAAqBC"}
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\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"],"names":["defaultFactory","url","protocol","WebSocket","window","connectionCache","WebsocketsConnection","params","tenant","code","reason","WebsocketsReadyState","undefined","data","connection","console","JSON","token","result","Error","start","Date","event","end","ex","createWebsocketsConnection"],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"domain/abstractions/IWebsocketsConnection.js","sources":["../../../src/domain/abstractions/IWebsocketsConnection.ts"],"sourcesContent":["import type { IWebsocketsSubscriptionManager } from \"./IWebsocketsSubscriptionManager.js\";\nimport type { IGenericData, WebsocketsCloseCode } from \"./types.js\";\n\nexport type IWebsocketsConnectProtocol = string | string[] | undefined;\n\nexport interface IWebsocketsConnectionFactory {\n (url: string, protocol?: IWebsocketsConnectProtocol): WebSocket;\n}\n\nexport enum WebsocketsReadyState {\n CONNECTING = 0,\n OPEN = 1,\n CLOSING = 2,\n CLOSED = 3\n}\n\nexport interface IWebsocketsConnection {\n readonly subscriptionManager: IWebsocketsSubscriptionManager;\n\n isConnected(): boolean;\n isClosed(): boolean;\n\n connect(): Promise<void>;\n close(code: WebsocketsCloseCode, reason: string): Promise<boolean>;\n send<T extends IGenericData = IGenericData>(data: T): void;\n}\n"],"names":["WebsocketsReadyState"],"mappings":"AASO,IAAKA,6CAAoBA,WAAAA,GAAAA,SAApBA,oBAAoB;8DACf;wDACN;2DACG;0DACD;WAJDA"}
1
+ {"version":3,"file":"domain/abstractions/IWebsocketsConnection.js","sources":["../../../src/domain/abstractions/IWebsocketsConnection.ts"],"sourcesContent":["import type { IWebsocketsSubscriptionManager } from \"./IWebsocketsSubscriptionManager.js\";\nimport type { IGenericData, WebsocketsCloseCode } from \"./types.js\";\n\nexport type IWebsocketsConnectProtocol = string | string[] | undefined;\n\nexport interface IWebsocketsConnectionFactory {\n (url: string, protocol?: IWebsocketsConnectProtocol): WebSocket;\n}\n\nexport enum WebsocketsReadyState {\n CONNECTING = 0,\n OPEN = 1,\n CLOSING = 2,\n CLOSED = 3\n}\n\nexport interface IWebsocketsConnection {\n readonly subscriptionManager: IWebsocketsSubscriptionManager;\n\n isConnected(): boolean;\n isClosed(): boolean;\n\n connect(): Promise<void>;\n close(code: WebsocketsCloseCode, reason: string): Promise<boolean>;\n send<T extends IGenericData = IGenericData>(data: T): void;\n}\n"],"names":["WebsocketsReadyState"],"mappings":"AASO,IAAKA,6CAAoBA,WAAAA,GAAAA,SAApBA,oBAAoB;;;;;WAApBA"}
@@ -1 +1 @@
1
- {"version":3,"file":"domain/abstractions/types.js","sources":["../../../src/domain/abstractions/types.ts"],"sourcesContent":["import type { GenericRecord } from \"@webiny/app/types.js\";\n\nexport type IWebsocketsManagerMessageEvent<T = IGenericData> = MessageEvent<T>;\nexport type IWebsocketsManagerCloseEvent = CloseEvent;\nexport type IWebsocketsManagerOpenEvent = Event;\nexport type IWebsocketsManagerErrorEvent = Event;\n\nexport type IGenericData = GenericRecord;\n\nexport enum WebsocketsCloseCode {\n NORMAL = 1000,\n GOING_AWAY = 1001,\n PROTOCOL_ERROR = 1002,\n CANNOT_ACCEPT = 1003,\n RESERVED = 1004,\n NO_STATUS = 1005,\n ABNORMAL = 1006,\n INVALID_DATA = 1007,\n POLICY_VIOLATION = 1008,\n TOO_BIG = 1009,\n MISSING_EXTENSION = 1010,\n SERVER_ERROR = 1011,\n SERVICE_RESTART = 1012,\n TRY_AGAIN_LATER = 1013,\n BAD_GATEWAY = 1014,\n TLS_HANDSHAKE = 1015\n}\n"],"names":["WebsocketsCloseCode"],"mappings":"AASO,IAAKA,4BAAmBA,WAAAA,GAAAA,SAAnBA,mBAAmB;wDAClB;4DACI;gEACI;+DACD;0DACL;2DACC;0DACD;8DACI;kEACI;yDACT;mEACU;8DACL;iEACG;iEACA;6DACJ;+DACE;WAhBRA"}
1
+ {"version":3,"file":"domain/abstractions/types.js","sources":["../../../src/domain/abstractions/types.ts"],"sourcesContent":["import type { GenericRecord } from \"@webiny/app/types.js\";\n\nexport type IWebsocketsManagerMessageEvent<T = IGenericData> = MessageEvent<T>;\nexport type IWebsocketsManagerCloseEvent = CloseEvent;\nexport type IWebsocketsManagerOpenEvent = Event;\nexport type IWebsocketsManagerErrorEvent = Event;\n\nexport type IGenericData = GenericRecord;\n\nexport enum WebsocketsCloseCode {\n NORMAL = 1000,\n GOING_AWAY = 1001,\n PROTOCOL_ERROR = 1002,\n CANNOT_ACCEPT = 1003,\n RESERVED = 1004,\n NO_STATUS = 1005,\n ABNORMAL = 1006,\n INVALID_DATA = 1007,\n POLICY_VIOLATION = 1008,\n TOO_BIG = 1009,\n MISSING_EXTENSION = 1010,\n SERVER_ERROR = 1011,\n SERVICE_RESTART = 1012,\n TRY_AGAIN_LATER = 1013,\n BAD_GATEWAY = 1014,\n TLS_HANDSHAKE = 1015\n}\n"],"names":["WebsocketsCloseCode"],"mappings":"AASO,IAAKA,4BAAmBA,WAAAA,GAAAA,SAAnBA,mBAAmB;;;;;;;;;;;;;;;;;WAAnBA"}
@@ -0,0 +1,10 @@
1
+ import { BaseEvent } from "@webiny/app/features/eventPublisher/index.js";
2
+ import type { IncomingGenericData } from "../types.js";
3
+ /**
4
+ * Published for every incoming websocket message. Carries the raw message data
5
+ * (which always includes an `action`), and routes to `WebsocketEventHandler` handlers.
6
+ */
7
+ export declare class WebsocketEvent extends BaseEvent<IncomingGenericData> {
8
+ readonly eventType: "Websockets/MessageReceived";
9
+ getHandlerAbstraction(): import("@webiny/di").Abstraction<import("@webiny/app/features/eventPublisher/abstractions.js").IEventHandler<WebsocketEvent>>;
10
+ }
@@ -0,0 +1,13 @@
1
+ import { BaseEvent } from "@webiny/app/features/eventPublisher/index.js";
2
+ import { WebsocketEventHandler } from "./abstractions.js";
3
+ class WebsocketEvent extends BaseEvent {
4
+ getHandlerAbstraction() {
5
+ return WebsocketEventHandler;
6
+ }
7
+ constructor(...args){
8
+ super(...args), this.eventType = "Websockets/MessageReceived";
9
+ }
10
+ }
11
+ export { WebsocketEvent };
12
+
13
+ //# sourceMappingURL=WebsocketEvent.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"events/WebsocketEvent.js","sources":["../../src/events/WebsocketEvent.ts"],"sourcesContent":["import { BaseEvent } from \"@webiny/app/features/eventPublisher/index.js\";\nimport { WebsocketEventHandler } from \"./abstractions.js\";\nimport type { IncomingGenericData } from \"~/types.js\";\n\n/**\n * Published for every incoming websocket message. Carries the raw message data\n * (which always includes an `action`), and routes to `WebsocketEventHandler` handlers.\n */\nexport class WebsocketEvent extends BaseEvent<IncomingGenericData> {\n readonly eventType = \"Websockets/MessageReceived\" as const;\n\n getHandlerAbstraction() {\n return WebsocketEventHandler;\n }\n}\n"],"names":["WebsocketEvent","BaseEvent","WebsocketEventHandler"],"mappings":";;AAQO,MAAMA,uBAAuBC;IAGhC,wBAAwB;QACpB,OAAOC;IACX;;QALG,qBACM,SAAS,GAAG;;AAKzB"}
@@ -0,0 +1,13 @@
1
+ import type { IEventHandler } from "@webiny/app/features/eventPublisher/index.js";
2
+ import type { WebsocketEvent } from "./WebsocketEvent.js";
3
+ /**
4
+ * Handlers registered against this abstraction receive EVERY incoming websocket message
5
+ * (published as a `WebsocketEvent` by the websockets→EventPublisher bridge). Each handler
6
+ * is responsible for filtering by `event.payload.action` and reacting to the ones it cares
7
+ * about, instead of subscribing to the websocket service directly.
8
+ */
9
+ export declare const WebsocketEventHandler: import("@webiny/di").Abstraction<IEventHandler<WebsocketEvent>>;
10
+ export declare namespace WebsocketEventHandler {
11
+ type Interface = IEventHandler<WebsocketEvent>;
12
+ type Event = WebsocketEvent;
13
+ }
@@ -0,0 +1,5 @@
1
+ import { createAbstraction } from "@webiny/feature/admin";
2
+ const WebsocketEventHandler = createAbstraction("App/WebsocketEventHandler");
3
+ export { WebsocketEventHandler };
4
+
5
+ //# sourceMappingURL=abstractions.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"events/abstractions.js","sources":["../../src/events/abstractions.ts"],"sourcesContent":["import { createAbstraction } from \"@webiny/feature/admin\";\nimport type { IEventHandler } from \"@webiny/app/features/eventPublisher/index.js\";\nimport type { WebsocketEvent } from \"./WebsocketEvent.js\";\n\n/**\n * Handlers registered against this abstraction receive EVERY incoming websocket message\n * (published as a `WebsocketEvent` by the websockets→EventPublisher bridge). Each handler\n * is responsible for filtering by `event.payload.action` and reacting to the ones it cares\n * about, instead of subscribing to the websocket service directly.\n */\nexport const WebsocketEventHandler = createAbstraction<IEventHandler<WebsocketEvent>>(\n \"App/WebsocketEventHandler\"\n);\n\nexport namespace WebsocketEventHandler {\n export type Interface = IEventHandler<WebsocketEvent>;\n export type Event = WebsocketEvent;\n}\n"],"names":["WebsocketEventHandler","createAbstraction"],"mappings":";AAUO,MAAMA,wBAAwBC,kBACjC"}
@@ -0,0 +1 @@
1
+ export { WebsocketEventHandler } from "../../events/abstractions.js";
@@ -0,0 +1 @@
1
+ export { WebsocketEventHandler } from "../../events/abstractions.js";
package/index.d.ts CHANGED
@@ -2,6 +2,9 @@ import React from "react";
2
2
  export interface WebsocketsProviderProps {
3
3
  children: React.ReactNode;
4
4
  }
5
- export declare const Websockets: React.MemoExoticComponent<() => React.JSX.Element>;
5
+ declare const WebsocketsExtension: () => React.JSX.Element;
6
+ export declare const Websockets: React.MemoExoticComponent<typeof WebsocketsExtension>;
6
7
  export * from "./types.js";
7
8
  export * from "./hooks/index.js";
9
+ export * from "./events/WebsocketEvent.js";
10
+ export * from "./events/abstractions.js";
package/index.js CHANGED
@@ -3,6 +3,8 @@ import { Provider } from "@webiny/app";
3
3
  import { WebsocketsContextProvider } from "./WebsocketsContextProvider.js";
4
4
  export * from "./types.js";
5
5
  export * from "./hooks/index.js";
6
+ export * from "./events/WebsocketEvent.js";
7
+ export * from "./events/abstractions.js";
6
8
  const WebsocketsHoc = (Component)=>function(props) {
7
9
  return /*#__PURE__*/ react.createElement(WebsocketsContextProvider, null, /*#__PURE__*/ react.createElement(Component, props));
8
10
  };
package/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sources":["../src/index.tsx"],"sourcesContent":["import React from \"react\";\nimport { Provider } from \"@webiny/app\";\nimport { WebsocketsContextProvider } from \"~/WebsocketsContextProvider.js\";\n\nexport interface WebsocketsProviderProps {\n children: React.ReactNode;\n}\n\nconst WebsocketsHoc = (Component: React.ComponentType<React.PropsWithChildren>) => {\n return function WebsocketsProvider(props: WebsocketsProviderProps) {\n return (\n <WebsocketsContextProvider>\n <Component {...props} />\n </WebsocketsContextProvider>\n );\n };\n};\n\nconst WebsocketsExtension = () => {\n return (\n <>\n <Provider hoc={WebsocketsHoc} />\n </>\n );\n};\n\nexport const Websockets = React.memo(WebsocketsExtension);\n\nexport * from \"./types.js\";\nexport * from \"./hooks/index.js\";\n"],"names":["WebsocketsHoc","Component","props","WebsocketsContextProvider","WebsocketsExtension","Provider","Websockets","React"],"mappings":";;;;;AAQA,MAAMA,gBAAgB,CAACC,YACZ,SAA4BC,KAA8B;QAC7D,OAAO,WAAP,GACI,oBAACC,2BAAyBA,MAAAA,WAAAA,GACtB,oBAACF,WAAcC;IAG3B;AAGJ,MAAME,sBAAsB,IACjB,WAAP,GACI,wDACI,oBAACC,UAAQA;QAAC,KAAKL;;AAKpB,MAAMM,aAAa,WAAHA,GAAGC,MAAAA,IAAU,CAACH"}
1
+ {"version":3,"file":"index.js","sources":["../src/index.tsx"],"sourcesContent":["import React from \"react\";\nimport { Provider } from \"@webiny/app\";\nimport { WebsocketsContextProvider } from \"~/WebsocketsContextProvider.js\";\n\nexport interface WebsocketsProviderProps {\n children: React.ReactNode;\n}\n\nconst WebsocketsHoc = (Component: React.ComponentType<React.PropsWithChildren>) => {\n return function WebsocketsProvider(props: WebsocketsProviderProps) {\n return (\n <WebsocketsContextProvider>\n <Component {...props} />\n </WebsocketsContextProvider>\n );\n };\n};\n\nconst WebsocketsExtension = () => {\n return (\n <>\n <Provider hoc={WebsocketsHoc} />\n </>\n );\n};\n\nexport const Websockets = React.memo(WebsocketsExtension);\n\nexport * from \"./types.js\";\nexport * from \"./hooks/index.js\";\nexport * from \"./events/WebsocketEvent.js\";\nexport * from \"./events/abstractions.js\";\n"],"names":["WebsocketsHoc","Component","props","WebsocketsContextProvider","WebsocketsExtension","Provider","Websockets","React"],"mappings":";;;;;;;AAQA,MAAMA,gBAAgB,CAACC,YACZ,SAA4BC,KAA8B;QAC7D,OAAO,WAAP,GACI,oBAACC,2BAAyBA,MAAAA,WAAAA,GACtB,oBAACF,WAAcC;IAG3B;AAGJ,MAAME,sBAAsB,IACjB,WAAP,GACI,wDACI,oBAACC,UAAQA;QAAC,KAAKL;;AAKpB,MAAMM,aAAa,WAAHA,GAAGC,MAAAA,IAAU,CAACH"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@webiny/app-websockets",
3
- "version": "6.4.12-beta.5",
3
+ "version": "6.5.0-beta.1",
4
4
  "type": "module",
5
5
  "exports": {
6
6
  ".": "./index.js",
@@ -17,16 +17,17 @@
17
17
  ],
18
18
  "license": "MIT",
19
19
  "dependencies": {
20
- "@webiny/app": "6.4.12-beta.5",
21
- "@webiny/app-admin": "6.4.12-beta.5",
22
- "@webiny/utils": "6.4.12-beta.5",
20
+ "@webiny/app": "6.5.0-beta.1",
21
+ "@webiny/app-admin": "6.5.0-beta.1",
22
+ "@webiny/feature": "6.5.0-beta.1",
23
+ "@webiny/utils": "6.5.0-beta.1",
23
24
  "react": "18.3.1",
24
25
  "react-dom": "18.3.1"
25
26
  },
26
27
  "devDependencies": {
27
- "@webiny/build-tools": "6.4.12-beta.5",
28
+ "@webiny/build-tools": "6.5.0-beta.1",
28
29
  "rimraf": "6.1.3",
29
- "typescript": "6.0.3"
30
+ "typescript": "7.0.2"
30
31
  },
31
32
  "publishConfig": {
32
33
  "access": "public"