/
server.ts
89 lines (77 loc) · 2.44 KB
/
server.ts
1
2
3
4
5
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
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
import {type SanityClient} from '@sanity/client'
import DataLoader from 'dataloader'
import {catchError, from, map, of} from 'rxjs'
import {DEFAULT_STUDIO_CLIENT_OPTIONS} from '../../../studioClient'
import {type KeyValueStoreValue} from '../types'
import {type Backend, type KeyValuePair} from './types'
/** @internal */
export interface ServerBackendOptions {
client: SanityClient
}
/**
* One of serveral possible backends for KeyValueStore. This backend uses the
* Sanity client to store and retrieve key-value pairs from the /users/me/keyvalue endpoint.
* @internal
*/
export function serverBackend({client: _client}: ServerBackendOptions): Backend {
const client = _client.withConfig({...DEFAULT_STUDIO_CLIENT_OPTIONS, apiVersion: 'vX'})
const keyValueLoader = new DataLoader<string, KeyValueStoreValue | null>(async (keys) => {
const value = await client
.request<KeyValuePair[]>({
uri: `/users/me/keyvalue/${keys.join(',')}`,
withCredentials: true,
})
.catch((error) => {
console.error('Error fetching data:', error)
return Array(keys.length).fill(null)
})
const keyValuePairs = value.reduce(
(acc, next) => {
if (next?.key) {
acc[next.key] = next.value
}
return acc
},
{} as Record<string, KeyValueStoreValue | null>,
)
const result = keys.map((key) => keyValuePairs[key] || null)
return result
})
const getKeys = (keys: string[]) => {
return from(keyValueLoader.loadMany(keys))
}
const setKeys = (keyValuePairs: KeyValuePair[]) => {
return from(
client.request<KeyValuePair[]>({
method: 'PUT',
uri: `/users/me/keyvalue`,
body: keyValuePairs,
withCredentials: true,
}),
).pipe(
map((response) => {
return response.map((pair) => {
keyValueLoader.clear(pair.key)
keyValueLoader.prime(pair.key, pair.value)
return pair.value
})
}),
catchError((error) => {
console.error('Error setting data:', error)
return of(Array(keyValuePairs.length).fill(null))
}),
)
}
const getKey = (key: string) => {
return getKeys([key]).pipe(map((values) => values[0]))
}
const setKey = (key: string, nextValue: unknown) => {
return setKeys([{key, value: nextValue as KeyValueStoreValue}]).pipe(map((values) => values[0]))
}
return {
getKey,
setKey,
getKeys,
setKeys,
}
}