import { Context, Effect as E, Layer, pipe } from "effect";
export class Storage extends Context.Tag("Storage")<
Storage,
{
readonly set: (key: string, value: string) => E.Effect<void, Error>;
readonly get: <T>(key: string, decode: (value: string) => T) => E.Effect<T, Error>;
}
>() {}
export const StorageLive = Layer.succeed(
Storage,
Storage.of({
set: (key, newValue) => {
return E.try({
try: () => window.localStorage.setItem(key, newValue),
catch: (cause) => Error("An error occured storing data.", { cause }),
}).pipe(E.tap(() => window.dispatchEvent(new StorageEvent("storage", { key, newValue }))));
},
get: (key, decode) => {
return pipe(
E.fromNullable(window.localStorage.getItem(key)),
E.match({
onFailure: (cause) => Error(`No data found matching key ${key}`, { cause }),
onSuccess: (value) => (decode ? decode(value) : value),
}),
);
},
}),
);
import { Context, Effect as E, Layer, pipe } from "effect";
export class Storage extends Context.Tag("Storage")<
Storage,
{
readonly set: (key: string, value: string) => E.Effect<void, Error>;
readonly get: <T>(key: string, decode: (value: string) => T) => E.Effect<T, Error>;
}
>() {}
export const StorageLive = Layer.succeed(
Storage,
Storage.of({
set: (key, newValue) => {
return E.try({
try: () => window.localStorage.setItem(key, newValue),
catch: (cause) => Error("An error occured storing data.", { cause }),
}).pipe(E.tap(() => window.dispatchEvent(new StorageEvent("storage", { key, newValue }))));
},
get: (key, decode) => {
return pipe(
E.fromNullable(window.localStorage.getItem(key)),
E.match({
onFailure: (cause) => Error(`No data found matching key ${key}`, { cause }),
onSuccess: (value) => (decode ? decode(value) : value),
}),
);
},
}),
);