From b35d8687a04c32eaf809fe3024c8ed0fd32eb5a7 Mon Sep 17 00:00:00 2001 From: Daniel Flanagan Date: Tue, 20 Feb 2024 20:37:55 -0600 Subject: [PATCH] Initial commit --- .envrc | 1 + .gitignore | 22 +++++++++++++ flake.lock | 27 ++++++++++++++++ flake.nix | 60 +++++++++++++++++++++++++++++++++++ main.ex | 92 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ readme.md | 27 ++++++++++++++++ 6 files changed, 229 insertions(+) create mode 100644 .envrc create mode 100644 .gitignore create mode 100644 flake.lock create mode 100644 flake.nix create mode 100644 main.ex create mode 100644 readme.md diff --git a/.envrc b/.envrc new file mode 100644 index 0000000..3550a30 --- /dev/null +++ b/.envrc @@ -0,0 +1 @@ +use flake diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..8cf7b60 --- /dev/null +++ b/.gitignore @@ -0,0 +1,22 @@ +# secret files +*.secret.* + +# build output +/_build + +# elixir dependencies +/deps + +# crash dumps +erl_crash.dump + +# sqlite databases +*.db +*.db-shm +*.db-wal + +# nix build output +/result + +# direnv cache +/.direnv diff --git a/flake.lock b/flake.lock new file mode 100644 index 0000000..cc4d1cb --- /dev/null +++ b/flake.lock @@ -0,0 +1,27 @@ +{ + "nodes": { + "nixpkgs": { + "locked": { + "lastModified": 1708407374, + "narHash": "sha256-EECzarm+uqnNDCwaGg/ppXCO11qibZ1iigORShkkDf0=", + "owner": "nixos", + "repo": "nixpkgs", + "rev": "f33dd27a47ebdf11dc8a5eb05e7c8fbdaf89e73f", + "type": "github" + }, + "original": { + "owner": "nixos", + "ref": "nixpkgs-unstable", + "repo": "nixpkgs", + "type": "github" + } + }, + "root": { + "inputs": { + "nixpkgs": "nixpkgs" + } + } + }, + "root": "root", + "version": 7 +} diff --git a/flake.nix b/flake.nix new file mode 100644 index 0000000..157b690 --- /dev/null +++ b/flake.nix @@ -0,0 +1,60 @@ +{ + inputs = { + nixpkgs.url = "github:nixos/nixpkgs/nixpkgs-unstable"; + }; + + outputs = { + self, + nixpkgs, + ... + }: let + inherit (self) outputs; + + systems = [ + "aarch64-linux" + "aarch64-darwin" + "x86_64-darwin" + "x86_64-linux" + ]; + + forAllSystems = nixpkgs.lib.genAttrs systems; + + nixpkgsFor = system: import nixpkgs {inherit system;}; + in { + packages = forAllSystems (system: let + pkgs = nixpkgsFor system; + + inherit (pkgs) beamPackages; + inherit (beamPackages) mixRelease fetchMixDeps; + + version = "0.1.0"; + src = ./.; + pname = "api.lyte.dev"; + in { + # this-package = mixRelease { + # inherit pname version src; + # mixFodDeps = fetchMixDeps { + # inherit version src; + # pname = "mix-deps-${pname}"; + # hash = pkgs.lib.fakeSha256; + # }; + # buildInputs = with pkgs; [sqlite]; + # HOME = "$(pwd)"; + # MIX_XDG = "$HOME"; + # }; + + # default = outputs.packages.${system}.this-package; + }); + + devShells = forAllSystems (system: let + pkgs = nixpkgsFor system; + erlang = pkgs.beam.packages.erlang_26; + elixir = erlang.elixir_1_16; + in { + default = pkgs.mkShell { + shellHook = "export LOCALE_ARCHIVE=/usr/lib/locale/locale-archive"; + buildInputs = with pkgs; [erlang_26 elixir elixir-ls watchexec]; + }; + }); + }; +} diff --git a/main.ex b/main.ex new file mode 100644 index 0000000..fe7be33 --- /dev/null +++ b/main.ex @@ -0,0 +1,92 @@ +Application.put_env(:sample, Sfe.Endpoint, + http: [ip: {127, 0, 0, 1}, port: 5001], + adapter: Bandit.PhoenixAdapter, + server: true, + live_view: [signing_salt: "aaaaaaaa"], + secret_key_base: String.duplicate("a", 64) +) + +Mix.install([ + {:bandit, "~> 1.2"}, + {:jason, "~> 1.0"}, + {:phoenix, "~> 1.7.0"}, + {:phoenix_live_view, "~> 0.19.0"}, + {:phoenix_pubsub, "~> 2.1"} +]) + +defmodule Sfe.ErrorView do + def render(template, _), do: Phoenix.Controller.status_message_from_template(template) +end + +defmodule Sfe.HomeLive do + use Phoenix.LiveView, layout: {__MODULE__, :live} + + def mount(_params, _session, socket) do + {:ok, assign(socket, :count, 0)} + end + + defp phx_vsn, do: Application.spec(:phoenix, :vsn) + defp lv_vsn, do: Application.spec(:phoenix_live_view, :vsn) + + def render("live.html", assigns) do + ~H""" + + + + + <%= @inner_content %> + """ + end + + def render(assigns) do + ~H""" + Multiplayer Counter + <%= @count %> + + + """ + end + + def handle_event("inc", _params, socket) do + {:noreply, assign(socket, :count, socket.assigns.count + 1)} + end + + def handle_event("dec", _params, socket) do + {:noreply, assign(socket, :count, socket.assigns.count - 1)} + end +end + +defmodule Sfe.Router do + use Phoenix.Router + import Phoenix.LiveView.Router + + pipeline :browser do + plug(:accepts, ["html"]) + end + + scope "/", Sfe do + pipe_through(:browser) + + live("/", HomeLive, :index) + end +end + +defmodule Sfe.Endpoint do + use Phoenix.Endpoint, otp_app: :sample + socket("/live", Phoenix.LiveView.Socket) + plug(Sfe.Router) +end + +children = [ + Sfe.Endpoint, + {Phoenix.PubSub, name: :my_pubsub} +] + +{:ok, _} = Supervisor.start_link(children, strategy: :one_for_one) + +Process.sleep(:infinity) diff --git a/readme.md b/readme.md new file mode 100644 index 0000000..61a2916 --- /dev/null +++ b/readme.md @@ -0,0 +1,27 @@ +# Single-File Elixir (`sfe`) + +I love Elixir, but for some reason I can't stand it's default project structure +and willingness to spread a hundred things across a hundred files. + +I was inspired by this: + +https://github.com/wojtekmach/mix_install_examples/blob/main/phoenix_live_view.exs + +So I've put this together in a Nix Flake to serve as a decent launch point for +quick-and-dirty Elixir applications. + +Here ya go! + +```bash +elixir main.ex +``` + +Or if you want "hot reloading" + +```bash +watchexec --filter main.ex --restart 'elixir main.ex' +``` + +# To Do + +- Look into `:counters` to implement pubsub stuff