miolo-react 3.0.0-beta.222 → 3.0.0-beta.224

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.222",
3
+ "version": "3.0.0-beta.224",
4
4
  "description": "React utils for miolo",
5
5
  "author": "Donato Lorenzo <donato@afialapis.com>",
6
6
  "contributors": [
@@ -30,7 +30,7 @@
30
30
  "prepublishOnly": "npm run lint"
31
31
  },
32
32
  "dependencies": {
33
- "idb-keyval": "^6.2.6",
33
+ "idb-keyval": "^6.3.0",
34
34
  "miolo-cli": "../miolo-cli"
35
35
  },
36
36
  "peerDependencies": {
@@ -3,6 +3,26 @@ import { useCallback, /*useEffect,*/ useState } from "react"
3
3
  import { useSsrDataOrReload } from "../ssr/useSsrDataOrReload.mjs"
4
4
  import Context from "./MioloContext.mjs"
5
5
 
6
+ /**
7
+ * @typedef {import('../ssr/useSsrDataOrReload.mjs').MioloSSRData} MioloSSRData
8
+ * @typedef {import('../ssr/useSsrDataOrReload.mjs').MioloSSRDataOptions} MioloSSRDataOptions
9
+ *
10
+ * @typedef {Object} MioloContextData
11
+ * @property {Object} user - session's data as in app.ctx
12
+ * @property {boolean} authenticated - authenticated flag as in app.ctx
13
+ * @property {Function} updateUser - function to update user
14
+ * @property {Function} googleLogin - function to login with google
15
+ * @property {Function} localLogin - function to login with local
16
+ * @property {Function} logout - function to logout
17
+ * @property {(name: string, options: MioloSSRDataOptions) => MioloSSRData} useSsrData - function to handle some ssr data
18
+ * @property {string} authMethod - authentication method
19
+ */
20
+
21
+ /**
22
+ * @param {Object} context - Miolo's app.ctx object
23
+ * @param {React.ReactNode} children - React children
24
+ * @returns {React.ReactNode}
25
+ */
6
26
  const MioloContextProvider = ({ context, children }) => {
7
27
  const [innerContext, setInnerContext] = useState(context)
8
28
  const [mioloObj, _setMioloObj] = useState(miolo_client(context))
@@ -0,0 +1,25 @@
1
+ let _historyPatched = false
2
+
3
+ export default function patchHistory() {
4
+ if (typeof window === "undefined" || _historyPatched) return
5
+
6
+ const originalPushState = window.history.pushState
7
+ window.history.pushState = function (...args) {
8
+ const ret = originalPushState.apply(this, args)
9
+ window.dispatchEvent(new Event("miolo-navigation"))
10
+ return ret
11
+ }
12
+
13
+ const originalReplaceState = window.history.replaceState
14
+ window.history.replaceState = function (...args) {
15
+ const ret = originalReplaceState.apply(this, args)
16
+ window.dispatchEvent(new Event("miolo-navigation"))
17
+ return ret
18
+ }
19
+
20
+ window.addEventListener("popstate", () => {
21
+ window.dispatchEvent(new Event("miolo-navigation"))
22
+ })
23
+
24
+ _historyPatched = true
25
+ }
@@ -0,0 +1,58 @@
1
+ import { useCallback } from "react"
2
+
3
+ const _makeSerializable = (obj) => {
4
+ try {
5
+ return JSON.parse(JSON.stringify(obj))
6
+ } catch (_) {
7
+ return obj
8
+ }
9
+ }
10
+
11
+ export default function useIndexedDb(name, logger, cache, ttl) {
12
+ const cacheInvalidate = useCallback(async () => {
13
+ if (typeof window !== "undefined") {
14
+ const { del } = await import("idb-keyval")
15
+ await del(`ssr-cache-${name}`)
16
+ }
17
+ }, [name])
18
+
19
+ const cacheSet = useCallback(
20
+ async (data) => {
21
+ if (cache === true) {
22
+ if (typeof window !== "undefined") {
23
+ try {
24
+ const { set } = await import("idb-keyval")
25
+ await set(`ssr-cache-${name}`, { data: _makeSerializable(data), ts: Date.now() })
26
+ } catch (err) {
27
+ logger.error(`[miolo-react][ssr][${name}] error setting cache for ${name}: ${err}`)
28
+ }
29
+ }
30
+ }
31
+ },
32
+ [logger, cache, name]
33
+ )
34
+
35
+ const cacheGet = useCallback(async () => {
36
+ if (cache === true) {
37
+ if (typeof window !== "undefined") {
38
+ try {
39
+ const { get } = await import("idb-keyval")
40
+ const cached = await get(`ssr-cache-${name}`)
41
+ if (cached && cached.data !== undefined) {
42
+ const expired = ttl !== undefined && Date.now() - cached.ts > ttl * 1000
43
+ return [cached.data, expired, cached.ts]
44
+ }
45
+ } catch (err) {
46
+ logger.error(`[miolo-react][ssr][${name}] error getting cache for ${name}: ${err}`)
47
+ }
48
+ }
49
+ }
50
+ return [null, false]
51
+ }, [logger, cache, name, ttl])
52
+
53
+ return {
54
+ cacheInvalidate,
55
+ cacheSet,
56
+ cacheGet
57
+ }
58
+ }
@@ -1,40 +1,39 @@
1
1
  import { useCallback, useEffect, useMemo, useRef, useState } from "react"
2
2
  import getSsrDataFromContext from "./getSsrDataFromContext.mjs"
3
+ import patchHistory from "./patchHistory.mjs"
4
+ import useIndexedDb from "./useIndexedDb.mjs"
3
5
  import useOnWindowFocus from "./useOnWindowFocus.mjs"
4
6
  import usePropsCheck from "./usePropsCheck.mjs"
5
7
 
6
- const _makeSerializable = (obj) => {
7
- try {
8
- return JSON.parse(JSON.stringify(obj))
9
- } catch (_) {
10
- return obj
11
- }
12
- }
13
-
14
- let _historyPatched = false
15
- const patchHistory = () => {
16
- if (typeof window === "undefined" || _historyPatched) return
17
-
18
- const originalPushState = window.history.pushState
19
- window.history.pushState = function (...args) {
20
- const ret = originalPushState.apply(this, args)
21
- window.dispatchEvent(new Event("miolo-navigation"))
22
- return ret
23
- }
24
-
25
- const originalReplaceState = window.history.replaceState
26
- window.history.replaceState = function (...args) {
27
- const ret = originalReplaceState.apply(this, args)
28
- window.dispatchEvent(new Event("miolo-navigation"))
29
- return ret
30
- }
31
-
32
- window.addEventListener("popstate", () => {
33
- window.dispatchEvent(new Event("miolo-navigation"))
34
- })
35
-
36
- _historyPatched = true
37
- }
8
+ /**
9
+ * @typedef {import('miolo-model').MioloModel} MioloModel
10
+ * @typedef {import('miolo-model').MioloArray} MioloArray
11
+ *
12
+ *
13
+ *
14
+ * @typedef {Object} MioloSSRDataOptions
15
+ * @property {any} [defval=[]] - The default value for the data.
16
+ * @property {Function} [loader] - A function that loads the data remotely. You need either @loader or @url.
17
+ * @property {string} [url] - The URL to load the data from. You need either @loader or @url.
18
+ * @property {Object} [params] - The parameters to pass to the @loader.
19
+ * @property {MioloModel} [model] - A MioloModel class for the data.
20
+ * @property {Function} [modifier] - A function that modifies the data (after ssr'ed or loaded, and after instantiated @model if any).
21
+ * @property {Function} [effect] - A function that is called when the data is loaded. The @effect function should return true if the data needs to be reloaded.
22
+ * @property {boolean} [cache=false] - Whether to cache the data.
23
+ * @property {number} [ttl] - The time to live for the cached data in seconds.
24
+ * @property {boolean} [autoRefresh=true] - Whether to automatically refresh the data on cache expiration.
25
+ *
26
+ *
27
+ * @typedef {Object} MioloSSRData
28
+ * @property {MioloModel | MioloArray | any} data - The data state. Generaly defined by @model and/or @modifier options.
29
+ * @property {Function} setData - Set the data state directly.
30
+ * @property {Function} refresh - If needed, remotely reload data (by calling @loader or @url).
31
+ * @property {Function} invalidate - Invalidate the data cache (requires @cache to be true).
32
+ * @property {string|undefined} error - The error message if any.
33
+ *
34
+ * @property {boolean} ok - Status of SSR data, true if everything was ssr'ed or remotely loaded ok.
35
+ * @property {boolean} ready - true when @data is loaded (either ssr'ed or remotely).
36
+ */
38
37
 
39
38
  const globalSocketState = {
40
39
  rooms: new Map(),
@@ -43,6 +42,18 @@ const globalSocketState = {
43
42
  versionsRequestedAt: 0
44
43
  }
45
44
 
45
+ /**
46
+ * Hook to get some ssr data or reload it if needed.
47
+ *
48
+ * @param {Object} context - The miolo context's state object.
49
+ * @param {Object} miolo - The miolo client object, that is:
50
+ * - @prop {Object} fetcher - The fetcher object.
51
+ * - @prop {Object} socket - The socket object.
52
+ * - @prop {Object} logger - The logger object.
53
+ * @param {string} name - The name of the data.
54
+ * @param {MioloSSRDataOptions} options - The options object:
55
+ * @returns {MioloSSRData}
56
+ */
46
57
  const useSsrDataOrReload = (context, miolo, name, options) => {
47
58
  const { fetcher, socket, logger } = miolo
48
59
  const {
@@ -85,46 +96,7 @@ const useSsrDataOrReload = (context, miolo, name, options) => {
85
96
  const [error, setError] = useState(undefined)
86
97
  const pendingLazyRefreshRef = useRef(false)
87
98
 
88
- const cacheInvalidate = useCallback(async () => {
89
- if (typeof window !== "undefined") {
90
- const { del } = await import("idb-keyval")
91
- await del(`ssr-cache-${name}`)
92
- }
93
- }, [name])
94
-
95
- const cacheSet = useCallback(
96
- async (data) => {
97
- if (cache === true) {
98
- if (typeof window !== "undefined") {
99
- try {
100
- const { set } = await import("idb-keyval")
101
- await set(`ssr-cache-${name}`, { data: _makeSerializable(data), ts: Date.now() })
102
- } catch (err) {
103
- logger.error(`[miolo-react][ssr][${name}] error setting cache for ${name}: ${err}`)
104
- }
105
- }
106
- }
107
- },
108
- [logger, cache, name]
109
- )
110
-
111
- const cacheGet = useCallback(async () => {
112
- if (cache === true) {
113
- if (typeof window !== "undefined") {
114
- try {
115
- const { get } = await import("idb-keyval")
116
- const cached = await get(`ssr-cache-${name}`)
117
- if (cached && cached.data !== undefined) {
118
- const expired = ttl !== undefined && Date.now() - cached.ts > ttl * 1000
119
- return [cached.data, expired, cached.ts]
120
- }
121
- } catch (err) {
122
- logger.error(`[miolo-react][ssr][${name}] error getting cache for ${name}: ${err}`)
123
- }
124
- }
125
- }
126
- return [null, false]
127
- }, [logger, cache, name, ttl])
99
+ const { cacheInvalidate, cacheSet, cacheGet } = useIndexedDb(name, logger, cache, ttl)
128
100
 
129
101
  const updateSsrData = useCallback(
130
102
  (data) => {