Content-Length: 656693 | pFad | http://github.com/vueuse/vueuse/commit/bb831783fd470acb2bb513d5135099f4354c47d2

04 feat(useIDBKeyval): add `options.serializer` (#4781) · vueuse/vueuse@bb83178 · GitHub
Skip to content

Commit bb83178

Browse files
matthewjumpsoffbuildingsOrbisK43081j
authored
feat(useIDBKeyval): add options.serializer (#4781)
Co-authored-by: Robin <robin.kehl@singular-it.de> Co-authored-by: James Garbutt <43081j@users.noreply.github.com>
1 parent e17c567 commit bb83178

File tree

2 files changed

+87
-23
lines changed

2 files changed

+87
-23
lines changed

packages/integrations/useIDBKeyval/index.test.ts

Lines changed: 63 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,20 @@
1+
import type { Ref } from 'vue'
12
import { get, set } from 'idb-keyval'
2-
import { beforeEach, describe, expect, it, vi } from 'vitest'
3+
import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest'
34
import { nextTick } from 'vue'
45
import { useIDBKeyval } from './index'
56

6-
const cache = {} as any
7+
const cache = new Map<string, unknown>()
78

89
vi.mock('idb-keyval', () => ({
9-
get: (key: string) => Promise.resolve(cache[key]),
10+
get: (key: string) => Promise.resolve(cache.get(key)),
1011
set: vi.fn((key: string, value: any) => new Promise((resolve, reject) => {
1112
if (value === 'error') {
1213
reject(new Error('set error'))
1314
return
1415
}
1516

16-
cache[key] = value
17+
cache.set(key, value)
1718

1819
resolve(undefined)
1920
})),
@@ -24,30 +25,39 @@ vi.mock('idb-keyval', () => ({
2425
return
2526
}
2627

27-
cache[key] = value
28+
cache.set(key, value)
2829

2930
resolve(undefined)
3031
}),
3132
del: (key: string) => {
32-
delete cache[key]
33+
cache.delete(key)
3334
},
3435
}))
3536

3637
const KEY1 = 'vue-use-idb-keyval-1'
3738
const KEY2 = 'vue-use-idb-keyval-2'
3839
const KEY3 = 'vue-use-idb-keyval-3'
3940
const KEY4 = 'vue-use-idb-keyval-4'
41+
4042
describe('useIDBKeyval', () => {
41-
beforeEach(() => {
42-
vi.clearAllMocks()
43+
let data1: Ref<{ count: number } | null>
44+
let data2: Ref<string[] | null>
45+
let data3: Ref<string | null>
46+
47+
beforeEach(async () => {
4348
console.error = vi.fn()
44-
})
4549

46-
set(KEY3, 'hello')
50+
await set(KEY3, 'hello');
4751

48-
const { data: data1 } = useIDBKeyval(KEY1, { count: 0 })
49-
const { data: data2 } = useIDBKeyval(KEY2, ['foo', 'bar'])
50-
const { data: data3 } = useIDBKeyval(KEY3, 'world', { shallow: true })
52+
({ data: data1 } = useIDBKeyval(KEY1, { count: 0 }));
53+
({ data: data2 } = useIDBKeyval(KEY2, ['foo', 'bar']));
54+
({ data: data3 } = useIDBKeyval(KEY3, 'world', { shallow: true }))
55+
})
56+
57+
afterEach(() => {
58+
vi.clearAllMocks()
59+
cache.clear()
60+
})
5161

5262
it('get/set', async () => {
5363
expect(data1.value).toEqual({ count: 0 })
@@ -60,8 +70,8 @@ describe('useIDBKeyval', () => {
6070
})
6171

6272
it('update', async () => {
63-
data1.value.count++
64-
data2.value.push('woo')
73+
data1.value!.count++
74+
data2.value!.push('woo')
6575
data3.value = 'world'
6676

6777
expect(await get(KEY1)).toEqual(data1.value)
@@ -109,6 +119,43 @@ describe('useIDBKeyval', () => {
109119
it('writeDefaults false', async () => {
110120
useIDBKeyval(KEY4, 'test', { writeDefaults: false })
111121

112-
expect(set).toHaveBeenCalledTimes(0)
122+
// the initial 3 IDB calls minus this one
123+
expect(set).toHaveBeenCalledTimes(3)
124+
})
125+
it('get/set with serializer', async () => {
126+
const serializer = {
127+
read(raw: unknown): string {
128+
return raw === 1 ? 'foo' : 'bar'
129+
},
130+
write(value: string): unknown {
131+
return value === 'foo' ? 1 : 0
132+
},
133+
}
134+
135+
const { data } = useIDBKeyval(KEY4, 'foo', { serializer })
136+
137+
await nextTick()
138+
139+
expect(data.value).toEqual('foo')
140+
expect(await get(KEY4)).toEqual(1)
141+
})
142+
it('get/set with serializer and existing value', async () => {
143+
const serializer = {
144+
read(raw: unknown): string {
145+
return raw === 1 ? 'foo' : 'bar'
146+
},
147+
write(value: string): unknown {
148+
return value === 'foo' ? 1 : 0
149+
},
150+
}
151+
152+
await set(KEY4, 0)
153+
154+
const { data } = useIDBKeyval(KEY4, 'foo', { serializer })
155+
156+
await nextTick()
157+
158+
expect(data.value).toEqual('bar')
159+
expect(await get(KEY4)).toEqual(0)
113160
})
114161
})

packages/integrations/useIDBKeyval/index.ts

Lines changed: 24 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,12 @@ import { watchPausable } from '@vueuse/core'
44
import { del, get, set, update } from 'idb-keyval'
55
import { ref as deepRef, shallowRef, toRaw, toValue } from 'vue'
66

7-
export interface UseIDBOptions extends ConfigurableFlush {
7+
interface Serializer<T> {
8+
read: (raw: unknown) => T
9+
write: (value: T) => unknown
10+
}
11+
12+
export interface UseIDBOptions<T> extends ConfigurableFlush {
813
/**
914
* Watch for deep changes
1015
*
@@ -31,6 +36,11 @@ export interface UseIDBOptions extends ConfigurableFlush {
3136
* @default true
3237
*/
3338
writeDefaults?: boolean
39+
40+
/**
41+
* Custom data serialization
42+
*/
43+
serializer?: Serializer<T>
3444
}
3545

3646
export interface UseIDBKeyvalReturn<T> {
@@ -48,7 +58,7 @@ export interface UseIDBKeyvalReturn<T> {
4858
export function useIDBKeyval<T>(
4959
key: IDBValidKey,
5060
initialValue: MaybeRefOrGetter<T>,
51-
options: UseIDBOptions = {},
61+
options: UseIDBOptions<T> = {},
5262
): UseIDBKeyvalReturn<T> {
5363
const {
5464
flush = 'pre',
@@ -58,6 +68,10 @@ export function useIDBKeyval<T>(
5868
console.error(e)
5969
},
6070
writeDefaults = true,
71+
serializer = {
72+
read: (raw: unknown) => raw as T,
73+
write: (value: T) => value,
74+
},
6175
} = options
6276

6377
const isFinished = shallowRef(false)
@@ -69,11 +83,13 @@ export function useIDBKeyval<T>(
6983
try {
7084
const rawValue = await get<T>(key)
7185
if (rawValue === undefined) {
72-
if (rawInit !== undefined && rawInit !== null && writeDefaults)
73-
await set(key, rawInit)
86+
if (rawInit !== undefined && rawInit !== null && writeDefaults) {
87+
const initValue = serializer.write(rawInit)
88+
await set(key, initValue)
89+
}
7490
}
7591
else {
76-
data.value = rawValue
92+
data.value = serializer.read(rawValue)
7793
}
7894
}
7995
catch (e) {
@@ -90,8 +106,9 @@ export function useIDBKeyval<T>(
90106
await del(key)
91107
}
92108
else {
93-
// IndexedDB does not support saving proxies, convert from proxy before saving
94-
await update(key, () => toRaw(data.value))
109+
const rawValue = toRaw(data.value)
110+
const serializedValue = serializer.write(rawValue)
111+
await update(key, () => serializedValue)
95112
}
96113
}
97114
catch (e) {

0 commit comments

Comments
 (0)








ApplySandwichStrip

pFad - (p)hone/(F)rame/(a)nonymizer/(d)eclutterfier!      Saves Data!


--- a PPN by Garber Painting Akron. With Image Size Reduction included!

Fetched URL: http://github.com/vueuse/vueuse/commit/bb831783fd470acb2bb513d5135099f4354c47d2

Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy