miolo-react 3.0.0-beta.221 → 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.
|
|
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.
|
|
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
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
}
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
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 =
|
|
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) => {
|
|
@@ -195,7 +167,7 @@ const useSsrDataOrReload = (context, miolo, name, options) => {
|
|
|
195
167
|
)
|
|
196
168
|
await cacheInvalidate()
|
|
197
169
|
if (autoRefresh === true) {
|
|
198
|
-
refreshSsrData()
|
|
170
|
+
await refreshSsrData()
|
|
199
171
|
}
|
|
200
172
|
} else {
|
|
201
173
|
logger.verbose(`[miolo-react][ssr][${name}] ssr-versions match for ${name}`)
|
|
@@ -232,13 +204,13 @@ const useSsrDataOrReload = (context, miolo, name, options) => {
|
|
|
232
204
|
|
|
233
205
|
if (expired) {
|
|
234
206
|
logger.verbose(`[miolo-react][ssr][${name}] expired cache for ${name}, refreshing`)
|
|
235
|
-
refreshSsrData()
|
|
207
|
+
await refreshSsrData()
|
|
236
208
|
} else {
|
|
237
209
|
setStatus("loaded")
|
|
238
210
|
}
|
|
239
211
|
} else {
|
|
240
212
|
logger.verbose(`[miolo-react][ssr][${name}] no cached data for ${name}, refreshing`)
|
|
241
|
-
refreshSsrData()
|
|
213
|
+
await refreshSsrData()
|
|
242
214
|
}
|
|
243
215
|
}
|
|
244
216
|
}
|
|
@@ -347,7 +319,7 @@ const useSsrDataOrReload = (context, miolo, name, options) => {
|
|
|
347
319
|
await handlersRef.current.cacheInvalidate()
|
|
348
320
|
|
|
349
321
|
if (!data.lazy) {
|
|
350
|
-
handlersRef.current.refreshSsrData()
|
|
322
|
+
await handlersRef.current.refreshSsrData()
|
|
351
323
|
} else {
|
|
352
324
|
if (handlersRef.current.refreshSsrDataLazy) {
|
|
353
325
|
handlersRef.current.refreshSsrDataLazy()
|