| 42 | const APP_SALT = "oVzKtazBo7d8sb7TBvY9jw"; |
| 43 | |
| 44 | export class NNStorage implements IStorage { |
| 45 | database: IKVStore; |
| 46 | |
| 47 | constructor( |
| 48 | name: string, |
| 49 | private readonly keyStore: () => IKeyStore | null = () => null, |
| 50 | persistence: DatabasePersistence = "db" |
| 51 | ) { |
| 52 | this.database = |
| 53 | persistence === "memory" |
| 54 | ? new MemoryKVStore() |
| 55 | : isFeatureSupported("indexedDB") |
| 56 | ? new IndexedDBKVStore(name, "keyvaluepairs") |
| 57 | : new LocalStorageKVStore(); |
| 58 | } |
| 59 | |
| 60 | async migrate() { |
| 61 | if (!this.keyStore) return; |
| 62 | const user = await this.read<User>("user"); |
| 63 | if (!user) return; |
| 64 | |
| 65 | const key = await this._getCryptoKey(`_uk_@${user.email}`); |
| 66 | if (!key) return; |
| 67 | |
| 68 | await this.database.deleteMany([ |
| 69 | `_uk_@${user.email}`, |
| 70 | `_uk_@${user.email}@_k` |
| 71 | ]); |
| 72 | await this.keyStore()?.setValue("userEncryptionKey", key); |
| 73 | } |
| 74 | |
| 75 | read<T>(key: string): Promise<T | undefined> { |
| 76 | if (!key) return Promise.resolve(undefined); |
| 77 | return this.database.get(key); |
| 78 | } |
| 79 | |
| 80 | readMulti<T>(keys: string[]): Promise<[string, T][]> { |
| 81 | if (keys.length <= 0) return Promise.resolve([]); |
| 82 | return this.database.getMany(keys.sort()); |
| 83 | } |
| 84 | |
| 85 | writeMulti<T>(entries: [string, T][]) { |
| 86 | return this.database.setMany(entries); |
| 87 | } |
| 88 | |
| 89 | write<T>(key: string, data: T) { |
| 90 | return this.database.set(key, data); |
| 91 | } |
| 92 | |
| 93 | remove(key: string) { |
| 94 | return this.database.delete(key); |
| 95 | } |
| 96 | |
| 97 | removeMulti(keys: string[]) { |
| 98 | return this.database.deleteMany(keys); |
| 99 | } |
| 100 | |
| 101 | clear() { |
nothing calls this directly
no outgoing calls
no test coverage detected