//// Typed access to the Web Storage API. import gleam/dynamic/decode import gleam/json.{type Json} import gleam/result import plinth/javascript/storage as plinth_storage /// An error that occurs when reading. pub type ReadError { /// A value was not found with the given key. NotFound /// The found value could not be decoded. DecodeError(err: json.DecodeError) } pub opaque type TypedStorage(a) { TypedStorage( raw_storage: plinth_storage.Storage, reader: decode.Decoder(a), writer: fn(a) -> Json, ) } /// Create a new `TypedStorage`. pub fn new( raw_storage: plinth_storage.Storage, reader: decode.Decoder(a), writer: fn(a) -> Json, ) -> TypedStorage(a) { TypedStorage(raw_storage: raw_storage, reader: reader, writer: writer) } /// Get a value from the storage. pub fn get(storage: TypedStorage(a), key: String) -> Result(a, ReadError) { use str <- result.try( plinth_storage.get_item(storage.raw_storage, key) |> result.replace_error(NotFound), ) json.parse(str, storage.reader) |> result.map_error(DecodeError) } /// Set a value in the storage. pub fn set(storage: TypedStorage(a), key: String, value: a) -> Result(Nil, Nil) { let encoded = value |> storage.writer() |> json.to_string() plinth_storage.set_item(storage.raw_storage, key, encoded) } /// Remove a value from the storage. pub fn remove(storage: TypedStorage(a), key: String) -> Nil { plinth_storage.remove_item(storage.raw_storage, key) } /// Clear the whole storage. /// /// NOTE! This will clear the whole storage, not just values you have set. pub fn clear(storage: TypedStorage(a)) -> Nil { plinth_storage.clear(storage.raw_storage) }