Packages
electric_client
0.9.4
0.10.3
0.10.2
0.10.1
0.10.1-beta-1
0.10.0
0.9.5-beta-1
0.9.4
0.9.4-beta-1
0.9.3
0.9.2
0.9.1
0.9.0
0.8.3
0.8.3-beta-1
0.8.2
0.8.1
0.8.0
0.8.0-beta-1
0.7.3
0.7.2
0.7.1
0.7.0
0.6.5
0.6.5-beta-5
0.6.5-beta-4
0.6.5-beta-3
0.6.5-beta-2
0.6.5-beta-1
0.6.4
0.6.3
0.6.2
0.6.1
0.6.0
0.5.0
0.5.0-beta-1
0.4.1
0.4.0
0.3.2
0.3.1
0.3.0
0.3.0-beta.4
0.3.0-beta.3
0.3.0-beta.2
0.2.6-pre-1
retired
0.2.6-beta.1
0.2.6-beta.0
0.2.5
0.2.4
0.2.4-pre-8
0.2.4-pre-7
0.2.4-pre-6
0.2.4-pre-5
0.2.4-pre-4
0.2.4-pre-3
0.2.4-pre-2
0.2.4-pre-1
0.2.3
0.2.3-rc-1
0.2.2
0.2.2-rc-1
0.2.1
0.2.1-rc-3
0.2.1-rc-2
0.2.1-rc-1
0.2.0
0.1.2
0.1.1
0.1.0
0.1.0-dev-9
0.1.0-dev-8
0.1.0-dev-7
0.1.0-dev-6
0.1.0-dev-5
0.1.0-dev-4
0.1.0-dev-3
0.1.0-dev-2
0.1.0-dev-17
0.1.0-dev-16
0.1.0-dev-15
0.1.0-dev-14
0.1.0-dev-13
0.1.0-dev-12
0.1.0-dev-11
0.1.0-dev-10
0.1.0-dev
Elixir client for ElectricSQL
Current section
Files
Jump to
Current section
Files
lib/electric/client/shape_key.ex
defmodule Electric.Client.ShapeKey do
@moduledoc """
Generate canonical shape keys for cache lookup.
The canonical shape key is a stable identifier for a shape definition that
excludes Electric protocol parameters (like cursor, handle, offset, etc.).
This allows the client to identify when different requests are for the same
underlying shape, which is useful for cache busting when CDN/proxy caches
serve stale responses.
"""
# Parameters that are part of the Electric protocol and should be excluded
# from the canonical shape key
@protocol_params ~w(
cursor
handle
live
offset
cache-buster
expired_handle
log
subset__where
subset__limit
subset__offset
subset__order_by
subset__params
subset__where_expr
subset__order_by_expr
)
@doc """
Generate a canonical shape key from a URI.
Extracts query parameters, filters out Electric protocol parameters,
sorts the remaining parameters alphabetically, and returns a canonical
URL string.
## Examples
iex> uri = URI.parse("http://localhost:3000/v1/shape?table=items&cursor=123&offset=0_0")
iex> ShapeKey.canonical(uri)
"http://localhost:3000/v1/shape?table=items"
"""
@spec canonical(URI.t()) :: String.t()
def canonical(%URI{} = uri) do
params = URI.decode_query(uri.query || "")
canonical(uri, params)
end
@doc """
Generate a canonical shape key from an endpoint URI and params map.
## Examples
iex> endpoint = URI.parse("http://localhost:3000/v1/shape")
iex> params = %{"table" => "items", "where" => "id > 0", "offset" => "0_0"}
iex> ShapeKey.canonical(endpoint, params)
"http://localhost:3000/v1/shape?table=items&where=id%20%3E%200"
"""
@spec canonical(URI.t(), map()) :: String.t()
def canonical(%URI{} = endpoint, params) when is_map(params) do
# Filter out protocol parameters
shape_params =
params
|> Enum.reject(fn {key, _value} -> key in @protocol_params end)
|> Enum.sort_by(fn {key, _value} -> key end)
# Build the canonical URL
query =
if shape_params == [] do
nil
else
URI.encode_query(shape_params, :rfc3986)
end
%{endpoint | query: query}
|> URI.to_string()
end
end