@playfast/reform-query-browser 0.0.2 → 0.1.0
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,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@playfast/reform-query-browser",
|
|
3
3
|
"playbook": "./playbook",
|
|
4
|
-
"version": "0.0
|
|
4
|
+
"version": "0.1.0",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"description": "Browser host layers for Reform's AsyncCalc — window focus/online auto-invalidation and localStorage persistence. Keeps reform core DOM-free: implements the optional QueryEvents and QueryStore seams.",
|
|
7
7
|
"keywords": [
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { QueryStore, type QueryStoreApi, noopQueryStore } from '@playfast/reform'
|
|
2
|
-
import { Effect, Layer, Option } from 'effect'
|
|
2
|
+
import { Effect, Layer, Option, Schema } from 'effect'
|
|
3
3
|
|
|
4
4
|
// `QueryStore` implemented over `localStorage` (JSON values under a namespace
|
|
5
5
|
// prefix). The driver hands already-`output`-encoded values across this seam, so
|
|
@@ -8,26 +8,24 @@ import { Effect, Layer, Option } from 'effect'
|
|
|
8
8
|
|
|
9
9
|
const PREFIX = 'reform-query:'
|
|
10
10
|
|
|
11
|
-
const
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
// A hand-edited or version-skewed entry: treat as a cache miss, fetch fresh.
|
|
16
|
-
return Option.none()
|
|
17
|
-
}
|
|
18
|
-
}
|
|
11
|
+
const JsonValue = Schema.parseJson(Schema.Unknown)
|
|
12
|
+
// A hand-edited or version-skewed entry fails to decode → `None`: a cache miss, fetch fresh.
|
|
13
|
+
const decodeJson = Schema.decodeUnknownOption(JsonValue)
|
|
14
|
+
const encodeJson = Schema.encodeSync(JsonValue)
|
|
19
15
|
|
|
20
16
|
const makeApi = (): QueryStoreApi => {
|
|
21
|
-
if (typeof window === 'undefined' || typeof localStorage === 'undefined')
|
|
17
|
+
if (typeof window === 'undefined' || typeof localStorage === 'undefined') {
|
|
18
|
+
return noopQueryStore
|
|
19
|
+
}
|
|
22
20
|
return {
|
|
23
21
|
get: (key) =>
|
|
24
22
|
Effect.sync(() => {
|
|
25
23
|
const raw = localStorage.getItem(PREFIX + key)
|
|
26
|
-
return raw === null ? Option.none() :
|
|
24
|
+
return raw === null ? Option.none() : decodeJson(raw)
|
|
27
25
|
}),
|
|
28
|
-
set: (key,
|
|
26
|
+
set: (key, payload) =>
|
|
29
27
|
Effect.sync(() => {
|
|
30
|
-
localStorage.setItem(PREFIX + key,
|
|
28
|
+
localStorage.setItem(PREFIX + key, encodeJson(payload))
|
|
31
29
|
}),
|
|
32
30
|
remove: (key) =>
|
|
33
31
|
Effect.sync(() => {
|
|
@@ -11,17 +11,21 @@ import { Effect, Layer } from 'effect'
|
|
|
11
11
|
export const QueryEventsBrowser: Layer.Layer<QueryEvents> = Layer.scoped(
|
|
12
12
|
QueryEvents,
|
|
13
13
|
Effect.gen(function* () {
|
|
14
|
-
if (typeof window === 'undefined')
|
|
14
|
+
if (typeof window === 'undefined') {
|
|
15
|
+
return noopQueryEvents
|
|
16
|
+
}
|
|
15
17
|
|
|
16
18
|
const focusListeners = new Set<() => void>()
|
|
17
19
|
const onlineListeners = new Set<() => void>()
|
|
18
20
|
const fire = (listeners: ReadonlySet<() => void>) => {
|
|
19
|
-
|
|
21
|
+
listeners.forEach((listener) => listener())
|
|
20
22
|
}
|
|
21
23
|
// Refocus and tab-becomes-visible both count as "focus"; ignore the
|
|
22
24
|
// visibility event that fires on hide.
|
|
23
25
|
const onFocus = () => {
|
|
24
|
-
if (document.visibilityState === 'visible')
|
|
26
|
+
if (document.visibilityState === 'visible') {
|
|
27
|
+
fire(focusListeners)
|
|
28
|
+
}
|
|
25
29
|
}
|
|
26
30
|
const onOnline = () => fire(onlineListeners)
|
|
27
31
|
|
package/src/refetchManagers.ts
CHANGED
|
@@ -16,7 +16,7 @@ const onSignal = (
|
|
|
16
16
|
const events = yield* QueryEvents
|
|
17
17
|
const queries = yield* Queries
|
|
18
18
|
const invalidateAll = () => {
|
|
19
|
-
|
|
19
|
+
queries.byName.forEach((handle) => handle.invalidate())
|
|
20
20
|
}
|
|
21
21
|
const unsubscribe = pick(events)(invalidateAll)
|
|
22
22
|
yield* Effect.addFinalizer(() => Effect.sync(unsubscribe))
|