lily/session

Session persistence allows certain model fields to survive page navigations via localStorage. This lets users carry authentication tokens, preferences, shopping cart data, and other session state across page loads without cookies. In Phoenix LiveView, the socket holds this persistence, and in some other frameworks, this may be purely server-side.

Session data is stored as individual fields in localStorage with the prefix lily_session_. Each field has its own encoder/decoder for type-safe serialisation.

Unlike the page store (which tears down on navigation), session data persists until explicitly cleared or expired.

Types

Configuration for a single persisted field within the session.

pub opaque type Field(session)

Complete session persistence configuration. Build using session.persistence and add fields with session.field.

pub opaque type Persistence(session)

Values

pub fn attach(
  runtime: client.Runtime(model, message),
  persistence persistence: Persistence(session),
  get get: fn(model) -> session,
  set set: fn(model, session) -> model,
) -> client.Runtime(model, message)

Attach session persistence to the runtime. Reads localStorage on start to hydrate the initial model, then writes changes to localStorage after each update. The get and set functions extract and inject the session slice from the model. The session data can be stored within your model for access. How you choose to do this is completely up to you, as session.attach only needs get and set functions as parameters.

Call this after creating the store but before client.start, or in the pipe chain after client.start.

Example

let persistence =
  session.persistence()
  |> session.field(
    key: "token",
    get: fn(session) { session.token },
    set: fn(session, value) { SessionData(..session, token: value) },
    encode: json.nullable(json.string),
    decoder: decode.optional(decode.string),
  )

store.new(Model(session: empty_session, ..), with: update)
|> session.attach(
  persistence:,
  get: fn(model) { model.session },
  set: fn(model, session) { Model(..model, session: session) },
)
|> client.start
pub fn clear() -> Nil

Clear all session data from localStorage. Removes all keys with the lily_session_ prefix.

Example

// On logout
fn update(model, msg) {
  case msg {
    Logout -> {
      session.clear()
      // Navigate to login page or clear session in model
      model
    }
    _ -> model
  }
}
pub fn field(
  persistence: Persistence(session),
  key key: String,
  get get: fn(session) -> a,
  set set: fn(session, a) -> session,
  encode encode: fn(a) -> json.Json,
  decoder decoder: decode.Decoder(a),
) -> Persistence(session)

Add a field to the session persistence configuration. Each field represents a single value stored in localStorage under lily_session_{key}.

The get and set functions extract and inject the field from the session type. The encode and decoder handle JSON serialisation.

Example

session.persistence()
|> session.field(
  key: "theme",
  get: fn(session) { session.theme },
  set: fn(session, theme) { SessionData(..session, theme: theme) },
  encode: theme_to_json,
  decoder: theme_decoder,
)
pub fn persistence() -> Persistence(session)

Create an empty session persistence configuration. Add fields using session.field.

Example

let persistence = session.persistence()
Search Document