Build libraries that mount into a Phoenix app.
A mountable library brings its own routes, LiveViews, controllers, assets and processes, and a host app mounts it with one line in its router:
# in the host router
import MyLib.Router
scope "/" do
pipe_through :browser
my_lib "/my_lib", resolver: MyApp.MyLibResolver
endThe library declares everything in a definition module:
defmodule MyLib.Router do
use PhoenixMountable,
otp_app: :my_lib,
macro: :my_lib,
layout: {MyLib.Layouts, :root},
assets:
{PhoenixMountable.Assets.Embedded,
css: "priv/static/app.css",
js: "priv/static/app.js",
prepend: [:phoenix, :phoenix_html, :phoenix_live_view, :phoenix_mountable]}
options resolver: [type: :atom, default: MyLib.Resolver, verify: {:behaviour, MyLib.Resolver}],
features: [type: {:list, :atom}, default: []]
routes do
get "/export", MyLib.ExportController, :csv
live_session :public, host_on_mount: false do
live "/share/:token", MyLib.ShareLive, :show
end
live_session :default, on_mount: [MyLib.Auth] do
live "/", MyLib.HomeLive, :index
live "/items/:id", MyLib.ItemLive, :show
end
end
endThe generated macro (my_lib/2) inserts ordinary Phoenix routes and live
sessions into the host router: mix phx.routes lists them, the host's
pipelines and scopes apply to them, and LiveView navigation works between
them. LiveView is optional: a library of controllers and plugs mounts in a
host without it.
See PhoenixMountable.Definition for options/1, routes/1 and
pipeline/2, and PhoenixMountable.Routes for the routes.
use options
:otp_app(atom/0) - Required. The library's OTP application.:macro(atom/0) - Required. The name of the mount macro defined for hosts.:as(atom/0) - The default mount name, used to name live sessions and route helpers. Defaults to the macro name. Hosts pass:asto mount the library more than once.:title(String.t/0) - The page title ofPhoenixMountable.Layout. Defaults to the camelized OTP application.:layout- The root layout of the library's pages: a{module, function}tuple for a document of its own (such as{PhoenixMountable.Layout, :root}), or:hostto render inside the host's root layout. The default value is:host.:assets- How the library's CSS and JavaScript reach the browser:{strategy, options}. SeePhoenixMountable.Assets. The default value isnil.:on_mount-on_mounthooks of the library, run in every library live session after the host's. The default value is[].:schema(atom/0) - The library'sPhoenixMountable.Migrationsmodule. The first use of each mount then checks the host has run the library's migrations; seePhoenixMountable.repo/1.:reload_on_stale(boolean/0) - Reload a page whose library assets belong to a previous build when its LiveView reconnects. The default value istrue.:socket_path(String.t/0) - The default of the:socket_pathmount option. The default value is"/live".:transport- The default of the:transportmount option. The default value is:websocket.
Mount options
Besides the options a library declares, every mount macro takes:
:as(atom/0) - The mount name: names the live sessions and route helpers. Mount a library twice with different names.:on_mount- The host'son_mounthooks, run before the library's. The default value is[].:socket_path(String.t/0) - The path of the host's LiveView socket. Defaults to"/live".:transport- The LiveView transport,:websocket(default) or:longpoll.:csp_nonce_assign_key- The assign holding the request's CSP nonce, or a map of kinds to assigns, such as%{script: :script_nonce, style: :style_nonce}. The default value isnil.:asset_host- A scheme and host to load the library's assets from, such as a CDN. The default value isnil.:pubsub- The PubSub server ofPhoenixMountable.PubSub. Defaults to the endpoint's. The default value isnil.
The mount
Library code reads the current PhoenixMountable.Mount as @mount in
LiveViews and templates, conn.assigns.mount in controllers and plugs, or
with PhoenixMountable.Mount.current/0 in the process handling them.
Summary
Callbacks
Child specs of the processes of one mount.
Adjusts or cross-validates the library's options after their validation.
The Ecto repo holding the library's tables, for the :schema check.
Extra values for the LiveView session of a library live session.
Functions
The mounts a host router declares.
A :via name for a process of a mount, unique to the mount.
Callbacks
@callback children(PhoenixMountable.Mount.t()) :: [ Supervisor.child_spec() | {module(), term()} | module() ]
Child specs of the processes of one mount.
They start under a supervisor of their own the first time the mount is
used, or when the host starts PhoenixMountable.Supervisor. Each mount
gets its own subtree, so two mounts never share state. Name the children
with via/2.
Adjusts or cross-validates the library's options after their validation.
Receives the options with defaults (a keyword list) and returns them,
possibly changed. Raise ArgumentError for an invalid combination. Runs
when the host router compiles.
@callback repo(PhoenixMountable.Mount.t()) :: module() | nil
The Ecto repo holding the library's tables, for the :schema check.
@callback session(conn :: Plug.Conn.t(), PhoenixMountable.Mount.t(), session :: atom()) :: map()
Extra values for the LiveView session of a library live session.
Runs on the HTTP request that renders a library LiveView, with the host's conn, so it can resolve the current user from the host's assigns. Returns a map with string keys, merged into the session.
Functions
@spec mounts(module()) :: [PhoenixMountable.Mount.t()]
The mounts a host router declares.
@spec via(PhoenixMountable.Mount.t(), term()) :: {:via, Registry, {PhoenixMountable.Registry, term()}}
A :via name for a process of a mount, unique to the mount.
def children(mount) do
[{MyLib.Cache, name: PhoenixMountable.via(mount, :cache)}]
end