import { checkErrors } from "./runtime" ; import { createLogger , StorageHelper , StorageHelperOptions } from "../utils" ; export interface ChromeStorageHelperOptions < T > extends Omit < StorageHelperOptions < T > , "storage" > { area ? : chrome . storage . AreaName ; } export function createStorageHelper < T > ( key , options ) { const { area = "local" , autoLoad = true , autoSyncDelay = 250 , defaultValue , migrations , } = options ; const logger = createLogger ( { systemPrefix : `[${ area . toUpperCase ( ) }]: chrome.storage["${ key }"]` , } ) ; let storageResourceVersion = 1 ; const chromeStorage = chrome . storage [ area ] ; const metadataVersionKey = `${ key }@version` ; const storageHelper = new StorageHelper < T > ( key , { autoLoad , autoSyncDelay , defaultValue , migrations , storage : { async setItem ( key , value ) { return new Promise ( resolve => { chromeStorage . set ( { [ key ] : value , [ metadataVersionKey ] : ++ storageResourceVersion , } , ( ) => resolve ( checkErrors ( ) ) ) ; } ) ; } , async getItem ( key ) { return new Promise ( resolve => { chromeStorage . get ( [ key , metadataVersionKey ] , items => { storageResourceVersion = Math . max ( storageResourceVersion , items [ metadataVersionKey ] ?? 0 ) ; resolve ( checkErrors ( items [ key ] ) ) ; } ) ; } ) ; } , async removeItem ( key ) { return new Promise ( resolve => { chromeStorage . remove ( [ key , metadataVersionKey ] , ( ) => resolve ( checkErrors ( ) ) ) ; } ) ; } , } , } ) ; chrome . storage . onChanged . addListener ( ( changes , areaName ) => { if ( area !== areaName || ! changes [ key ] || ! storageHelper . loaded ) return ; const { newValue : storageState } = changes [ key ] ; const resourceVersion = changes [ metadataVersionKey ] ?. newValue ; const isUpdateRequired = resourceVersion > storageResourceVersion ; logger . info ( `received update` , { origin : location . href , isUpdateRequired , ... changes } ) ; if ( isUpdateRequired ) { storageResourceVersion = resourceVersion ; storageHelper . set ( storageState , { silent : true , } ) ; } } ) ; return storageHelper ; }