Cherrypicker (cherrypicker v0.1.0)

Copy Markdown View Source

Stable named .localhost URLs for local dev servers, on the BEAM.

A running daemon (cherrypicker start, or Cherrypicker.Daemon in a supervision tree) proxies http://<name>.localhost[:port] to registered loopback ports. This module is the client: it finds the daemon through its state file and speaks the control API using only the standard library, so depending on it costs a host application nothing at runtime.

The register model, deliberately: apps start themselves and say where they are — no child-process wrapping, no PORT-injection guesswork.

case Cherrypicker.register("mysite", 4000) do
  {:ok, url} -> IO.puts("also at " <> url)
  {:error, :no_daemon} -> :ok
end

Summary

Functions

The daemon's bound proxy port, when one is answering.

Registers name to proxy to 127.0.0.1:port, returning the named URL. {:error, :no_daemon} when no daemon is reachable — callers treat that as "fall back to the port URL", never as a failure.

Every registered route.

Removes a route; absent routes and absent daemons are fine.

Types

error()

@type error() :: :no_daemon | String.t()

name()

@type name() :: String.t()

Functions

daemon_port()

@spec daemon_port() :: {:ok, :inet.port_number()} | :error

The daemon's bound proxy port, when one is answering.

register(name, port)

@spec register(name(), :inet.port_number()) :: {:ok, String.t()} | {:error, error()}

Registers name to proxy to 127.0.0.1:port, returning the named URL. {:error, :no_daemon} when no daemon is reachable — callers treat that as "fall back to the port URL", never as a failure.

routes()

@spec routes() ::
  {:ok, [%{name: name(), port: :inet.port_number()}]} | {:error, error()}

Every registered route.

unregister(name)

@spec unregister(name()) :: :ok

Removes a route; absent routes and absent daemons are fine.