# `PhoenixDatastar.Socket`
[🔗](https://github.com/RicoTrevisan/phoenix_datastar/blob/v0.1.16/lib/socket.ex#L1)

Socket struct for PhoenixDatastar, similar to Phoenix.LiveView.Socket.
Holds the view module, session id, assigns, signals, private data, and queued events.

## Assigns vs Signals

- **Assigns** are server-side state, never sent to the client. Use `assign/2,3` and
  `update/3` to work with assigns. They are available in templates as `@key`.

- **Signals** are Datastar reactive state sent to the client via SSE. Use `put_signal/2,3`
  and `update_signal/3` to work with signals. They must be JSON-serializable. The client
  accesses them via Datastar expressions like `$count`. Signals are **not** available
  as `@key` in templates — Datastar handles their rendering client-side.

# `event`
[🔗](https://github.com/RicoTrevisan/phoenix_datastar/blob/v0.1.16/lib/socket.ex#L54)

```elixir
@type event() ::
  {:patch, String.t(), String.t()}
  | {:patch, String.t(), String.t(), keyword()}
  | {:script, String.t(), keyword()}
```

# `t`
[🔗](https://github.com/RicoTrevisan/phoenix_datastar/blob/v0.1.16/lib/socket.ex#L59)

```elixir
@type t() :: %PhoenixDatastar.Socket{
  assigns: map(),
  events: [event()],
  id: String.t() | nil,
  private: map(),
  signals: map(),
  view: module()
}
```

# `assign`
[🔗](https://github.com/RicoTrevisan/phoenix_datastar/blob/v0.1.16/lib/socket.ex#L92)

```elixir
@spec assign(t(), map() | keyword()) :: t()
```

Merges assigns into the socket from a map or keyword list.

## Examples

    assign(socket, %{user: user, settings: settings})
    assign(socket, user: user, settings: settings)

# `assign`
[🔗](https://github.com/RicoTrevisan/phoenix_datastar/blob/v0.1.16/lib/socket.ex#L79)

```elixir
@spec assign(t(), atom(), any()) :: t()
```

Assigns a single key-value pair to the socket's server-side assigns.

Assigns are never sent to the client. Use `put_signal/3` for client-side
Datastar signals.

## Examples

    assign(socket, :user, %User{name: "Alice"})

# `console_log`
[🔗](https://github.com/RicoTrevisan/phoenix_datastar/blob/v0.1.16/lib/socket.ex#L285)

```elixir
@spec console_log(t(), term(), keyword()) :: t()
```

Queues a console.log to be executed on the client via SSE.

## Options

- `:level` - Console method: `:log`, `:warn`, `:error`, `:info`, `:debug` (default: :log)
- Plus all options from `execute_script/3`

## Examples

    socket
    |> console_log("Debug message")

    socket
    |> console_log("Warning!", level: :warn)

    socket
    |> console_log(%{user: "alice", action: "login"}, level: :info)

# `execute_script`
[🔗](https://github.com/RicoTrevisan/phoenix_datastar/blob/v0.1.16/lib/socket.ex#L232)

```elixir
@spec execute_script(t(), String.t(), keyword()) :: t()
```

Queues a JavaScript script to be executed on the client via SSE.

## Options

- `:auto_remove` - Remove script tag after execution (default: true)
- `:attributes` - Map of additional script tag attributes

## Examples

    socket
    |> execute_script("alert('Hello!')")

    socket
    |> execute_script("console.log('debug')", auto_remove: false)

    # ES module script
    socket
    |> execute_script("import {...} from 'module'", attributes: %{type: "module"})

# `new`
[🔗](https://github.com/RicoTrevisan/phoenix_datastar/blob/v0.1.16/lib/socket.ex#L37)

```elixir
@spec new(String.t(), module(), String.t(), keyword()) :: t()
```

Creates a new socket with standard assigns.

## Options

  * `:live` - Whether this is a live (stateful) view. Defaults to `true`.
    When `false`, `stream_path` is set to `nil`.
  * `:flash` - Flash map. Defaults to `%{}`.

## Examples

    Socket.new(session_id, MyApp.CounterStar, "/counter")
    Socket.new(session_id, MyApp.PageStar, "/about", live: false)

# `patch_elements`
[🔗](https://github.com/RicoTrevisan/phoenix_datastar/blob/v0.1.16/lib/socket.ex#L190)

```elixir
@spec patch_elements(
  t(),
  String.t(),
  (map() -&gt; Phoenix.HTML.Safe.t()) | Phoenix.HTML.Safe.t()
) :: t()
```

Queues an HTML patch to be sent via SSE.

The selector is a CSS selector targeting the element to patch.
The second argument can be either:
- A render function that takes assigns and returns HTML
- Raw HTML content (must implement Phoenix.HTML.Safe)

The render function receives `socket.assigns` (server-side state only,
not signals).

## Examples

With a render function (recommended for pipelines):

    socket
    |> assign(:items, updated_items)
    |> patch_elements("#items", &render_items/1)
    |> then(&{:noreply, &1})

    defp render_items(assigns) do
      ~H|<ul id="items"><li :for={item <- @items}>{item}</li></ul>|
    end

With raw HTML:

    socket
    |> patch_elements("#count", ~H"<span id="count">42</span>")

# `put_signal`
[🔗](https://github.com/RicoTrevisan/phoenix_datastar/blob/v0.1.16/lib/socket.ex#L137)

```elixir
@spec put_signal(t(), map() | keyword()) :: t()
```

Merges signals into the socket from a map or keyword list.

## Examples

    put_signal(socket, %{count: 0, name: "test"})
    put_signal(socket, count: 0, name: "test")

# `put_signal`
[🔗](https://github.com/RicoTrevisan/phoenix_datastar/blob/v0.1.16/lib/socket.ex#L124)

```elixir
@spec put_signal(t(), atom(), any()) :: t()
```

Puts a single Datastar signal on the socket.

Signals are sent to the client and must be JSON-serializable.
They are accessed client-side via Datastar expressions (e.g., `$count`).

## Examples

    put_signal(socket, :count, 0)

# `redirect`
[🔗](https://github.com/RicoTrevisan/phoenix_datastar/blob/v0.1.16/lib/socket.ex#L255)

```elixir
@spec redirect(t(), String.t(), keyword()) :: t()
```

Queues a redirect to be executed on the client via SSE.

Uses setTimeout for proper browser history handling, especially in Firefox.

## Options

Same as `execute_script/3`.

## Examples

    socket
    |> redirect("/dashboard")

    socket
    |> redirect("https://example.com")

# `update`
[🔗](https://github.com/RicoTrevisan/phoenix_datastar/blob/v0.1.16/lib/socket.ex#L108)

```elixir
@spec update(t(), atom(), (any() -&gt; any())) :: t()
```

Updates an assign using a function.

## Examples

    update(socket, :user, &User.increment_visits/1)

# `update_signal`
[🔗](https://github.com/RicoTrevisan/phoenix_datastar/blob/v0.1.16/lib/socket.ex#L153)

```elixir
@spec update_signal(t(), atom(), (any() -&gt; any())) :: t()
```

Updates a signal using a function.

## Examples

    update_signal(socket, :count, &(&1 + 1))

---

*Consult [api-reference.md](api-reference.md) for complete listing*
