miolo-react 3.0.0-beta.211 → 3.0.0-beta.212

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.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "miolo-react",
3
- "version": "3.0.0-beta.211",
3
+ "version": "3.0.0-beta.212",
4
4
  "description": "React utils for miolo",
5
5
  "author": "Donato Lorenzo <donato@afialapis.com>",
6
6
  "contributors": [
@@ -7,10 +7,10 @@ const MioloContextProvider = ({ context, children }) => {
7
7
  const [innerContext, setInnerContext] = useState(context)
8
8
  const [mioloObj, setMioloObj] = useState(miolo_client(context))
9
9
 
10
- useEffect(() => {
10
+ /*useEffect(() => {
11
11
  setInnerContext(context)
12
12
  setMioloObj(miolo_client(context))
13
- }, [context])
13
+ }, [context])*/
14
14
 
15
15
  const localLogin = useCallback(
16
16
  async (params) => {
@@ -0,0 +1,33 @@
1
+ import { useEffect, useRef } from "react"
2
+
3
+ export default function useOnWindowFocus(callback) {
4
+ // Usamos un ref para guardar el callback más reciente
5
+ // Esto evita problemas de re-renderizados si el callback cambia
6
+ const callbackRef = useRef(callback)
7
+
8
+ useEffect(() => {
9
+ callbackRef.current = callback
10
+ }, [callback])
11
+
12
+ useEffect(() => {
13
+ const handleFocus = () => {
14
+ // document.hidden es parte de la Page Visibility API
15
+ // Solo ejecutamos el callback si la pestaña realmente está visible
16
+ if (!document.hidden && callbackRef.current) {
17
+ callbackRef.current()
18
+ }
19
+ }
20
+
21
+ // Escuchamos cuando la pestaña se vuelve visible (Page Visibility API)
22
+ document.addEventListener("visibilitychange", handleFocus)
23
+
24
+ // Escuchamos cuando la ventana recupera el foco (Fallback)
25
+ window.addEventListener("focus", handleFocus)
26
+
27
+ // Limpieza de eventos al desmontar
28
+ return () => {
29
+ document.removeEventListener("visibilitychange", handleFocus)
30
+ window.removeEventListener("focus", handleFocus)
31
+ }
32
+ }, [])
33
+ }
@@ -1,8 +1,9 @@
1
1
  import { useCallback, useEffect, useMemo, useState } from "react"
2
2
  import getSsrDataFromContext from "./getSsrDataFromContext.mjs"
3
+ import useOnWindowFocus from "./useOnWindowFocus.mjs"
3
4
  import usePropsCheck from "./usePropsCheck.mjs"
4
5
 
5
- const makeSerializable = (obj) => {
6
+ const _makeSerializable = (obj) => {
6
7
  try {
7
8
  return JSON.parse(JSON.stringify(obj))
8
9
  } catch (_) {
@@ -10,6 +11,14 @@ const makeSerializable = (obj) => {
10
11
  }
11
12
  }
12
13
 
14
+ /*
15
+ QUE PASA CON LA DUPLICIDAD DE INVALIDACION
16
+ - el cliente hace un cambio
17
+ - setData() cambia estado y cache local
18
+ - la llamada en servidor provoca un ssr-refresh (necesario para otros clientes)
19
+ - pero se puede evitar el doble refresh en el que hace el cambio?
20
+ */
21
+
13
22
  const useSsrDataOrReload = (context, miolo, name, options) => {
14
23
  const { fetcher, socket, logger } = miolo
15
24
  const {
@@ -21,6 +30,7 @@ const useSsrDataOrReload = (context, miolo, name, options) => {
21
30
  effect = undefined,
22
31
  model = undefined,
23
32
  cache = false,
33
+ autoRefresh = true,
24
34
  ttl = undefined
25
35
  } = options
26
36
 
@@ -60,7 +70,7 @@ const useSsrDataOrReload = (context, miolo, name, options) => {
60
70
  if (cache === true) {
61
71
  if (typeof window !== "undefined") {
62
72
  import("idb-keyval").then(({ set }) => {
63
- set(`ssr-cache-${name}`, { data: makeSerializable(data), ts: Date.now() }).catch(
73
+ set(`ssr-cache-${name}`, { data: _makeSerializable(data), ts: Date.now() }).catch(
64
74
  () => {}
65
75
  )
66
76
  })
@@ -78,6 +88,8 @@ const useSsrDataOrReload = (context, miolo, name, options) => {
78
88
  setStatus("loading")
79
89
  setError(undefined)
80
90
 
91
+ logger.verbose(`[miolo-react][ssr][${name}] refreshing ssr data`)
92
+
81
93
  let newData
82
94
 
83
95
  if (loader !== undefined) {
@@ -100,7 +112,7 @@ const useSsrDataOrReload = (context, miolo, name, options) => {
100
112
  if (typeof window !== "undefined") {
101
113
  try {
102
114
  const { set } = await import("idb-keyval")
103
- await set(`ssr-cache-${name}`, { data: makeSerializable(newData), ts: Date.now() })
115
+ await set(`ssr-cache-${name}`, { data: _makeSerializable(newData), ts: Date.now() })
104
116
  } catch (err) {
105
117
  console.error(err)
106
118
  }
@@ -110,7 +122,7 @@ const useSsrDataOrReload = (context, miolo, name, options) => {
110
122
  }
111
123
 
112
124
  setStatus("loaded")
113
- }, [status, context, fetcher, loader, url, params, parseData, name, cache])
125
+ }, [status, context, fetcher, loader, url, params, parseData, name, cache, logger])
114
126
 
115
127
  const invalidateCache = useCallback((tName, callback = undefined) => {
116
128
  if (typeof window !== "undefined") {
@@ -126,6 +138,46 @@ const useSsrDataOrReload = (context, miolo, name, options) => {
126
138
  }
127
139
  }, [])
128
140
 
141
+ const checkCacheVersions = useCallback(
142
+ (versions) => {
143
+ logger.verbose(
144
+ `[miolo-react][ssr][${name}] Backend versions received: ${JSON.stringify(versions)}`
145
+ )
146
+
147
+ const ssrVersions = versions || {}
148
+ if (ssrVersions[name]) {
149
+ const backendVersion = ssrVersions[name]
150
+ logger.verbose(
151
+ `[miolo-react][ssr][${name}] Backend version for ${name} is ${backendVersion}`
152
+ )
153
+
154
+ if (typeof window !== "undefined") {
155
+ import("idb-keyval")
156
+ .then(({ get }) => {
157
+ get(`ssr-cache-${name}`)
158
+ .then((cached) => {
159
+ if (cached && cached.ts < backendVersion) {
160
+ logger.info(
161
+ `[miolo-react][ssr][${name}] ssr-versions mismatch for ${name}, invalidating`
162
+ )
163
+ invalidateCache(name, () => {
164
+ if (autoRefresh === true) {
165
+ refreshSsrData()
166
+ }
167
+ })
168
+ } else {
169
+ logger.verbose(`[miolo-react][ssr][${name}] ssr-versions match for ${name}`)
170
+ }
171
+ })
172
+ .catch(() => {})
173
+ })
174
+ .catch(() => {})
175
+ }
176
+ }
177
+ },
178
+ [name, logger, invalidateCache, refreshSsrData, autoRefresh]
179
+ )
180
+
129
181
  useEffect(() => {
130
182
  let mounted = true
131
183
 
@@ -134,6 +186,8 @@ const useSsrDataOrReload = (context, miolo, name, options) => {
134
186
 
135
187
  try {
136
188
  if (status === "idle") {
189
+ logger.verbose(`[miolo-react][ssr][${name}] loadData for ${name}...`)
190
+
137
191
  const changed =
138
192
  effect === undefined ||
139
193
  (typeof effect === "function" && effect() === true) ||
@@ -173,14 +227,14 @@ const useSsrDataOrReload = (context, miolo, name, options) => {
173
227
  return () => {
174
228
  mounted = false
175
229
  }
176
- }, [status, refreshSsrData, effect, name, ttl, parseData, cache])
230
+ }, [status, refreshSsrData, effect, name, ttl, parseData, cache, logger])
177
231
 
178
232
  useEffect(() => {
179
233
  if (cache === true) {
180
234
  if (ssrDataFromContext !== undefined && typeof window !== "undefined") {
181
235
  import("idb-keyval").then(({ set }) => {
182
236
  set(`ssr-cache-${name}`, {
183
- data: makeSerializable(ssrDataFromContext),
237
+ data: _makeSerializable(ssrDataFromContext),
184
238
  ts: Date.now()
185
239
  }).catch(() => {})
186
240
  })
@@ -199,21 +253,65 @@ const useSsrDataOrReload = (context, miolo, name, options) => {
199
253
  setSocketInited(true)
200
254
 
201
255
  socket.on("connect", () => {
202
- logger.verbose("[ssr] Socket connected")
203
- })
256
+ logger.verbose(`[miolo-react][ssr][${name}] Socket connected`)
257
+ if (cache === true) {
258
+ logger.verbose(`[miolo-react][ssr][${name}] Asking for ssr-versions`)
259
+ socket.emit("ssr-versions")
204
260
 
205
- socket.on("ssr-invalidate", (data) => {
206
- logger.info(`[ssr] ssr-invalidate ${data.name}`)
207
- invalidateCache(data.name)
208
- })
261
+ logger.verbose(`[miolo-react][ssr][${name}] Attaching ssr/cache socket handlers`)
209
262
 
210
- socket.on("ssr-refresh", (data) => {
211
- logger.info(`[ssr] ssr-refresh ${data.name}`)
212
- invalidateCache(data.name, () => {
213
- refreshSsrData()
214
- })
263
+ socket.on("ssr-versions", checkCacheVersions)
264
+
265
+ socket.on("ssr-invalidate", (data) => {
266
+ logger.verbose(`[miolo-react][ssr][${name}] ssr-invalidate ${JSON.stringify(data)}`)
267
+ if (data.exclude_socket_id && data.exclude_socket_id === socket.id) {
268
+ logger.verbose(
269
+ `[miolo-react][ssr][${name}] ssr-invalidate ${data.name} ignored for socketid ${socket.id}`
270
+ )
271
+ return
272
+ }
273
+ logger.info(`[miolo-react][ssr][${name}] ssr-invalidate ${data.name}`)
274
+ invalidateCache(data.name)
275
+ })
276
+
277
+ socket.on("ssr-refresh", (data) => {
278
+ logger.verbose(
279
+ `[miolo-react][ssr][${name}] ssr-refresh ${JSON.stringify(data)} - my socket id: ${socket.id}`
280
+ )
281
+ if (data.exclude_socket_id && data.exclude_socket_id === socket.id) {
282
+ logger.verbose(
283
+ `[miolo-react][ssr][${name}] ssr-refresh ${data.name} ignored for socketid ${socket.id}`
284
+ )
285
+ return
286
+ }
287
+ logger.info(`[miolo-react][ssr][${name}] ssr-refresh ${data.name}`)
288
+ invalidateCache(data.name, () => {
289
+ refreshSsrData()
290
+ })
291
+ })
292
+ }
215
293
  })
216
- }, [socket, socketInited, logger, invalidateCache, refreshSsrData])
294
+ }, [
295
+ name,
296
+ cache,
297
+ socket,
298
+ socketInited,
299
+ checkCacheVersions,
300
+ logger,
301
+ invalidateCache,
302
+ refreshSsrData
303
+ ])
304
+
305
+ useOnWindowFocus(() => {
306
+ if (cache !== true) {
307
+ return
308
+ }
309
+ if (socket === undefined) {
310
+ return
311
+ }
312
+ logger.verbose(`[miolo-react][ssr][${name}] Window focused, checking versions`)
313
+ socket.emit("ssr-versions")
314
+ }, [name, cache, logger, socket])
217
315
 
218
316
  return {
219
317
  data: ssrData,