@greatapps/common 1.1.794 → 1.1.795

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.
@@ -8,8 +8,8 @@ import dynamic from "next/dynamic";
8
8
  import {
9
9
  PersistQueryClientProvider
10
10
  } from "@tanstack/react-query-persist-client";
11
- import { broadcastQueryClient } from "@tanstack/query-broadcast-client-experimental";
12
11
  import { set, get, del } from "idb-keyval";
12
+ import { isShareableQuery, shareQueryCacheBetweenTabs } from "./share-query-cache";
13
13
  const ReactQueryDevtools = process.env.NODE_ENV === "development" ? dynamic(
14
14
  () => import("@tanstack/react-query-devtools").then((mod) => ({
15
15
  default: mod.ReactQueryDevtools
@@ -62,12 +62,7 @@ function QueryProvider({
62
62
  }
63
63
  })
64
64
  );
65
- useEffect(() => {
66
- broadcastQueryClient({
67
- queryClient,
68
- broadcastChannel: "react-query"
69
- });
70
- }, [queryClient]);
65
+ useEffect(() => shareQueryCacheBetweenTabs(queryClient), [queryClient]);
71
66
  return /* @__PURE__ */ jsxs(
72
67
  PersistQueryClientProvider,
73
68
  {
@@ -77,12 +72,7 @@ function QueryProvider({
77
72
  maxAge: 2 * 60 * 60 * 1e3,
78
73
  buster: persisterVersion,
79
74
  dehydrateOptions: {
80
- shouldDehydrateQuery: (query) => {
81
- if (query.state.status === "error") return false;
82
- if (query.meta?.persist === false) return false;
83
- if ((query.state.dataUpdateCount ?? 0) > 10) return false;
84
- return true;
85
- }
75
+ shouldDehydrateQuery: isShareableQuery
86
76
  }
87
77
  },
88
78
  children: [
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/providers/query.provider.tsx"],"sourcesContent":["\"use client\";\r\n\r\nimport {\r\n QueryCache,\r\n QueryClient,\r\n QueryClientProvider,\r\n} from \"@tanstack/react-query\";\r\nimport { ReactNode, useEffect, useState } from \"react\";\r\nimport dynamic from \"next/dynamic\";\r\nimport { toast } from \"sonner\";\r\nimport {\r\n PersistedClient,\r\n PersistQueryClientProvider,\r\n} from \"@tanstack/react-query-persist-client\";\r\nimport { broadcastQueryClient } from \"@tanstack/query-broadcast-client-experimental\";\r\nimport { set, get, del } from \"idb-keyval\";\r\n\r\n// React Query Devtools só em desenvolvimento - remove do bundle de produção\r\nconst ReactQueryDevtools =\r\n process.env.NODE_ENV === \"development\"\r\n ? dynamic(\r\n () =>\r\n import(\"@tanstack/react-query-devtools\").then((mod) => ({\r\n default: mod.ReactQueryDevtools,\r\n })),\r\n { ssr: false },\r\n )\r\n : () => null;\r\n\r\nexport const persister = {\r\n persistClient: async (client: PersistedClient) => {\r\n try {\r\n await set(\"rq-cache\", client);\r\n } catch {\r\n console.warn(\"Falha ao persistir cache\");\r\n }\r\n },\r\n restoreClient: async (): Promise<PersistedClient | undefined> => {\r\n try {\r\n return await get(\"rq-cache\");\r\n } catch {\r\n await del(\"rq-cache\").catch(() => {});\r\n return undefined;\r\n }\r\n },\r\n removeClient: async () => {\r\n try {\r\n await del(\"rq-cache\");\r\n } catch {\r\n console.warn(\"Falha ao remover cache\");\r\n }\r\n },\r\n};\r\n\r\ninterface QueryProviderProps {\r\n children: ReactNode;\r\n persisterVersion?: string;\r\n}\r\n\r\nexport function QueryProvider({\r\n children,\r\n persisterVersion = \"v1\",\r\n}: QueryProviderProps) {\r\n const [queryClient] = useState(\r\n () =>\r\n new QueryClient({\r\n defaultOptions: {\r\n queries: {\r\n staleTime: 15 * 1000,\r\n gcTime: 5 * 60 * 1000,\r\n refetchOnWindowFocus: false,\r\n refetchOnReconnect: true,\r\n retry: 2,\r\n retryDelay: (attempt) => Math.min(1000 * 2 ** attempt, 30000),\r\n },\r\n mutations: {\r\n retry: false,\r\n },\r\n },\r\n }),\r\n );\r\n\r\n useEffect(() => {\r\n broadcastQueryClient({\r\n queryClient,\r\n broadcastChannel: \"react-query\",\r\n });\r\n }, [queryClient]);\r\n\r\n return (\r\n <PersistQueryClientProvider\r\n client={queryClient}\r\n persistOptions={{\r\n persister,\r\n maxAge: 2 * 60 * 60 * 1000,\r\n buster: persisterVersion,\r\n dehydrateOptions: {\r\n shouldDehydrateQuery: (query) => {\r\n if (query.state.status === \"error\") return false;\r\n if (query.meta?.persist === false) return false;\r\n if ((query.state.dataUpdateCount ?? 0) > 10) return false;\r\n return true;\r\n },\r\n },\r\n }}\r\n >\r\n {children}\r\n <ReactQueryDevtools initialIsOpen={false} />\r\n </PersistQueryClientProvider>\r\n );\r\n}\r\n"],"mappings":";AA0FI,SAiBE,KAjBF;AAxFJ;AAAA,EAEE;AAAA,OAEK;AACP,SAAoB,WAAW,gBAAgB;AAC/C,OAAO,aAAa;AAEpB;AAAA,EAEE;AAAA,OACK;AACP,SAAS,4BAA4B;AACrC,SAAS,KAAK,KAAK,WAAW;AAG9B,MAAM,qBACJ,QAAQ,IAAI,aAAa,gBACrB;AAAA,EACE,MACE,OAAO,gCAAgC,EAAE,KAAK,CAAC,SAAS;AAAA,IACtD,SAAS,IAAI;AAAA,EACf,EAAE;AAAA,EACJ,EAAE,KAAK,MAAM;AACf,IACA,MAAM;AAEL,MAAM,YAAY;AAAA,EACvB,eAAe,OAAO,WAA4B;AAChD,QAAI;AACF,YAAM,IAAI,YAAY,MAAM;AAAA,IAC9B,QAAQ;AACN,cAAQ,KAAK,0BAA0B;AAAA,IACzC;AAAA,EACF;AAAA,EACA,eAAe,YAAkD;AAC/D,QAAI;AACF,aAAO,MAAM,IAAI,UAAU;AAAA,IAC7B,QAAQ;AACN,YAAM,IAAI,UAAU,EAAE,MAAM,MAAM;AAAA,MAAC,CAAC;AACpC,aAAO;AAAA,IACT;AAAA,EACF;AAAA,EACA,cAAc,YAAY;AACxB,QAAI;AACF,YAAM,IAAI,UAAU;AAAA,IACtB,QAAQ;AACN,cAAQ,KAAK,wBAAwB;AAAA,IACvC;AAAA,EACF;AACF;AAOO,SAAS,cAAc;AAAA,EAC5B;AAAA,EACA,mBAAmB;AACrB,GAAuB;AACrB,QAAM,CAAC,WAAW,IAAI;AAAA,IACpB,MACE,IAAI,YAAY;AAAA,MACd,gBAAgB;AAAA,QACd,SAAS;AAAA,UACP,WAAW,KAAK;AAAA,UAChB,QAAQ,IAAI,KAAK;AAAA,UACjB,sBAAsB;AAAA,UACtB,oBAAoB;AAAA,UACpB,OAAO;AAAA,UACP,YAAY,CAAC,YAAY,KAAK,IAAI,MAAO,KAAK,SAAS,GAAK;AAAA,QAC9D;AAAA,QACA,WAAW;AAAA,UACT,OAAO;AAAA,QACT;AAAA,MACF;AAAA,IACF,CAAC;AAAA,EACL;AAEA,YAAU,MAAM;AACd,yBAAqB;AAAA,MACnB;AAAA,MACA,kBAAkB;AAAA,IACpB,CAAC;AAAA,EACH,GAAG,CAAC,WAAW,CAAC;AAEhB,SACE;AAAA,IAAC;AAAA;AAAA,MACC,QAAQ;AAAA,MACR,gBAAgB;AAAA,QACd;AAAA,QACA,QAAQ,IAAI,KAAK,KAAK;AAAA,QACtB,QAAQ;AAAA,QACR,kBAAkB;AAAA,UAChB,sBAAsB,CAAC,UAAU;AAC/B,gBAAI,MAAM,MAAM,WAAW,QAAS,QAAO;AAC3C,gBAAI,MAAM,MAAM,YAAY,MAAO,QAAO;AAC1C,iBAAK,MAAM,MAAM,mBAAmB,KAAK,GAAI,QAAO;AACpD,mBAAO;AAAA,UACT;AAAA,QACF;AAAA,MACF;AAAA,MAEC;AAAA;AAAA,QACD,oBAAC,sBAAmB,eAAe,OAAO;AAAA;AAAA;AAAA,EAC5C;AAEJ;","names":[]}
1
+ {"version":3,"sources":["../../src/providers/query.provider.tsx"],"sourcesContent":["\"use client\";\r\n\r\nimport {\r\n QueryCache,\r\n QueryClient,\r\n QueryClientProvider,\r\n} from \"@tanstack/react-query\";\r\nimport { ReactNode, useEffect, useState } from \"react\";\r\nimport dynamic from \"next/dynamic\";\r\nimport { toast } from \"sonner\";\r\nimport {\r\n PersistedClient,\r\n PersistQueryClientProvider,\r\n} from \"@tanstack/react-query-persist-client\";\r\nimport { set, get, del } from \"idb-keyval\";\r\nimport { isShareableQuery, shareQueryCacheBetweenTabs } from \"./share-query-cache\";\r\n\r\n// React Query Devtools só em desenvolvimento - remove do bundle de produção\r\nconst ReactQueryDevtools =\r\n process.env.NODE_ENV === \"development\"\r\n ? dynamic(\r\n () =>\r\n import(\"@tanstack/react-query-devtools\").then((mod) => ({\r\n default: mod.ReactQueryDevtools,\r\n })),\r\n { ssr: false },\r\n )\r\n : () => null;\r\n\r\nexport const persister = {\r\n persistClient: async (client: PersistedClient) => {\r\n try {\r\n await set(\"rq-cache\", client);\r\n } catch {\r\n console.warn(\"Falha ao persistir cache\");\r\n }\r\n },\r\n restoreClient: async (): Promise<PersistedClient | undefined> => {\r\n try {\r\n return await get(\"rq-cache\");\r\n } catch {\r\n await del(\"rq-cache\").catch(() => {});\r\n return undefined;\r\n }\r\n },\r\n removeClient: async () => {\r\n try {\r\n await del(\"rq-cache\");\r\n } catch {\r\n console.warn(\"Falha ao remover cache\");\r\n }\r\n },\r\n};\r\n\r\ninterface QueryProviderProps {\r\n children: ReactNode;\r\n persisterVersion?: string;\r\n}\r\n\r\nexport function QueryProvider({\r\n children,\r\n persisterVersion = \"v1\",\r\n}: QueryProviderProps) {\r\n const [queryClient] = useState(\r\n () =>\r\n new QueryClient({\r\n defaultOptions: {\r\n queries: {\r\n staleTime: 15 * 1000,\r\n gcTime: 5 * 60 * 1000,\r\n refetchOnWindowFocus: false,\r\n refetchOnReconnect: true,\r\n retry: 2,\r\n retryDelay: (attempt) => Math.min(1000 * 2 ** attempt, 30000),\r\n },\r\n mutations: {\r\n retry: false,\r\n },\r\n },\r\n }),\r\n );\r\n\r\n useEffect(() => shareQueryCacheBetweenTabs(queryClient), [queryClient]);\r\n\r\n return (\r\n <PersistQueryClientProvider\r\n client={queryClient}\r\n persistOptions={{\r\n persister,\r\n maxAge: 2 * 60 * 60 * 1000,\r\n buster: persisterVersion,\r\n dehydrateOptions: {\r\n shouldDehydrateQuery: isShareableQuery,\r\n },\r\n }}\r\n >\r\n {children}\r\n <ReactQueryDevtools initialIsOpen={false} />\r\n </PersistQueryClientProvider>\r\n );\r\n}\r\n"],"mappings":";AAqFI,SAYE,KAZF;AAnFJ;AAAA,EAEE;AAAA,OAEK;AACP,SAAoB,WAAW,gBAAgB;AAC/C,OAAO,aAAa;AAEpB;AAAA,EAEE;AAAA,OACK;AACP,SAAS,KAAK,KAAK,WAAW;AAC9B,SAAS,kBAAkB,kCAAkC;AAG7D,MAAM,qBACJ,QAAQ,IAAI,aAAa,gBACrB;AAAA,EACE,MACE,OAAO,gCAAgC,EAAE,KAAK,CAAC,SAAS;AAAA,IACtD,SAAS,IAAI;AAAA,EACf,EAAE;AAAA,EACJ,EAAE,KAAK,MAAM;AACf,IACA,MAAM;AAEL,MAAM,YAAY;AAAA,EACvB,eAAe,OAAO,WAA4B;AAChD,QAAI;AACF,YAAM,IAAI,YAAY,MAAM;AAAA,IAC9B,QAAQ;AACN,cAAQ,KAAK,0BAA0B;AAAA,IACzC;AAAA,EACF;AAAA,EACA,eAAe,YAAkD;AAC/D,QAAI;AACF,aAAO,MAAM,IAAI,UAAU;AAAA,IAC7B,QAAQ;AACN,YAAM,IAAI,UAAU,EAAE,MAAM,MAAM;AAAA,MAAC,CAAC;AACpC,aAAO;AAAA,IACT;AAAA,EACF;AAAA,EACA,cAAc,YAAY;AACxB,QAAI;AACF,YAAM,IAAI,UAAU;AAAA,IACtB,QAAQ;AACN,cAAQ,KAAK,wBAAwB;AAAA,IACvC;AAAA,EACF;AACF;AAOO,SAAS,cAAc;AAAA,EAC5B;AAAA,EACA,mBAAmB;AACrB,GAAuB;AACrB,QAAM,CAAC,WAAW,IAAI;AAAA,IACpB,MACE,IAAI,YAAY;AAAA,MACd,gBAAgB;AAAA,QACd,SAAS;AAAA,UACP,WAAW,KAAK;AAAA,UAChB,QAAQ,IAAI,KAAK;AAAA,UACjB,sBAAsB;AAAA,UACtB,oBAAoB;AAAA,UACpB,OAAO;AAAA,UACP,YAAY,CAAC,YAAY,KAAK,IAAI,MAAO,KAAK,SAAS,GAAK;AAAA,QAC9D;AAAA,QACA,WAAW;AAAA,UACT,OAAO;AAAA,QACT;AAAA,MACF;AAAA,IACF,CAAC;AAAA,EACL;AAEA,YAAU,MAAM,2BAA2B,WAAW,GAAG,CAAC,WAAW,CAAC;AAEtE,SACE;AAAA,IAAC;AAAA;AAAA,MACC,QAAQ;AAAA,MACR,gBAAgB;AAAA,QACd;AAAA,QACA,QAAQ,IAAI,KAAK,KAAK;AAAA,QACtB,QAAQ;AAAA,QACR,kBAAkB;AAAA,UAChB,sBAAsB;AAAA,QACxB;AAAA,MACF;AAAA,MAEC;AAAA;AAAA,QACD,oBAAC,sBAAmB,eAAe,OAAO;AAAA;AAAA;AAAA,EAC5C;AAEJ;","names":[]}
@@ -0,0 +1,54 @@
1
+ function isShareableQuery(query) {
2
+ if (query.state.status === "error") return false;
3
+ if (query.meta?.persist === false) return false;
4
+ if (query.state.dataUpdateCount > 10) return false;
5
+ return true;
6
+ }
7
+ function shareQueryCacheBetweenTabs(queryClient) {
8
+ if (typeof BroadcastChannel === "undefined") return () => {
9
+ };
10
+ const channel = new BroadcastChannel("greatapps-query-cache");
11
+ const queryCache = queryClient.getQueryCache();
12
+ let applyingRemoteMessage = false;
13
+ const unsubscribe = queryCache.subscribe((event) => {
14
+ if (applyingRemoteMessage) return;
15
+ const { query } = event;
16
+ const { queryHash, queryKey } = query;
17
+ if (event.type === "removed" && query.observers.length > 0) {
18
+ channel.postMessage({ type: "removed", queryHash, queryKey });
19
+ }
20
+ if (event.type === "updated" && event.action.type === "success" && isShareableQuery(query)) {
21
+ try {
22
+ channel.postMessage({ type: "updated", queryHash, queryKey, state: query.state });
23
+ } catch {
24
+ console.warn("Falha ao espelhar query entre abas", queryHash);
25
+ }
26
+ }
27
+ });
28
+ channel.addEventListener("message", (event) => {
29
+ const message = event.data;
30
+ const query = queryCache.get(message.queryHash);
31
+ applyingRemoteMessage = true;
32
+ try {
33
+ if (message.type === "removed" && query) queryCache.remove(query);
34
+ if (message.type === "updated") {
35
+ if (!query) {
36
+ queryCache.build(queryClient, { queryKey: message.queryKey, queryHash: message.queryHash }, message.state);
37
+ } else if (isShareableQuery(query) && message.state.dataUpdatedAt >= query.state.dataUpdatedAt) {
38
+ query.setState(message.state);
39
+ }
40
+ }
41
+ } finally {
42
+ applyingRemoteMessage = false;
43
+ }
44
+ });
45
+ return () => {
46
+ unsubscribe();
47
+ channel.close();
48
+ };
49
+ }
50
+ export {
51
+ isShareableQuery,
52
+ shareQueryCacheBetweenTabs
53
+ };
54
+ //# sourceMappingURL=share-query-cache.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../src/providers/share-query-cache.ts"],"sourcesContent":["import type { Query, QueryClient, QueryKey, QueryState } from \"@tanstack/react-query\";\n\ntype CacheMessage =\n | { type: \"removed\"; queryHash: string; queryKey: QueryKey }\n | { type: \"updated\"; queryHash: string; queryKey: QueryKey; state: QueryState };\n\nexport function isShareableQuery(query: Query): boolean {\n if (query.state.status === \"error\") return false;\n if (query.meta?.persist === false) return false;\n if (query.state.dataUpdateCount > 10) return false;\n return true;\n}\n\nexport function shareQueryCacheBetweenTabs(queryClient: QueryClient): () => void {\n if (typeof BroadcastChannel === \"undefined\") return () => {};\n const channel = new BroadcastChannel(\"greatapps-query-cache\");\n const queryCache = queryClient.getQueryCache();\n let applyingRemoteMessage = false;\n\n const unsubscribe = queryCache.subscribe((event) => {\n if (applyingRemoteMessage) return;\n const { query } = event;\n const { queryHash, queryKey } = query;\n if (event.type === \"removed\" && query.observers.length > 0) {\n channel.postMessage({ type: \"removed\", queryHash, queryKey });\n }\n if (event.type === \"updated\" && event.action.type === \"success\" && isShareableQuery(query)) {\n try {\n channel.postMessage({ type: \"updated\", queryHash, queryKey, state: query.state });\n } catch {\n console.warn(\"Falha ao espelhar query entre abas\", queryHash);\n }\n }\n });\n\n channel.addEventListener(\"message\", (event: MessageEvent<CacheMessage>) => {\n const message = event.data;\n const query = queryCache.get(message.queryHash);\n applyingRemoteMessage = true;\n try {\n if (message.type === \"removed\" && query) queryCache.remove(query);\n if (message.type === \"updated\") {\n if (!query) {\n queryCache.build(queryClient, { queryKey: message.queryKey, queryHash: message.queryHash }, message.state);\n } else if (isShareableQuery(query) && message.state.dataUpdatedAt >= query.state.dataUpdatedAt) {\n query.setState(message.state);\n }\n }\n } finally {\n applyingRemoteMessage = false;\n }\n });\n\n return () => {\n unsubscribe();\n channel.close();\n };\n}\n"],"mappings":"AAMO,SAAS,iBAAiB,OAAuB;AACtD,MAAI,MAAM,MAAM,WAAW,QAAS,QAAO;AAC3C,MAAI,MAAM,MAAM,YAAY,MAAO,QAAO;AAC1C,MAAI,MAAM,MAAM,kBAAkB,GAAI,QAAO;AAC7C,SAAO;AACT;AAEO,SAAS,2BAA2B,aAAsC;AAC/E,MAAI,OAAO,qBAAqB,YAAa,QAAO,MAAM;AAAA,EAAC;AAC3D,QAAM,UAAU,IAAI,iBAAiB,uBAAuB;AAC5D,QAAM,aAAa,YAAY,cAAc;AAC7C,MAAI,wBAAwB;AAE5B,QAAM,cAAc,WAAW,UAAU,CAAC,UAAU;AAClD,QAAI,sBAAuB;AAC3B,UAAM,EAAE,MAAM,IAAI;AAClB,UAAM,EAAE,WAAW,SAAS,IAAI;AAChC,QAAI,MAAM,SAAS,aAAa,MAAM,UAAU,SAAS,GAAG;AAC1D,cAAQ,YAAY,EAAE,MAAM,WAAW,WAAW,SAAS,CAAC;AAAA,IAC9D;AACA,QAAI,MAAM,SAAS,aAAa,MAAM,OAAO,SAAS,aAAa,iBAAiB,KAAK,GAAG;AAC1F,UAAI;AACF,gBAAQ,YAAY,EAAE,MAAM,WAAW,WAAW,UAAU,OAAO,MAAM,MAAM,CAAC;AAAA,MAClF,QAAQ;AACN,gBAAQ,KAAK,sCAAsC,SAAS;AAAA,MAC9D;AAAA,IACF;AAAA,EACF,CAAC;AAED,UAAQ,iBAAiB,WAAW,CAAC,UAAsC;AACzE,UAAM,UAAU,MAAM;AACtB,UAAM,QAAQ,WAAW,IAAI,QAAQ,SAAS;AAC9C,4BAAwB;AACxB,QAAI;AACF,UAAI,QAAQ,SAAS,aAAa,MAAO,YAAW,OAAO,KAAK;AAChE,UAAI,QAAQ,SAAS,WAAW;AAC9B,YAAI,CAAC,OAAO;AACV,qBAAW,MAAM,aAAa,EAAE,UAAU,QAAQ,UAAU,WAAW,QAAQ,UAAU,GAAG,QAAQ,KAAK;AAAA,QAC3G,WAAW,iBAAiB,KAAK,KAAK,QAAQ,MAAM,iBAAiB,MAAM,MAAM,eAAe;AAC9F,gBAAM,SAAS,QAAQ,KAAK;AAAA,QAC9B;AAAA,MACF;AAAA,IACF,UAAE;AACA,8BAAwB;AAAA,IAC1B;AAAA,EACF,CAAC;AAED,SAAO,MAAM;AACX,gBAAY;AACZ,YAAQ,MAAM;AAAA,EAChB;AACF;","names":[]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@greatapps/common",
3
- "version": "1.1.794",
3
+ "version": "1.1.795",
4
4
  "description": "Shared library for GreatApps frontend applications",
5
5
  "main": "./dist/index.mjs",
6
6
  "types": "./src/index.ts",
@@ -12,8 +12,8 @@ import {
12
12
  PersistedClient,
13
13
  PersistQueryClientProvider,
14
14
  } from "@tanstack/react-query-persist-client";
15
- import { broadcastQueryClient } from "@tanstack/query-broadcast-client-experimental";
16
15
  import { set, get, del } from "idb-keyval";
16
+ import { isShareableQuery, shareQueryCacheBetweenTabs } from "./share-query-cache";
17
17
 
18
18
  // React Query Devtools só em desenvolvimento - remove do bundle de produção
19
19
  const ReactQueryDevtools =
@@ -80,12 +80,7 @@ export function QueryProvider({
80
80
  }),
81
81
  );
82
82
 
83
- useEffect(() => {
84
- broadcastQueryClient({
85
- queryClient,
86
- broadcastChannel: "react-query",
87
- });
88
- }, [queryClient]);
83
+ useEffect(() => shareQueryCacheBetweenTabs(queryClient), [queryClient]);
89
84
 
90
85
  return (
91
86
  <PersistQueryClientProvider
@@ -95,12 +90,7 @@ export function QueryProvider({
95
90
  maxAge: 2 * 60 * 60 * 1000,
96
91
  buster: persisterVersion,
97
92
  dehydrateOptions: {
98
- shouldDehydrateQuery: (query) => {
99
- if (query.state.status === "error") return false;
100
- if (query.meta?.persist === false) return false;
101
- if ((query.state.dataUpdateCount ?? 0) > 10) return false;
102
- return true;
103
- },
93
+ shouldDehydrateQuery: isShareableQuery,
104
94
  },
105
95
  }}
106
96
  >
@@ -0,0 +1,58 @@
1
+ import type { Query, QueryClient, QueryKey, QueryState } from "@tanstack/react-query";
2
+
3
+ type CacheMessage =
4
+ | { type: "removed"; queryHash: string; queryKey: QueryKey }
5
+ | { type: "updated"; queryHash: string; queryKey: QueryKey; state: QueryState };
6
+
7
+ export function isShareableQuery(query: Query): boolean {
8
+ if (query.state.status === "error") return false;
9
+ if (query.meta?.persist === false) return false;
10
+ if (query.state.dataUpdateCount > 10) return false;
11
+ return true;
12
+ }
13
+
14
+ export function shareQueryCacheBetweenTabs(queryClient: QueryClient): () => void {
15
+ if (typeof BroadcastChannel === "undefined") return () => {};
16
+ const channel = new BroadcastChannel("greatapps-query-cache");
17
+ const queryCache = queryClient.getQueryCache();
18
+ let applyingRemoteMessage = false;
19
+
20
+ const unsubscribe = queryCache.subscribe((event) => {
21
+ if (applyingRemoteMessage) return;
22
+ const { query } = event;
23
+ const { queryHash, queryKey } = query;
24
+ if (event.type === "removed" && query.observers.length > 0) {
25
+ channel.postMessage({ type: "removed", queryHash, queryKey });
26
+ }
27
+ if (event.type === "updated" && event.action.type === "success" && isShareableQuery(query)) {
28
+ try {
29
+ channel.postMessage({ type: "updated", queryHash, queryKey, state: query.state });
30
+ } catch {
31
+ console.warn("Falha ao espelhar query entre abas", queryHash);
32
+ }
33
+ }
34
+ });
35
+
36
+ channel.addEventListener("message", (event: MessageEvent<CacheMessage>) => {
37
+ const message = event.data;
38
+ const query = queryCache.get(message.queryHash);
39
+ applyingRemoteMessage = true;
40
+ try {
41
+ if (message.type === "removed" && query) queryCache.remove(query);
42
+ if (message.type === "updated") {
43
+ if (!query) {
44
+ queryCache.build(queryClient, { queryKey: message.queryKey, queryHash: message.queryHash }, message.state);
45
+ } else if (isShareableQuery(query) && message.state.dataUpdatedAt >= query.state.dataUpdatedAt) {
46
+ query.setState(message.state);
47
+ }
48
+ }
49
+ } finally {
50
+ applyingRemoteMessage = false;
51
+ }
52
+ });
53
+
54
+ return () => {
55
+ unsubscribe();
56
+ channel.close();
57
+ };
58
+ }