Phoenix.Sync (Phoenix.Sync v0.3.0-pre-2)

View Source

Wrappers to ease integration of Electric’s Postgres syncing service with Phoenix applications.

There are currently 2 integration modes: Phoenix.LiveView streams and configuration gateway.

Phoenix.LiveView Streams

Phoenix.Sync.LiveView.sync_stream/4 integrates with Phoenix.LiveView.stream/4 and provides a live updating collection of items.

Configuration Gateway

Using Phoenix.Sync.Plug you can create endpoints that return configuration information for your Electric Typescript clients. See that module's documentation for more information.

Installation

Add phoenix_sync to your application dependencies:

def deps do
  [
    {:phoenix_sync, "~> 0.1"}
  ]
end

Configuration

In your config/config.exs or config/runtime.exs you must configure the client for the Electric streaming API:

import Config

config :phoenix_sync, Electric.Client,
  # one of `base_url` or `endpoint` is required
  base_url: System.get_env("ELECTRIC_URL", "http://localhost:3000"),
  # endpoint: System.get_env("ELECTRIC_ENDPOINT", "http://localhost:3000/v1/shape"),
  # optional
  database_id: System.get_env("ELECTRIC_DATABASE_ID", nil)

See the documentation for Electric.Client.new/1 for information on the client configuration.

Embedding Electric

TODO

Summary

Functions

Create a new Electric.Client instance based on the application config.

Types

param_override()

@type param_override() ::
  {:namespace, String.t()}
  | {:table, String.t()}
  | {:where, String.t()}
  | {:columns, String.t()}

param_overrides()

@type param_overrides() :: [param_override()]

shape_definition()

@type shape_definition() :: String.t() | Ecto.Queryable.t() | shape_definition()

shape_specification()

@type shape_specification() :: [
  table: binary(),
  query: atom() | struct(),
  namespace: binary(),
  where: binary(),
  columns: [binary()],
  replica: term(),
  storage: map() | nil
]

Functions

client!()

Create a new Electric.Client instance based on the application config.

To connect your live streams to an externally hosted Electric instance over HTTP, configure your app with the URL of the Electric server:

# dev.exs config :phoenix_sync, Electric.Client,

base_url: "http://localhost:3000"

If Electric is installed as a dependency of your app, and you wish to connect your live streams to this internal application, then you don't need to configure anything -- client!/0 will return an Electric.Client instance configured to data directly from the running Electric application.

See Electric.Client.new/1 for the available options.

plug_opts()

See Phoenix.Sync.Application.plug_opts/0.

shape_from_params(conn_or_map, overrides \\ [])

@spec shape_from_params(
  Plug.Conn.t() | Plug.Conn.params(),
  overrides :: param_overrides()
) ::
  {:ok, Electric.Client.ShapeDefinition.t()} | {:error, String.t()}

Use request query parameters to create a Electric.Client.ShapeDefinition.

Useful when creating authorization endpoints that validate a user's access to a specific shape.

Parameters

Required

  • table - the Postgres table name

    Note: table is not required in the parameters if a :table override is set.

Optional

  • where - the Shape's where clause
  • columns - The columns to include in the shape.
  • namespace - The Postgres namespace (also called SCHEMA).

See Electric.Client.ShapeDefinition.new/2 for more details on the parameters.

Examples

# pass the Plug.Conn struct for a request
iex> Phoenix.Sync.shape_from_params(%Plug.Conn{params: %{"table" => "items", "where" => "visible = true" }})
{:ok, %Electric.Client.ShapeDefinition{table: "items", where: "visible = true"}}

# or a simple parameter map
iex> Phoenix.Sync.shape_from_params(%{"table" => "items", "columns" => "id,name,value" })
{:ok, %Electric.Client.ShapeDefinition{table: "items", columns: ["id", "name", "value"]}}

iex> Phoenix.Sync.shape_from_params(%{"columns" => "id,name,value" })
{:error, "Missing `table` parameter"}

Overriding Parameter Values

If you want to hard-code some elements of the shape, ignoring the values from the request, or to set defaults, then use the overrides to set specific values for elements of the shape.

Examples

iex> Phoenix.Sync.shape_from_params(%{"columns" => "id,name,value"}, table: "things")
{:ok, %Electric.Client.ShapeDefinition{table: "things", columns: ["id", "name", "value"]}}

iex> Phoenix.Sync.shape_from_params(%{"table" => "ignored"}, table: "things")
{:ok, %Electric.Client.ShapeDefinition{table: "things"}}