Current section
Files
Jump to
Current section
Files
lib/mflask.ex
defmodule Mflask do
# Publicly expose the library version at compile time (read from mix.exs).
# This provides a stable, compile-time value accessible as `Mflask.mflask_version/0`
# or `Mflask.version/0`.
@mflask_version Mix.Project.config()[:version]
@moduledoc """
Mflask — a Flask-style web framework for Elixir.
## Minimal app
defmodule MyApp do
use Mflask
get "/" do
text(conn, "Hello!")
end
end
Mflask.run(MyApp, port: 4000)
## Composed app (no blueprints needed)
defmodule MyApp do
use Mflask
plug Mflask.Middleware.Logger
plug Mflask.Middleware.BodyParser
mount "/api", MyApp.API
mount "/admin", MyApp.Admin
mount "/", MyApp.Web
end
Sub-routers use `use Mflask.Router` and are completely self-contained.
No app context, no circular imports, no registration.
defmodule MyApp.API do
use Mflask.Router
plug MyApp.RequireAuth
get "/users" do
json(conn, Users.list())
end
end
## Response helpers
Available in all route blocks:
| Helper | Description |
|--------|-------------|
| `text(conn, body, status \\\\ 200)` | Plain text |
| `json(conn, data, status \\\\ 200)` | JSON (any Jason-encodable term) |
| `html(conn, body, status \\\\ 200)` | HTML string |
| `redirect(conn, to, status \\\\ 302)` | Redirect |
| `send_file(conn, path)` | Send a file |
| `render(conn, template, assigns)` | EEx template |
| `halt(conn)` | Stop plug pipeline |
## Request helpers
| Helper | Description |
|--------|-------------|
| `params["key"]` | Path or query param |
| `body_param(conn, "key")` | Body param (POST/JSON) |
| `query_param(conn, "key")` | Query string param |
| `get_header(conn, "x-foo")` | Request header |
| `remote_ip(conn)` | Client IP string |
| `get_cookie(conn, "name")` | Cookie value |
"""
defmacro __using__(_opts) do
quote do
import Mflask.Router, except: [plug: 1, plug: 2]
import Mflask.Response
import Mflask.Request
import Mflask.Template
Module.register_attribute(__MODULE__, :mflask_routes, accumulate: true)
Module.register_attribute(__MODULE__, :mflask_plugs, accumulate: true)
@before_compile Mflask.Router
end
end
@doc """
Start the Mflask HTTP server (blocking — runs under a supervisor).
## Options
- `:port` — port number (default: `4000`)
- `:ip` — bind address (default: `{0, 0, 0, 0}`)
## Example
Mflask.run(MyApp, port: 4000)
For production or umbrella apps, add it to your supervision tree instead:
children = [
{Bandit, plug: MyApp, port: 4000}
]
"""
def run(app_module, opts \\ []) do
port = Keyword.get(opts, :port, 4000)
ip = Keyword.get(opts, :ip, {0, 0, 0, 0})
children = [{Bandit, plug: app_module, port: port, ip: ip}]
IO.puts("""
\e[33m🔥 Mflask #{@mflask_version}\e[0m
\e[32m→\e[0m http://localhost:#{port}
Press Ctrl+C to stop.
""")
{:ok, _} = Supervisor.start_link(children, strategy: :one_for_one)
Process.sleep(:infinity)
end
@doc "Return the Mflask version (as defined in mix.exs) at compile time."
@spec mflask_version() :: String.t() | nil
def mflask_version, do: @mflask_version
@doc "Alias for `mflask_version/0`."
@spec version() :: String.t() | nil
def version, do: @mflask_version
end