RpcElixir.Resolution (elixir_ts_rpc v0.0.2)

Copy Markdown View Source

Envelope threaded through the middleware pipeline for a single procedure invocation. Middleware receive and return a %Resolution{}.

Field ownership

One struct holds everything. Each field has its own writer. Ownership mirrors Plug.Conn:

  • :ctx — the transport sets it at construction. Middleware updates it with put_ctx/3 or assign/3. Read by handlers.
  • :private — middleware-owned. Use put_private/3 for framework-internal scratch data. Handlers never see it, because they receive only :ctx.
  • :params — reserved for middleware. The framework does not read or write it; validated input goes straight to the handler.
  • :state — set to :halted only via halt/2. Never set directly.
  • :resultdispatcher-owned. Middleware should not write to it directly; use halt/2 to short-circuit with an error. Direct writes pre-dispatch are clobbered by the handler step.
  • :procedure — set at construction time, never mutated.
  • :resp_cookies — middleware-writable. Use put_resp_cookie/4 or delete_resp_cookie/3. The transport adapter drains this onto the response after dispatch. Format: %{name => {value, opts}} for set, %{name => {:delete, opts}} for delete.
  • :resp_headers — middleware-writable. Use put_resp_header/3. The transport adapter appends these to the response. Duplicates are allowed (e.g. multiple Set-Cookie values). Format: [{name, value}].
  • :resp_session — middleware-writable. Use put_session/3, delete_session/2, or clear_session/1. The transport adapter drains this into the Plug session after dispatch. Requires Plug.Session to be configured earlier in the pipeline. Keys must be atoms or strings, and Plug stores both as strings. So put_session(res, :user_id, 1) reads back as ctx.req.session["user_id"].
  • :resp_session_clear — set only by clear_session/1. It wins over every other :resp_session entry.

All cookie, header, and session helpers are safe to call from middleware.

Halting

Calling halt/2 short-circuits remaining middleware and the handler. The dispatcher returns the resolution unchanged from that point.

Summary

Types

Cookie entry in resp_cookies — either a set or delete instruction.

Session entry in resp_session — either a value to set or :delete.

Pipeline execution state.

t()

Resolution envelope.

Functions

Stores application data under key in the context's :assigns map — the primary way middleware passes request-scoped data to handlers.

Marks the entire session to be cleared on the response.

Marks a cookie for deletion on the response.

Marks a session key for deletion on the response.

Halts the pipeline with an error.

Replaces a known field on the nested %Context{} struct.

Stores framework/library-private request-scoped data under key in the resolution's :private map. For application data, use assign/3 instead.

Stores a cookie to be set on the response.

Appends a response header. Duplicates are preserved (useful for headers like set-cookie that must be set separately per cookie).

Stores a session key-value pair to be set on the response.

Types

resp_session_entry()

@type resp_session_entry() :: term() | :delete

Session entry in resp_session — either a value to set or :delete.

state()

@type state() :: :continue | :halted

Pipeline execution state.

t()

@type t() :: %RpcElixir.Resolution{
  ctx: RpcElixir.Context.t(),
  params: map(),
  private: map(),
  procedure: String.t() | nil,
  resp_cookies: %{optional(String.t()) => resp_cookie_entry()},
  resp_headers: [{String.t(), String.t()}],
  resp_session: %{optional(term()) => resp_session_entry()},
  resp_session_clear: boolean(),
  result: {:ok, term()} | {:error, RpcElixir.RpcError.t()} | nil,
  state: state()
}

Resolution envelope.

Functions

assign(res, key, value)

@spec assign(t(), atom(), term()) :: t()

Stores application data under key in the context's :assigns map — the primary way middleware passes request-scoped data to handlers.

clear_session(res)

@spec clear_session(t()) :: t()

Marks the entire session to be cleared on the response.

This sets the :resp_session_clear flag. The transport adapter then calls Plug.Conn.clear_session/1. Any other resp_session entries are ignored after a clear.

delete_resp_cookie(res, name, opts \\ [])

@spec delete_resp_cookie(t(), String.t(), keyword()) :: t()

Marks a cookie for deletion on the response.

opts are forwarded to Plug.Conn.delete_resp_cookie/3 by the transport adapter.

delete_session(res, key)

@spec delete_session(t(), term()) :: t()

Marks a session key for deletion on the response.

halt(res, err)

@spec halt(t(), RpcElixir.RpcError.t() | term()) :: t()

Halts the pipeline with an error.

Accepts either a fully-formed %RpcError{} or any other term, which is wrapped under code: :middleware_halted with the original term stored at details.reason. After halting, downstream middleware and the handler are skipped.

put_ctx(res, key, value)

@spec put_ctx(t(), atom(), term()) :: t()

Replaces a known field on the nested %Context{} struct.

Raises KeyError if key is not a field on the context struct. To store arbitrary request-scoped data, use assign/3 (application data) or put_private/3 (framework/library data) instead.

put_private(res, key, value)

@spec put_private(t(), atom(), term()) :: t()

Stores framework/library-private request-scoped data under key in the resolution's :private map. For application data, use assign/3 instead.

put_resp_cookie(res, name, value, opts \\ [])

@spec put_resp_cookie(t(), String.t(), String.t(), keyword()) :: t()

Stores a cookie to be set on the response.

opts are forwarded directly to Plug.Conn.put_resp_cookie/4 by the transport adapter. Supported options include :http_only, :secure, :same_site, :max_age, :path, :domain, :sign, :encrypt.

put_resp_header(res, name, value)

@spec put_resp_header(t(), String.t(), String.t()) :: t()

Appends a response header. Duplicates are preserved (useful for headers like set-cookie that must be set separately per cookie).

put_session(res, key, value)

@spec put_session(t(), term(), term()) :: t()

Stores a session key-value pair to be set on the response.

Requires Plug.Session to be configured in the Plug pipeline. The transport adapter drains this into the session after dispatch.