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

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.213",
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 (_) {
@@ -21,6 +22,7 @@ const useSsrDataOrReload = (context, miolo, name, options) => {
21
22
  effect = undefined,
22
23
  model = undefined,
23
24
  cache = false,
25
+ autoRefresh = true,
24
26
  ttl = undefined
25
27
  } = options
26
28
 
@@ -60,7 +62,7 @@ const useSsrDataOrReload = (context, miolo, name, options) => {
60
62
  if (cache === true) {
61
63
  if (typeof window !== "undefined") {
62
64
  import("idb-keyval").then(({ set }) => {
63
- set(`ssr-cache-${name}`, { data: makeSerializable(data), ts: Date.now() }).catch(
65
+ set(`ssr-cache-${name}`, { data: _makeSerializable(data), ts: Date.now() }).catch(
64
66
  () => {}
65
67
  )
66
68
  })
@@ -78,6 +80,8 @@ const useSsrDataOrReload = (context, miolo, name, options) => {
78
80
  setStatus("loading")
79
81
  setError(undefined)
80
82
 
83
+ logger.verbose(`[miolo-react][ssr][${name}] refreshing ssr data`)
84
+
81
85
  let newData
82
86
 
83
87
  if (loader !== undefined) {
@@ -100,7 +104,7 @@ const useSsrDataOrReload = (context, miolo, name, options) => {
100
104
  if (typeof window !== "undefined") {
101
105
  try {
102
106
  const { set } = await import("idb-keyval")
103
- await set(`ssr-cache-${name}`, { data: makeSerializable(newData), ts: Date.now() })
107
+ await set(`ssr-cache-${name}`, { data: _makeSerializable(newData), ts: Date.now() })
104
108
  } catch (err) {
105
109
  console.error(err)
106
110
  }
@@ -110,7 +114,7 @@ const useSsrDataOrReload = (context, miolo, name, options) => {
110
114
  }
111
115
 
112
116
  setStatus("loaded")
113
- }, [status, context, fetcher, loader, url, params, parseData, name, cache])
117
+ }, [status, context, fetcher, loader, url, params, parseData, name, cache, logger])
114
118
 
115
119
  const invalidateCache = useCallback((tName, callback = undefined) => {
116
120
  if (typeof window !== "undefined") {
@@ -126,6 +130,46 @@ const useSsrDataOrReload = (context, miolo, name, options) => {
126
130
  }
127
131
  }, [])
128
132
 
133
+ const checkCacheVersions = useCallback(
134
+ (versions) => {
135
+ logger.verbose(
136
+ `[miolo-react][ssr][${name}] Backend versions received: ${JSON.stringify(versions)}`
137
+ )
138
+
139
+ const ssrVersions = versions || {}
140
+ if (ssrVersions[name]) {
141
+ const backendVersion = ssrVersions[name]
142
+ logger.verbose(
143
+ `[miolo-react][ssr][${name}] Backend version for ${name} is ${backendVersion}`
144
+ )
145
+
146
+ if (typeof window !== "undefined") {
147
+ import("idb-keyval")
148
+ .then(({ get }) => {
149
+ get(`ssr-cache-${name}`)
150
+ .then((cached) => {
151
+ if (cached && cached.ts < backendVersion) {
152
+ logger.info(
153
+ `[miolo-react][ssr][${name}] ssr-versions mismatch for ${name}, invalidating`
154
+ )
155
+ invalidateCache(name, () => {
156
+ if (autoRefresh === true) {
157
+ refreshSsrData()
158
+ }
159
+ })
160
+ } else {
161
+ logger.verbose(`[miolo-react][ssr][${name}] ssr-versions match for ${name}`)
162
+ }
163
+ })
164
+ .catch(() => {})
165
+ })
166
+ .catch(() => {})
167
+ }
168
+ }
169
+ },
170
+ [name, logger, invalidateCache, refreshSsrData, autoRefresh]
171
+ )
172
+
129
173
  useEffect(() => {
130
174
  let mounted = true
131
175
 
@@ -134,6 +178,8 @@ const useSsrDataOrReload = (context, miolo, name, options) => {
134
178
 
135
179
  try {
136
180
  if (status === "idle") {
181
+ logger.verbose(`[miolo-react][ssr][${name}] getting data for ${name}...`)
182
+
137
183
  const changed =
138
184
  effect === undefined ||
139
185
  (typeof effect === "function" && effect() === true) ||
@@ -153,14 +199,17 @@ const useSsrDataOrReload = (context, miolo, name, options) => {
153
199
  }
154
200
 
155
201
  if (cached && cached.data !== undefined) {
202
+ logger.verbose(`[miolo-react][ssr][${name}] read data for ${name} from cache`)
156
203
  setSsrData(parseData(cached.data))
157
204
 
158
205
  if (ttl !== undefined && Date.now() - cached.ts > ttl * 1000) {
206
+ logger.verbose(`[miolo-react][ssr][${name}] expired cache for ${name}, refreshing`)
159
207
  refreshSsrData()
160
208
  } else {
161
209
  setStatus("loaded")
162
210
  }
163
211
  } else {
212
+ logger.verbose(`[miolo-react][ssr][${name}] no cached data for ${name}, refreshing`)
164
213
  refreshSsrData()
165
214
  }
166
215
  }
@@ -173,20 +222,23 @@ const useSsrDataOrReload = (context, miolo, name, options) => {
173
222
  return () => {
174
223
  mounted = false
175
224
  }
176
- }, [status, refreshSsrData, effect, name, ttl, parseData, cache])
225
+ }, [status, refreshSsrData, effect, name, ttl, parseData, cache, logger])
177
226
 
178
227
  useEffect(() => {
179
228
  if (cache === true) {
180
229
  if (ssrDataFromContext !== undefined && typeof window !== "undefined") {
230
+ logger.verbose(`[miolo-react][ssr][${name}] read data for ${name} from context`)
231
+
181
232
  import("idb-keyval").then(({ set }) => {
233
+ logger.verbose(`[miolo-react][ssr][${name}] writing data for ${name} to cache`)
182
234
  set(`ssr-cache-${name}`, {
183
- data: makeSerializable(ssrDataFromContext),
235
+ data: _makeSerializable(ssrDataFromContext),
184
236
  ts: Date.now()
185
237
  }).catch(() => {})
186
238
  })
187
239
  }
188
240
  }
189
- }, [ssrDataFromContext, name, cache])
241
+ }, [logger, ssrDataFromContext, name, cache])
190
242
 
191
243
  useEffect(() => {
192
244
  if (socket === undefined) {
@@ -199,21 +251,67 @@ const useSsrDataOrReload = (context, miolo, name, options) => {
199
251
  setSocketInited(true)
200
252
 
201
253
  socket.on("connect", () => {
202
- logger.verbose("[ssr] Socket connected")
203
- })
254
+ logger.verbose(`[miolo-react][ssr][${name}] Socket connected`)
255
+ if (cache === true) {
256
+ logger.verbose(`[miolo-react][ssr][${name}] Asking for ssr-versions`)
257
+ socket.emit("ssr-versions")
204
258
 
205
- socket.on("ssr-invalidate", (data) => {
206
- logger.info(`[ssr] ssr-invalidate ${data.name}`)
207
- invalidateCache(data.name)
208
- })
259
+ logger.verbose(`[miolo-react][ssr][${name}] Attaching ssr/cache socket handlers`)
209
260
 
210
- socket.on("ssr-refresh", (data) => {
211
- logger.info(`[ssr] ssr-refresh ${data.name}`)
212
- invalidateCache(data.name, () => {
213
- refreshSsrData()
214
- })
261
+ socket.on("ssr-versions", checkCacheVersions)
262
+
263
+ socket.on("ssr-invalidate", (data) => {
264
+ logger.verbose(`[miolo-react][ssr][${name}] ssr-invalidate ${JSON.stringify(data)}`)
265
+ if (data.exclude_socket_id && data.exclude_socket_id === socket.id) {
266
+ logger.verbose(
267
+ `[miolo-react][ssr][${name}] ssr-invalidate ${data.name} ignored for socketid ${socket.id}`
268
+ )
269
+ return
270
+ }
271
+ logger.info(`[miolo-react][ssr][${name}] ssr-invalidate ${data.name}`)
272
+ invalidateCache(data.name)
273
+ })
274
+
275
+ socket.on("ssr-refresh", (data) => {
276
+ logger.verbose(
277
+ `[miolo-react][ssr][${name}] ssr-refresh ${JSON.stringify(data)} - my socket id: ${socket.id}`
278
+ )
279
+ if (data.exclude_socket_id && data.exclude_socket_id === socket.id) {
280
+ logger.verbose(
281
+ `[miolo-react][ssr][${name}] ssr-refresh ${data.name} ignored for socketid ${socket.id}`
282
+ )
283
+ return
284
+ }
285
+ logger.info(`[miolo-react][ssr][${name}] ssr-refresh ${data.name}`)
286
+ invalidateCache(data.name, () => {
287
+ refreshSsrData()
288
+ })
289
+ })
290
+ }
215
291
  })
216
- }, [socket, socketInited, logger, invalidateCache, refreshSsrData])
292
+ }, [
293
+ name,
294
+ cache,
295
+ socket,
296
+ socketInited,
297
+ checkCacheVersions,
298
+ logger,
299
+ invalidateCache,
300
+ refreshSsrData
301
+ ])
302
+
303
+ useOnWindowFocus(() => {
304
+ if (cache !== true) {
305
+ return
306
+ }
307
+ if (socket === undefined) {
308
+ return
309
+ }
310
+ logger.verbose(
311
+ `[miolo-react][ssr][${name}] Window focused, checking versions (socket id is ${socket.id})`
312
+ )
313
+ socket.emit("ssr-versions")
314
+ }, [name, cache, logger, socket])
217
315
 
218
316
  return {
219
317
  data: ssrData,