import { CurriedFunction2 , curry2 } from '@most/prelude' ; import { LocalStorageClearCommand , LocalStorageCommand , LocalStorageRemoveItemCommand , LocalStorageSetItemCommand , LocalStorageSource , } from './types' ; import { Stream , constant , drain , filter , fromEvent , map , merge , multicast , skipRepeats , startWith , tap , } from 'most' ; import { hold } from '@most/hold' ; export interface LocalStorageSinks { localStorage$ : Stream < LocalStorageCommand > ; } export interface LocalStorageSources { localStorage : LocalStorageSource ; } export function LocalStorage ( sinks ) { const { localStorage$ } = sinks ; const localStorageEvent$ = filter ( isLocalStorageEvent , fromEvent < StorageEvent > ( 'storage' , window , true ) ) ; const storage$ = multicast ( merge ( constant ( window . localStorage , tap ( storageAction , localStorage$ ) ) , constant ( window . localStorage , localStorageEvent$ ) ) ) ; drain ( storage$ ) ; const getItem = createGetItem ( storage$ ) ; const length = createLength ( storage$ ) ; const localStorage = { getItem , length } ; return { localStorage } ; } export function clear ( ) { return { method : 'clear' } ; } export function removeItem ( key ) { return { method : 'removeItem' , key } ; } export const setItem = curry2 ( function setItem ( key , value ) : LocalStorageSetItemCommand { return { method : 'setItem' , key , value } ; } ) ; function storageAction ( command ) { if ( command . method === 'clear' ) window . localStorage . clear ( ) ; if ( command . method === 'removeItem' ) window . localStorage . removeItem ( command . key ) ; if ( command . method === 'setItem' ) window . localStorage . setItem ( command . key , command . value ) ; } function createGetItem ( storage$ ) { return function getItem ( key ) : Stream < string | null > { return hold ( skipRepeats ( map ( ( storage ) => storage . getItem ( key ) , startWith ( window . localStorage , storage$ ) ) ) ) ; } ; } function createLength ( storage$ ) { return function length ( ) : Stream < number > { return hold ( skipRepeats ( map ( ( storage ) => storage . length , startWith ( window . localStorage , storage$ ) ) ) ) ; } ; } function isLocalStorageEvent ( event ) { return event . storageArea === window . localStorage ; }