my fork of the bluesky client
1import {MMKV} from 'react-native-mmkv'
2
3import {IS_DEV} from '#/env'
4import {Device} from '#/storage/schema'
5
6export * from '#/storage/schema'
7
8/**
9 * Generic storage class. DO NOT use this directly. Instead, use the exported
10 * storage instances below.
11 */
12export class Storage<Scopes extends unknown[], Schema> {
13 protected sep = ':'
14 protected store: MMKV
15
16 constructor({id}: {id: string}) {
17 this.store = new MMKV({id})
18 }
19
20 /**
21 * Store a value in storage based on scopes and/or keys
22 *
23 * `set([key], value)`
24 * `set([scope, key], value)`
25 */
26 set<Key extends keyof Schema>(
27 scopes: [...Scopes, Key],
28 data: Schema[Key],
29 ): void {
30 // stored as `{ data: <value> }` structure to ease stringification
31 this.store.set(scopes.join(this.sep), JSON.stringify({data}))
32 }
33
34 /**
35 * Get a value from storage based on scopes and/or keys
36 *
37 * `get([key])`
38 * `get([scope, key])`
39 */
40 get<Key extends keyof Schema>(
41 scopes: [...Scopes, Key],
42 ): Schema[Key] | undefined {
43 const res = this.store.getString(scopes.join(this.sep))
44 if (!res) return undefined
45 // parsed from storage structure `{ data: <value> }`
46 return JSON.parse(res).data
47 }
48
49 /**
50 * Remove a value from storage based on scopes and/or keys
51 *
52 * `remove([key])`
53 * `remove([scope, key])`
54 */
55 remove<Key extends keyof Schema>(scopes: [...Scopes, Key]) {
56 this.store.delete(scopes.join(this.sep))
57 }
58
59 /**
60 * Remove many values from the same storage scope by keys
61 *
62 * `removeMany([], [key])`
63 * `removeMany([scope], [key])`
64 */
65 removeMany<Key extends keyof Schema>(scopes: [...Scopes], keys: Key[]) {
66 keys.forEach(key => this.remove([...scopes, key]))
67 }
68}
69
70/**
71 * Device data that's specific to the device and does not vary based on account
72 *
73 * `device.set([key], true)`
74 */
75export const device = new Storage<[], Device>({id: 'bsky_device'})
76
77if (IS_DEV && typeof window !== 'undefined') {
78 // @ts-ignore
79 window.bsky_storage = {
80 device,
81 }
82}