Initial commit
This commit is contained in:
commit
03027baa11
14 changed files with 313 additions and 0 deletions
4
.formatter.exs
Normal file
4
.formatter.exs
Normal file
|
@ -0,0 +1,4 @@
|
||||||
|
# Used by "mix format"
|
||||||
|
[
|
||||||
|
inputs: ["{mix,.formatter}.exs", "{config,lib,test}/**/*.{ex,exs}"]
|
||||||
|
]
|
26
.gitignore
vendored
Normal file
26
.gitignore
vendored
Normal file
|
@ -0,0 +1,26 @@
|
||||||
|
# The directory Mix will write compiled artifacts to.
|
||||||
|
/_build/
|
||||||
|
|
||||||
|
# If you run "mix test --cover", coverage assets end up here.
|
||||||
|
/cover/
|
||||||
|
|
||||||
|
# The directory Mix downloads your dependencies sources to.
|
||||||
|
/deps/
|
||||||
|
|
||||||
|
# Where third-party dependencies like ExDoc output generated docs.
|
||||||
|
/doc/
|
||||||
|
|
||||||
|
# Ignore .fetch files in case you like to edit your project deps locally.
|
||||||
|
/.fetch
|
||||||
|
|
||||||
|
# If the VM crashes, it generates a dump, let's ignore it too.
|
||||||
|
erl_crash.dump
|
||||||
|
|
||||||
|
# Also ignore archive artifacts (built via "mix archive.build").
|
||||||
|
*.ez
|
||||||
|
|
||||||
|
# Ignore package tarball (built via "mix hex.build").
|
||||||
|
feeniks-*.tar
|
||||||
|
|
||||||
|
# Temporary files, for example, from tests.
|
||||||
|
/tmp/
|
2
.tool-versions
Normal file
2
.tool-versions
Normal file
|
@ -0,0 +1,2 @@
|
||||||
|
elixir 1.14.3-otp-25
|
||||||
|
erlang 25.1.1
|
21
README.md
Normal file
21
README.md
Normal file
|
@ -0,0 +1,21 @@
|
||||||
|
# Feeniks
|
||||||
|
|
||||||
|
**TODO: Add description**
|
||||||
|
|
||||||
|
## Installation
|
||||||
|
|
||||||
|
If [available in Hex](https://hex.pm/docs/publish), the package can be installed
|
||||||
|
by adding `feeniks` to your list of dependencies in `mix.exs`:
|
||||||
|
|
||||||
|
```elixir
|
||||||
|
def deps do
|
||||||
|
[
|
||||||
|
{:feeniks, "~> 0.1.0"}
|
||||||
|
]
|
||||||
|
end
|
||||||
|
```
|
||||||
|
|
||||||
|
Documentation can be generated with [ExDoc](https://github.com/elixir-lang/ex_doc)
|
||||||
|
and published on [HexDocs](https://hexdocs.pm). Once published, the docs can
|
||||||
|
be found at <https://hexdocs.pm/feeniks>.
|
||||||
|
|
22
config/config.exs
Normal file
22
config/config.exs
Normal file
|
@ -0,0 +1,22 @@
|
||||||
|
import Config
|
||||||
|
|
||||||
|
# Configures the endpoint
|
||||||
|
config :feeniks, Feeniks.Endpoint,
|
||||||
|
render_errors: [accepts: ~w(html json)],
|
||||||
|
pubsub_server: Feeniks.PubSub,
|
||||||
|
code_reloader: config_env() == :dev,
|
||||||
|
debug_errors: config_env() == :dev,
|
||||||
|
check_origin: config_env() == :prod
|
||||||
|
|
||||||
|
# Configures Elixir's Logger
|
||||||
|
config :logger, :console,
|
||||||
|
format: "$time $metadata[$level] $message\n",
|
||||||
|
metadata: [:request_id]
|
||||||
|
|
||||||
|
# Use Jason for JSON parsing in Phoenix
|
||||||
|
config :phoenix, :json_library, Jason
|
||||||
|
|
||||||
|
# Do not print debug messages in production
|
||||||
|
if config_env() == :prod do
|
||||||
|
config :logger, level: :error
|
||||||
|
end
|
19
lib/feeniks/application.ex
Normal file
19
lib/feeniks/application.ex
Normal file
|
@ -0,0 +1,19 @@
|
||||||
|
defmodule Feeniks.Application do
|
||||||
|
# See https://hexdocs.pm/elixir/Application.html
|
||||||
|
# for more information on OTP Applications
|
||||||
|
@moduledoc false
|
||||||
|
|
||||||
|
use Application
|
||||||
|
|
||||||
|
@impl true
|
||||||
|
def start(_type, _args) do
|
||||||
|
children = [
|
||||||
|
{Bandit, plug: Feeniks.Endpoint, scheme: :http, options: [port: 31545]}
|
||||||
|
]
|
||||||
|
|
||||||
|
# See https://hexdocs.pm/elixir/Supervisor.html
|
||||||
|
# for other strategies and supported options
|
||||||
|
opts = [strategy: :one_for_one, name: Feeniks.Supervisor]
|
||||||
|
Supervisor.start_link(children, opts)
|
||||||
|
end
|
||||||
|
end
|
5
lib/feeniks/controller.ex
Normal file
5
lib/feeniks/controller.ex
Normal file
|
@ -0,0 +1,5 @@
|
||||||
|
defmodule Feeniks.Controller do
|
||||||
|
def index(conn, params) do
|
||||||
|
Phoenix.Controller.text(conn, inspect(params))
|
||||||
|
end
|
||||||
|
end
|
58
lib/feeniks/endpoint.ex
Normal file
58
lib/feeniks/endpoint.ex
Normal file
|
@ -0,0 +1,58 @@
|
||||||
|
defmodule Feeniks.Endpoint do
|
||||||
|
import PlugHelpers
|
||||||
|
|
||||||
|
@behaviour Plug
|
||||||
|
|
||||||
|
@config Phoenix.Endpoint.Supervisor.config(:feeniks, __MODULE__)
|
||||||
|
@code_reloading @config[:code_reloader]
|
||||||
|
|
||||||
|
@session_options [
|
||||||
|
store: :cookie,
|
||||||
|
key: "_feeniks_key",
|
||||||
|
signing_salt: "örgölbörgöl"
|
||||||
|
]
|
||||||
|
|
||||||
|
@plugs pipeline([
|
||||||
|
&__MODULE__.set_endpoint/1,
|
||||||
|
module_plug(Plug.Static,
|
||||||
|
at: "/",
|
||||||
|
from: :feeniks,
|
||||||
|
gzip: true,
|
||||||
|
only: ~w(app.css favicon.ico robots.txt)
|
||||||
|
),
|
||||||
|
if @code_reloading do
|
||||||
|
[
|
||||||
|
module_plug(Phoenix.LiveReloader),
|
||||||
|
module_plug(Phoenix.CodeReloader)
|
||||||
|
]
|
||||||
|
end,
|
||||||
|
module_plug(Plug.RequestId),
|
||||||
|
module_plug(Plug.Logger),
|
||||||
|
module_plug(Plug.Parsers,
|
||||||
|
parsers: [:urlencoded, :multipart, :json],
|
||||||
|
pass: ["*/*"],
|
||||||
|
json_decoder: Jason
|
||||||
|
),
|
||||||
|
module_plug(Plug.MethodOverride),
|
||||||
|
module_plug(Plug.Head),
|
||||||
|
module_plug(
|
||||||
|
Plug.Session,
|
||||||
|
@session_options
|
||||||
|
),
|
||||||
|
module_plug(Feeniks.Router)
|
||||||
|
])
|
||||||
|
|
||||||
|
@impl Plug
|
||||||
|
def init(opts), do: opts
|
||||||
|
|
||||||
|
@impl Plug
|
||||||
|
def call(conn, _opts) do
|
||||||
|
run_plugs(conn, @plugs)
|
||||||
|
end
|
||||||
|
|
||||||
|
def config(key) do
|
||||||
|
@config[key]
|
||||||
|
end
|
||||||
|
|
||||||
|
def set_endpoint(conn), do: Plug.Conn.put_private(conn, :phoenix_endpoint, __MODULE__)
|
||||||
|
end
|
60
lib/feeniks/router.ex
Normal file
60
lib/feeniks/router.ex
Normal file
|
@ -0,0 +1,60 @@
|
||||||
|
defmodule Feeniks.Router do
|
||||||
|
import PlugHelpers
|
||||||
|
import RouterHelpers
|
||||||
|
|
||||||
|
@behaviour Plug
|
||||||
|
|
||||||
|
@common_browser pipeline([
|
||||||
|
&Plug.Conn.fetch_session/1,
|
||||||
|
&Phoenix.Controller.fetch_flash/1,
|
||||||
|
&__MODULE__.put_root_layout/1,
|
||||||
|
&Phoenix.Controller.put_secure_browser_headers/1,
|
||||||
|
&Phoenix.Controller.protect_from_forgery/1
|
||||||
|
])
|
||||||
|
|
||||||
|
@common_api pipeline([
|
||||||
|
&__MODULE__.accepts_json/1
|
||||||
|
])
|
||||||
|
|
||||||
|
@index @common_browser ++ [build_action(&Feeniks.Controller.index/1)]
|
||||||
|
|
||||||
|
@impl Plug
|
||||||
|
def init(opts), do: opts
|
||||||
|
|
||||||
|
@impl Plug
|
||||||
|
def call(conn, _opts) do
|
||||||
|
path_info = Plug.Router.Utils.decode_path_info!(conn)
|
||||||
|
match(conn, conn.method, path_info)
|
||||||
|
end
|
||||||
|
|
||||||
|
def put_root_layout(conn) do
|
||||||
|
Phoenix.Controller.put_root_layout(conn, {Feeniks.LayoutView, :root})
|
||||||
|
end
|
||||||
|
|
||||||
|
def accepts_json(conn) do
|
||||||
|
Phoenix.Controller.accepts(conn, ["json"])
|
||||||
|
end
|
||||||
|
|
||||||
|
@spec match(Plug.Conn.t(), Plug.Conn.method(), Plug.Conn.segments()) :: Plug.Conn.t()
|
||||||
|
defp match(conn, method, path_info)
|
||||||
|
|
||||||
|
defp match(conn, "GET", _) do
|
||||||
|
conn
|
||||||
|
|> common_browser()
|
||||||
|
|> Feeniks.Controller.index(conn.params)
|
||||||
|
end
|
||||||
|
|
||||||
|
defp match(conn, "POST", _) do
|
||||||
|
conn
|
||||||
|
|> run_plugs(@common_api)
|
||||||
|
|> Feeniks.Controller.index(conn.params)
|
||||||
|
end
|
||||||
|
|
||||||
|
defp match(conn, _, _) do
|
||||||
|
conn |> common_browser() |> Plug.Conn.put_status(200) |> Phoenix.Controller.text("Not found")
|
||||||
|
end
|
||||||
|
|
||||||
|
defp common_browser(conn) do
|
||||||
|
run_plugs(conn, @common_browser)
|
||||||
|
end
|
||||||
|
end
|
39
lib/plug_helpers.ex
Normal file
39
lib/plug_helpers.ex
Normal file
|
@ -0,0 +1,39 @@
|
||||||
|
defmodule PlugHelpers do
|
||||||
|
@typep plug_definition() :: {module(), term()}
|
||||||
|
@typep plug_function() :: (Plug.Conn.t() -> Plug.Conn.t())
|
||||||
|
|
||||||
|
@spec module_plug(module(), term()) :: plug_definition()
|
||||||
|
def module_plug(plug, opts \\ []) do
|
||||||
|
{plug, plug.init(opts)}
|
||||||
|
end
|
||||||
|
|
||||||
|
@spec pipeline(list()) :: [plug_definition() | plug_function()]
|
||||||
|
def pipeline(plugs) do
|
||||||
|
plugs
|
||||||
|
|> List.flatten()
|
||||||
|
|> Enum.filter(fn
|
||||||
|
{mod, _opts} when is_atom(mod) -> true
|
||||||
|
fun when is_function(fun, 1) -> true
|
||||||
|
_ -> false
|
||||||
|
end)
|
||||||
|
end
|
||||||
|
|
||||||
|
@spec run_plugs(Plug.Conn.t(), [plug_definition() | plug_function()]) ::
|
||||||
|
Plug.Conn.t()
|
||||||
|
def run_plugs(conn, plugs) do
|
||||||
|
for plug <- plugs, reduce: conn do
|
||||||
|
%Plug.Conn{halted: true} = c ->
|
||||||
|
c
|
||||||
|
|
||||||
|
%Plug.Conn{} = c ->
|
||||||
|
case plug do
|
||||||
|
p when is_function(p) -> p.(c)
|
||||||
|
{p, opts} -> p.call(c, opts)
|
||||||
|
what -> raise "Unknown plug type #{inspect(what)} in plug list"
|
||||||
|
end
|
||||||
|
|
||||||
|
other ->
|
||||||
|
"Expected plugs to return Plug.Conn, got: #{inspect(other)}"
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
7
lib/router_helpers.ex
Normal file
7
lib/router_helpers.ex
Normal file
|
@ -0,0 +1,7 @@
|
||||||
|
defmodule RouterHelpers do
|
||||||
|
@spec build_action((Plug.Conn.t(), Plug.Conn.params() -> Plug.Conn.t())) ::
|
||||||
|
(Plug.Conn.t() -> Plug.Conn.t())
|
||||||
|
def build_action(action) do
|
||||||
|
fn conn -> action.(conn, conn.params) end
|
||||||
|
end
|
||||||
|
end
|
31
mix.exs
Normal file
31
mix.exs
Normal file
|
@ -0,0 +1,31 @@
|
||||||
|
defmodule Feeniks.MixProject do
|
||||||
|
use Mix.Project
|
||||||
|
|
||||||
|
def project do
|
||||||
|
[
|
||||||
|
app: :feeniks,
|
||||||
|
version: "0.1.0",
|
||||||
|
elixir: "~> 1.14",
|
||||||
|
start_permanent: Mix.env() == :prod,
|
||||||
|
deps: deps()
|
||||||
|
]
|
||||||
|
end
|
||||||
|
|
||||||
|
# Run "mix help compile.app" to learn about applications.
|
||||||
|
def application do
|
||||||
|
[
|
||||||
|
extra_applications: [:logger],
|
||||||
|
mod: {Feeniks.Application, []}
|
||||||
|
]
|
||||||
|
end
|
||||||
|
|
||||||
|
# Run "mix help deps" to learn about dependencies.
|
||||||
|
defp deps do
|
||||||
|
[
|
||||||
|
{:phoenix, "~> 1.6.15"},
|
||||||
|
{:bandit, "~> 0.6.7"},
|
||||||
|
{:jason, "~> 1.4"},
|
||||||
|
{:phoenix_live_reload, "~> 1.4"}
|
||||||
|
]
|
||||||
|
end
|
||||||
|
end
|
18
mix.lock
Normal file
18
mix.lock
Normal file
|
@ -0,0 +1,18 @@
|
||||||
|
%{
|
||||||
|
"bandit": {:hex, :bandit, "0.6.7", "8d768a512ecbda9bd4e71fe223fce8d57c30899ede61dc70a0d4d34407910a8e", [:mix], [{:hpax, "~> 0.1.1", [hex: :hpax, repo: "hexpm", optional: false]}, {:plug, "~> 1.14", [hex: :plug, repo: "hexpm", optional: false]}, {:thousand_island, "~> 0.5.14", [hex: :thousand_island, repo: "hexpm", optional: false]}, {:websock, "~> 0.4.3", [hex: :websock, repo: "hexpm", optional: false]}], "hexpm", "0f1e9ac0e09714ee54c76001fe9d973aa25bff9cd058668c8f6cd0152f8ca3cf"},
|
||||||
|
"castore": {:hex, :castore, "1.0.0", "c25cd0794c054ebe6908a86820c8b92b5695814479ec95eeff35192720b71eec", [:mix], [], "hexpm", "577d0e855983a97ca1dfa33cbb8a3b6ece6767397ffb4861514343b078fc284b"},
|
||||||
|
"file_system": {:hex, :file_system, "0.2.10", "fb082005a9cd1711c05b5248710f8826b02d7d1784e7c3451f9c1231d4fc162d", [:mix], [], "hexpm", "41195edbfb562a593726eda3b3e8b103a309b733ad25f3d642ba49696bf715dc"},
|
||||||
|
"hpax": {:hex, :hpax, "0.1.2", "09a75600d9d8bbd064cdd741f21fc06fc1f4cf3d0fcc335e5aa19be1a7235c84", [:mix], [], "hexpm", "2c87843d5a23f5f16748ebe77969880e29809580efdaccd615cd3bed628a8c13"},
|
||||||
|
"jason": {:hex, :jason, "1.4.0", "e855647bc964a44e2f67df589ccf49105ae039d4179db7f6271dfd3843dc27e6", [:mix], [{:decimal, "~> 1.0 or ~> 2.0", [hex: :decimal, repo: "hexpm", optional: true]}], "hexpm", "79a3791085b2a0f743ca04cec0f7be26443738779d09302e01318f97bdb82121"},
|
||||||
|
"mime": {:hex, :mime, "2.0.3", "3676436d3d1f7b81b5a2d2bd8405f412c677558c81b1c92be58c00562bb59095", [:mix], [], "hexpm", "27a30bf0db44d25eecba73755acf4068cbfe26a4372f9eb3e4ea3a45956bff6b"},
|
||||||
|
"phoenix": {:hex, :phoenix, "1.6.15", "0a1d96bbc10747fd83525370d691953cdb6f3ccbac61aa01b4acb012474b047d", [:mix], [{:castore, ">= 0.0.0", [hex: :castore, repo: "hexpm", optional: false]}, {:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: true]}, {:phoenix_pubsub, "~> 2.0", [hex: :phoenix_pubsub, repo: "hexpm", optional: false]}, {:phoenix_view, "~> 1.0 or ~> 2.0", [hex: :phoenix_view, repo: "hexpm", optional: false]}, {:plug, "~> 1.10", [hex: :plug, repo: "hexpm", optional: false]}, {:plug_cowboy, "~> 2.2", [hex: :plug_cowboy, repo: "hexpm", optional: true]}, {:plug_crypto, "~> 1.2", [hex: :plug_crypto, repo: "hexpm", optional: false]}, {:telemetry, "~> 0.4 or ~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "d70ab9fbf6b394755ea88b644d34d79d8b146e490973151f248cacd122d20672"},
|
||||||
|
"phoenix_live_reload": {:hex, :phoenix_live_reload, "1.4.1", "2aff698f5e47369decde4357ba91fc9c37c6487a512b41732818f2204a8ef1d3", [:mix], [{:file_system, "~> 0.2.1 or ~> 0.3", [hex: :file_system, repo: "hexpm", optional: false]}, {:phoenix, "~> 1.4", [hex: :phoenix, repo: "hexpm", optional: false]}], "hexpm", "9bffb834e7ddf08467fe54ae58b5785507aaba6255568ae22b4d46e2bb3615ab"},
|
||||||
|
"phoenix_pubsub": {:hex, :phoenix_pubsub, "2.1.1", "ba04e489ef03763bf28a17eb2eaddc2c20c6d217e2150a61e3298b0f4c2012b5", [:mix], [], "hexpm", "81367c6d1eea5878ad726be80808eb5a787a23dee699f96e72b1109c57cdd8d9"},
|
||||||
|
"phoenix_template": {:hex, :phoenix_template, "1.0.0", "c57bc5044f25f007dc86ab21895688c098a9f846a8dda6bc40e2d0ddc146e38f", [:mix], [{:phoenix_html, "~> 2.14.2 or ~> 3.0", [hex: :phoenix_html, repo: "hexpm", optional: true]}], "hexpm", "1b066f99a26fd22064c12b2600a9a6e56700f591bf7b20b418054ea38b4d4357"},
|
||||||
|
"phoenix_view": {:hex, :phoenix_view, "2.0.2", "6bd4d2fd595ef80d33b439ede6a19326b78f0f1d8d62b9a318e3d9c1af351098", [:mix], [{:phoenix_html, "~> 2.14.2 or ~> 3.0", [hex: :phoenix_html, repo: "hexpm", optional: true]}, {:phoenix_template, "~> 1.0", [hex: :phoenix_template, repo: "hexpm", optional: false]}], "hexpm", "a929e7230ea5c7ee0e149ffcf44ce7cf7f4b6d2bfe1752dd7c084cdff152d36f"},
|
||||||
|
"plug": {:hex, :plug, "1.14.0", "ba4f558468f69cbd9f6b356d25443d0b796fbdc887e03fa89001384a9cac638f", [:mix], [{:mime, "~> 1.0 or ~> 2.0", [hex: :mime, repo: "hexpm", optional: false]}, {:plug_crypto, "~> 1.1.1 or ~> 1.2", [hex: :plug_crypto, repo: "hexpm", optional: false]}, {:telemetry, "~> 0.4.3 or ~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "bf020432c7d4feb7b3af16a0c2701455cbbbb95e5b6866132cb09eb0c29adc14"},
|
||||||
|
"plug_crypto": {:hex, :plug_crypto, "1.2.3", "8f77d13aeb32bfd9e654cb68f0af517b371fb34c56c9f2b58fe3df1235c1251a", [:mix], [], "hexpm", "b5672099c6ad5c202c45f5a403f21a3411247f164e4a8fab056e5cd8a290f4a2"},
|
||||||
|
"telemetry": {:hex, :telemetry, "1.2.1", "68fdfe8d8f05a8428483a97d7aab2f268aaff24b49e0f599faa091f1d4e7f61c", [:rebar3], [], "hexpm", "dad9ce9d8effc621708f99eac538ef1cbe05d6a874dd741de2e689c47feafed5"},
|
||||||
|
"thousand_island": {:hex, :thousand_island, "0.5.15", "3163c8b61c5e985a80e330d8544c4409e6039a1796587b812385051291b25361", [:mix], [{:telemetry, "~> 0.4 or ~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "e7347a922f7c8ae3f36737455c6539bba37e3e37c17cde20f9bac3fd0367a52f"},
|
||||||
|
"websock": {:hex, :websock, "0.4.3", "184ac396bdcd3dfceb5b74c17d221af659dd559a95b1b92041ecb51c9b728093", [:mix], [], "hexpm", "5e4dd85f305f43fd3d3e25d70bec4a45228dfed60f0f3b072d8eddff335539cf"},
|
||||||
|
}
|
1
priv/static/app.css
Normal file
1
priv/static/app.css
Normal file
|
@ -0,0 +1 @@
|
||||||
|
@charset "utf-8";
|
Loading…
Reference in a new issue