11class FlagStorage {
2- private dbName = 'databuddy-flags' ;
3- private version = 1 ;
4- private storeName = 'flags' ;
52 private ttl = 24 * 60 * 60 * 1000 ; // 24 hours in milliseconds
63
74 async get ( key : string ) : Promise < any > {
8- try {
9- const db = await this . openDB ( ) ;
10- const transaction = db . transaction ( this . storeName , 'readonly' ) ;
11- const store = transaction . objectStore ( this . storeName ) ;
12- return new Promise ( ( resolve ) => {
13- const request = store . get ( key ) ;
14- request . onsuccess = ( ) => {
15- const result = request . result ;
16- if ( result && this . isExpired ( result . expiresAt ) ) {
17- this . delete ( key ) ;
18- resolve ( null ) ;
19- } else {
20- resolve ( result ?. value ) ;
21- }
22- } ;
23- request . onerror = ( ) => resolve ( null ) ;
24- } ) ;
25- } catch {
26- return this . getFromLocalStorage ( key ) ;
27- }
5+ return this . getFromLocalStorage ( key ) ;
286 }
297
308 async set ( key : string , value : unknown ) : Promise < void > {
31- try {
32- const db = await this . openDB ( ) ;
33- const transaction = db . transaction ( this . storeName , 'readwrite' ) ;
34- const store = transaction . objectStore ( this . storeName ) ;
35- const expiresAt = Date . now ( ) + this . ttl ;
36- store . put ( { key, value, timestamp : Date . now ( ) , expiresAt } ) ;
37- } catch {
38- this . setToLocalStorage ( key , value ) ;
39- }
9+ this . setToLocalStorage ( key , value ) ;
4010 }
4111
4212 async getAll ( ) : Promise < Record < string , unknown > > {
43- try {
44- const db = await this . openDB ( ) ;
45- const transaction = db . transaction ( this . storeName , 'readonly' ) ;
46- const store = transaction . objectStore ( this . storeName ) ;
47- return new Promise ( ( resolve ) => {
48- const request = store . getAll ( ) ;
49- request . onsuccess = ( ) => {
50- const result : Record < string , unknown > = { } ;
51- const expiredKeys : string [ ] = [ ] ;
52-
53- for ( const item of request . result || [ ] ) {
54- if ( this . isExpired ( item . expiresAt ) ) {
55- expiredKeys . push ( item . key ) ;
13+ const result : Record < string , unknown > = { } ;
14+ const now = Date . now ( ) ;
15+ Object . keys ( localStorage )
16+ . filter ( ( key ) => key . startsWith ( 'db-flag-' ) )
17+ . forEach ( ( key ) => {
18+ const flagKey = key . replace ( 'db-flag-' , '' ) ;
19+ try {
20+ const item = localStorage . getItem ( key ) ;
21+ if ( item ) {
22+ const parsed = JSON . parse ( item ) ;
23+ if ( parsed . expiresAt && now > parsed . expiresAt ) {
24+ localStorage . removeItem ( key ) ;
5625 } else {
57- result [ item . key ] = item . value ;
26+ result [ flagKey ] = parsed . value || parsed ; // Support both new and old format
5827 }
5928 }
60-
61- if ( expiredKeys . length > 0 ) {
62- this . deleteMultiple ( expiredKeys ) ;
63- }
64-
65- resolve ( result ) ;
66- } ;
67- request . onerror = ( ) => resolve ( { } ) ;
29+ } catch { }
6830 } ) ;
69- } catch {
70- const result : Record < string , unknown > = { } ;
71- const now = Date . now ( ) ;
72- Object . keys ( localStorage )
73- . filter ( ( key ) => key . startsWith ( 'db-flag-' ) )
74- . forEach ( ( key ) => {
75- const flagKey = key . replace ( 'db-flag-' , '' ) ;
76- try {
77- const item = localStorage . getItem ( key ) ;
78- if ( item ) {
79- const parsed = JSON . parse ( item ) ;
80- if ( parsed . expiresAt && now > parsed . expiresAt ) {
81- localStorage . removeItem ( key ) ;
82- } else {
83- result [ flagKey ] = parsed . value || parsed ; // Support both new and old format
84- }
85- }
86- } catch { }
87- } ) ;
88- return result ;
89- }
31+ return result ;
9032 }
9133
9234 async clear ( ) : Promise < void > {
93- try {
94- const db = await this . openDB ( ) ;
95- const transaction = db . transaction ( this . storeName , 'readwrite' ) ;
96- const store = transaction . objectStore ( this . storeName ) ;
97- store . clear ( ) ;
98- } catch {
99- Object . keys ( localStorage )
100- . filter ( ( key ) => key . startsWith ( 'db-flag-' ) )
101- . forEach ( ( key ) => {
102- localStorage . removeItem ( key ) ;
103- } ) ;
104-
105- return ;
106- }
107- }
108-
109- private async openDB ( ) : Promise < IDBDatabase > {
110- return new Promise ( ( resolve , reject ) => {
111- const request = indexedDB . open ( this . dbName , this . version ) ;
112-
113- request . onerror = ( ) => reject ( request . error ) ;
114- request . onsuccess = ( ) => resolve ( request . result ) ;
115-
116- request . onupgradeneeded = ( ) => {
117- const db = request . result ;
118- if ( ! db . objectStoreNames . contains ( this . storeName ) ) {
119- db . createObjectStore ( this . storeName , { keyPath : 'key' } ) ;
120- }
121- } ;
122- } ) ;
35+ Object . keys ( localStorage )
36+ . filter ( ( key ) => key . startsWith ( 'db-flag-' ) )
37+ . forEach ( ( key ) => {
38+ localStorage . removeItem ( key ) ;
39+ } ) ;
12340 }
12441
12542 private getFromLocalStorage ( key : string ) : any {
@@ -164,28 +81,12 @@ class FlagStorage {
16481 }
16582
16683 async delete ( key : string ) : Promise < void > {
167- try {
168- const db = await this . openDB ( ) ;
169- const transaction = db . transaction ( this . storeName , 'readwrite' ) ;
170- const store = transaction . objectStore ( this . storeName ) ;
171- store . delete ( key ) ;
172- } catch {
173- localStorage . removeItem ( `db-flag-${ key } ` ) ;
174- }
84+ localStorage . removeItem ( `db-flag-${ key } ` ) ;
17585 }
17686
17787 async deleteMultiple ( keys : string [ ] ) : Promise < void > {
178- try {
179- const db = await this . openDB ( ) ;
180- const transaction = db . transaction ( this . storeName , 'readwrite' ) ;
181- const store = transaction . objectStore ( this . storeName ) ;
182- for ( const key of keys ) {
183- store . delete ( key ) ;
184- }
185- } catch {
186- for ( const key of keys ) {
187- localStorage . removeItem ( `db-flag-${ key } ` ) ;
188- }
88+ for ( const key of keys ) {
89+ localStorage . removeItem ( `db-flag-${ key } ` ) ;
18990 }
19091 }
19192
@@ -206,50 +107,22 @@ class FlagStorage {
206107 }
207108
208109 async cleanupExpired ( ) : Promise < void > {
209- try {
210- const db = await this . openDB ( ) ;
211- const transaction = db . transaction ( this . storeName , 'readwrite' ) ;
212- const store = transaction . objectStore ( this . storeName ) ;
213-
214- return new Promise ( ( resolve ) => {
215- const request = store . getAll ( ) ;
216- request . onsuccess = ( ) => {
217- const expiredKeys : string [ ] = [ ] ;
218- for ( const item of request . result || [ ] ) {
219- if ( this . isExpired ( item . expiresAt ) ) {
220- expiredKeys . push ( item . key ) ;
110+ const now = Date . now ( ) ;
111+ Object . keys ( localStorage )
112+ . filter ( ( key ) => key . startsWith ( 'db-flag-' ) )
113+ . forEach ( ( key ) => {
114+ try {
115+ const item = localStorage . getItem ( key ) ;
116+ if ( item ) {
117+ const parsed = JSON . parse ( item ) ;
118+ if ( parsed . expiresAt && now > parsed . expiresAt ) {
119+ localStorage . removeItem ( key ) ;
221120 }
222121 }
223-
224- if ( expiredKeys . length > 0 ) {
225- this . deleteMultiple ( expiredKeys )
226- . then ( ( ) => resolve ( ) )
227- . catch ( ( ) => resolve ( ) ) ;
228- } else {
229- resolve ( ) ;
230- }
231- } ;
232- request . onerror = ( ) => resolve ( ) ;
122+ } catch {
123+ localStorage . removeItem ( key ) ;
124+ }
233125 } ) ;
234- } catch {
235- this . cleanupExpired ( ) ;
236- const now = Date . now ( ) ;
237- Object . keys ( localStorage )
238- . filter ( ( key ) => key . startsWith ( 'db-flag-' ) )
239- . forEach ( ( key ) => {
240- try {
241- const item = localStorage . getItem ( key ) ;
242- if ( item ) {
243- const parsed = JSON . parse ( item ) ;
244- if ( parsed . expiresAt && now > parsed . expiresAt ) {
245- localStorage . removeItem ( key ) ;
246- }
247- }
248- } catch {
249- localStorage . removeItem ( key ) ;
250- }
251- } ) ;
252- }
253126 }
254127}
255128
0 commit comments