Packages
maru
0.11.4
0.14.0-pre.1
0.13.2
0.13.1
0.13.0
0.12.5
0.12.4
0.12.3
0.12.2
0.12.1
0.12.0
0.11.5
0.11.4
0.11.3
0.11.2
0.11.1
0.11.0
0.10.6
0.10.5
0.10.4
0.10.3
0.10.2
0.10.1
0.10.0
0.9.6
0.9.5
0.9.4
0.9.3
0.9.2
0.9.1
0.9.0
0.8.5
0.8.4
0.8.3
0.8.2
0.8.1
0.8.0
0.7.2
0.7.1
0.7.0
0.6.0
0.5.1
0.5.0
0.4.1
0.4.0
0.3.1
0.3.0
0.2.10
0.2.9
0.2.8
0.2.7
0.2.6
0.2.5
REST-like API micro-framework for elixir inspired by grape.
Current section
Files
Jump to
Current section
Files
lib/maru/builder/dsls.ex
defmodule Maru.Builder.DSLs do
@moduledoc """
General DSLs for parsing router.
"""
alias Maru.Struct.Resource
alias Maru.Struct.Plug, as: MaruPlug
alias Maru.Builder.Path, as: MaruPath
@doc """
Define path prefix of current router.
"""
defmacro prefix(path) do
path = MaruPath.split path
quote do
Resource.push_path(unquote(path))
end
end
@doc """
Define params block of current endpoint.
"""
defmacro params([do: block]) do
quote do
import Maru.Builder.Namespaces, only: []
import Kernel, except: [use: 1]
import Maru.Builder.Params
@group []
unquote(block)
import Maru.Builder.Params, only: []
import Kernel
import Maru.Builder.Namespaces
end
end
@doc """
Save shared param to module attribute.
"""
defmacro params(name, [do: block]) do
quote do
@shared_params unquote({name, block |> Macro.escape})
end
end
@doc """
Define version of current router.
"""
defmacro version(v) do
quote do
Resource.set_version(unquote(v))
end
end
@doc """
version: "v1", do ... end:
Version of routes within block.
version: "v2", extend: "v1", at: V1
Define version and extended router of current router.
"""
defmacro version(v, [do: block]) do
quote do
s = Resource.snapshot
Resource.set_version(unquote(v))
unquote(block)
Resource.restore(s)
end
end
defmacro version(v, opts) do
quote do
Resource.set_version(unquote(v))
@extend {unquote(v), unquote(opts)}
end
end
defmacro helpers({_, _, module}) do
module = Module.concat(module)
quote do
unquote(module).__shared_params__ |> Enum.each(&(@shared_params &1))
import unquote(module)
end
end
defmacro helpers([do: block]) do
quote do
import Kernel, only: []
import Maru.Builder.DSLs, only: [params: 2]
unquote(block)
import Maru.Builder.DSLs
import Maru.Builder.DSLs, except: [params: 2]
import Kernel
end
end
@doc """
Define description for current endpoint.
"""
defmacro desc(desc) do
quote do
@desc %{summary: unquote(desc)}
end
end
@doc """
Define description with a block for current endpoint.
"""
defmacro desc(desc, [do: block]) do
quote do
@desc %{summary: unquote(desc)}
import Maru.Builder.Description
unquote(block)
import Maru.Builder.Description, only: []
end
end
@doc """
Mount another router to current router.
"""
defmacro mount({_, _, mod}) do
module = Module.concat(mod)
try do
true = {:__routes__, 0} in module.__info__(:functions)
rescue
[UndefinedFunctionError, MatchError] ->
raise """
#{inspect module} is not an available Maru.Router.
If you mount it to another module written at the same file,
make sure this module at the front of the file.
"""
end
quote do
if @test do
@mounted_modules unquote(module)
else
for route <- unquote(module).__routes__ do
@mounted Maru.Struct.Route.merge(
@resource, @plugs, __MODULE__, route
)
end
end
end
end
@doc """
Push a `Plug` struct to current scope.
"""
defmacro plug(plug)
defmacro plug({:when, _, [plug, guards]}) do
do_plug(nil, plug, [], guards)
end
defmacro plug(plug) do
do_plug(nil, plug, [], true)
end
@doc """
Push a `Plug` struct with options and guards to current scope.
"""
defmacro plug(plug, opts)
defmacro plug(plug, {:when, _, [opts, guards]}) do
do_plug(nil, plug, opts, guards)
end
defmacro plug(plug, opts) do
do_plug(nil, plug, opts, true)
end
@doc """
Push a overridable `Plug` struct to current scope.
"""
defmacro plug_overridable(name, plug)
defmacro plug_overridable(name, {:when, _, [plug, guards]}) do
do_plug(name, plug, [], guards)
end
defmacro plug_overridable(name, plug) do
do_plug(name, plug, [], true)
end
@doc """
Push a overridable `Plug` struct with options and guards to current scope.
"""
defmacro plug_overridable(name, plug, opts)
defmacro plug_overridable(name, plug, {:when, _, [opts, guards]}) do
do_plug(name, plug, opts, guards)
end
defmacro plug_overridable(name, plug, opts) do
do_plug(name, plug, opts, true)
end
defp do_plug(name, plug, opts, guards) do
quote do
Resource.push_plug(%MaruPlug{
name: unquote(name),
plug: unquote(plug),
options: unquote(opts),
guards: unquote(Macro.escape(guards)),
})
end
end
@doc """
Define pipeline block of current endpoint.
"""
defmacro pipeline(block) do
quote do
import Kernel, only: []
import Maru.Builder.DSLs, only: []
import Maru.Builder.Pipeline, only: [
plug: 1, plug: 2, plug_overridable: 2, plug_overridable: 3
]
unquote(block)
import Maru.Builder.Pipeline, only: []
import Maru.Builder.DSLs
import Kernel
end
end
@doc """
Define plugs which execute before routes match.
"""
defmacro before([do: block]) do
quote do
if @make_plug do
import Maru.Builder.DSLs, except: [
plug: 1, plug: 2, plug_overridable: 2, plug_overridable: 3
]
import Maru.Builder.Before
unquote(block)
import Maru.Builder.Before, only: []
import Maru.Builder.DSLs
else
Maru.Utils.warn "#{inspect __MODULE__}: `before` only works for plug router, Ignore.\n"
end
end
end
end