starting files

This commit is contained in:
2026-03-05 12:58:23 -07:00
commit 76c164d931
38 changed files with 1239 additions and 0 deletions

9
lib/elixir_ai.ex Normal file
View File

@@ -0,0 +1,9 @@
defmodule ElixirAi do
@moduledoc """
ElixirAi keeps the contexts that define your domain
and business logic.
Contexts are also responsible for managing your data, regardless
if it comes from the database, an external API or others.
"""
end

View File

@@ -0,0 +1,23 @@
defmodule ElixirAi.Application do
@moduledoc false
use Application
@impl true
def start(_type, _args) do
children = [
ElixirAiWeb.Telemetry,
{DNSCluster, query: Application.get_env(:elixir_ai, :dns_cluster_query) || :ignore},
{Phoenix.PubSub, name: ElixirAi.PubSub},
ElixirAiWeb.Endpoint
]
opts = [strategy: :one_for_one, name: ElixirAi.Supervisor]
Supervisor.start_link(children, opts)
end
@impl true
def config_change(changed, _new, removed) do
ElixirAiWeb.Endpoint.config_change(changed, removed)
:ok
end
end

109
lib/elixir_ai_web.ex Normal file
View File

@@ -0,0 +1,109 @@
defmodule ElixirAiWeb do
@moduledoc """
The entrypoint for defining your web interface, such
as controllers, components, channels, and so on.
This can be used in your application as:
use ElixirAiWeb, :controller
use ElixirAiWeb, :html
The definitions below will be executed for every controller,
component, etc, so keep them short and clean, focused
on imports, uses and aliases.
Do NOT define functions inside the quoted expressions
below. Instead, define additional modules and import
those modules here.
"""
def static_paths, do: ~w(assets fonts images favicon.ico robots.txt)
def router do
quote do
use Phoenix.Router, helpers: false
# Import common connection and controller functions to use in pipelines
import Plug.Conn
import Phoenix.Controller
import Phoenix.LiveView.Router
end
end
def channel do
quote do
use Phoenix.Channel
end
end
def controller do
quote do
use Phoenix.Controller,
formats: [:html, :json],
layouts: [html: ElixirAiWeb.Layouts]
import Plug.Conn
unquote(verified_routes())
end
end
def live_view do
quote do
use Phoenix.LiveView,
layout: {ElixirAiWeb.Layouts, :app}
unquote(html_helpers())
end
end
def live_component do
quote do
use Phoenix.LiveComponent
unquote(html_helpers())
end
end
def html do
quote do
use Phoenix.Component
# Import convenience functions from controllers
import Phoenix.Controller,
only: [get_csrf_token: 0, view_module: 1, view_template: 1]
# Include general helpers for rendering HTML
unquote(html_helpers())
end
end
defp html_helpers do
quote do
# HTML escaping functionality
import Phoenix.HTML
# Shortcut for generating JS commands
alias Phoenix.LiveView.JS
# Routes generation with the ~p sigil
unquote(verified_routes())
end
end
def verified_routes do
quote do
use Phoenix.VerifiedRoutes,
endpoint: ElixirAiWeb.Endpoint,
router: ElixirAiWeb.Router,
statics: ElixirAiWeb.static_paths()
end
end
@doc """
When used, dispatch to the appropriate controller/live_view/etc.
"""
defmacro __using__(which) when is_atom(which) do
apply(__MODULE__, which, [])
end
end

View File

@@ -0,0 +1,14 @@
defmodule ElixirAiWeb.Layouts do
@moduledoc """
This module holds different layouts used by your application.
See the `layouts` directory for all templates available.
The "root" layout is a skeleton rendered as part of the
application router. The "app" layout is set as the default
layout on both `use ElixirAiWeb, :controller` and
`use ElixirAiWeb, :live_view`.
"""
use ElixirAiWeb, :html
embed_templates "layouts/*"
end

View File

@@ -0,0 +1,17 @@
<!DOCTYPE html>
<html lang="en" class="[scrollbar-gutter:stable]">
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<meta name="csrf-token" content={get_csrf_token()} />
<.live_title default="ElixirAi" suffix=" · Phoenix Framework">
{assigns[:page_title]}
</.live_title>
<link phx-track-static rel="stylesheet" href={~p"/assets/app.css"} />
<script defer phx-track-static type="text/javascript" src={~p"/assets/app.js"}>
</script>
</head>
<body class="bg-cyan-900 text-cyan-50">
{@inner_content}
</body>
</html>

View File

@@ -0,0 +1,24 @@
defmodule ElixirAiWeb.ErrorHTML do
@moduledoc """
This module is invoked by your endpoint in case of errors on HTML requests.
See config/config.exs.
"""
use ElixirAiWeb, :html
# If you want to customize your error pages,
# uncomment the embed_templates/1 call below
# and add pages to the error directory:
#
# * lib/elixir_ai_web/controllers/error_html/404.html.heex
# * lib/elixir_ai_web/controllers/error_html/500.html.heex
#
# embed_templates "error_html/*"
# The default is to render a plain text page based on
# the template name. For example, "404.html" becomes
# "Not Found".
def render(template, _assigns) do
Phoenix.Controller.status_message_from_template(template)
end
end

View File

@@ -0,0 +1,21 @@
defmodule ElixirAiWeb.ErrorJSON do
@moduledoc """
This module is invoked by your endpoint in case of errors on JSON requests.
See config/config.exs.
"""
# If you want to customize a particular status code,
# you may add your own clauses, such as:
#
# def render("500.json", _assigns) do
# %{errors: %{detail: "Internal Server Error"}}
# end
# By default, Phoenix returns the status message from
# the template name. For example, "404.json" becomes
# "Not Found".
def render(template, _assigns) do
%{errors: %{detail: Phoenix.Controller.status_message_from_template(template)}}
end
end

View File

@@ -0,0 +1,9 @@
defmodule ElixirAiWeb.PageController do
use ElixirAiWeb, :controller
def home(conn, _params) do
# The home page is often custom made,
# so skip the default app layout.
render(conn, :home, layout: false)
end
end

View File

@@ -0,0 +1,10 @@
defmodule ElixirAiWeb.PageHTML do
@moduledoc """
This module contains pages rendered by PageController.
See the `page_html` directory for all templates available.
"""
use ElixirAiWeb, :html
embed_templates "page_html/*"
end

View File

@@ -0,0 +1,3 @@
<div class="">
home
</div>

View File

@@ -0,0 +1,52 @@
defmodule ElixirAiWeb.Endpoint do
use Phoenix.Endpoint, otp_app: :elixir_ai
# The session will be stored in the cookie and signed,
# this means its contents can be read but not tampered with.
# Set :encryption_salt if you would also like to encrypt it.
@session_options [
store: :cookie,
key: "_elixir_ai_key",
signing_salt: "EFrzWK63",
same_site: "Lax"
]
socket "/live", Phoenix.LiveView.Socket,
websocket: [connect_info: [session: @session_options]],
longpoll: [connect_info: [session: @session_options]]
# Serve at "/" the static files from "priv/static" directory.
#
# You should set gzip to true if you are running phx.digest
# when deploying your static files in production.
plug Plug.Static,
at: "/",
from: :elixir_ai,
gzip: false,
only: ElixirAiWeb.static_paths()
# Code reloading can be explicitly enabled under the
# :code_reloader configuration of your endpoint.
if code_reloading? do
socket "/phoenix/live_reload/socket", Phoenix.LiveReloader.Socket
plug Phoenix.LiveReloader
plug Phoenix.CodeReloader
end
plug Phoenix.LiveDashboard.RequestLogger,
param_key: "request_logger",
cookie_key: "request_logger"
plug Plug.RequestId
plug Plug.Telemetry, event_prefix: [:phoenix, :endpoint]
plug Plug.Parsers,
parsers: [:urlencoded, :multipart, :json],
pass: ["*/*"],
json_decoder: Phoenix.json_library()
plug Plug.MethodOverride
plug Plug.Head
plug Plug.Session, @session_options
plug ElixirAiWeb.Router
end

View File

@@ -0,0 +1,42 @@
defmodule ElixirAiWeb.Router do
use ElixirAiWeb, :router
pipeline :browser do
plug :accepts, ["html"]
plug :fetch_session
plug :fetch_live_flash
plug :put_root_layout, html: {ElixirAiWeb.Layouts, :root}
plug :protect_from_forgery
plug :put_secure_browser_headers
end
pipeline :api do
plug :accepts, ["json"]
end
scope "/", ElixirAiWeb do
pipe_through :browser
get "/", PageController, :home
end
# Other scopes may use custom stacks.
# scope "/api", ElixirAiWeb do
# pipe_through :api
# end
if Application.compile_env(:elixir_ai, :dev_routes) do
# If you want to use the LiveDashboard in production, you should put
# it behind authentication and allow only admins to access it.
# If your application does not have an admins-only section yet,
# you can use Plug.BasicAuth to set up some basic authentication
# as long as you are also using SSL (which you should anyway).
import Phoenix.LiveDashboard.Router
scope "/dev" do
pipe_through :browser
live_dashboard "/dashboard", metrics: ElixirAiWeb.Telemetry
end
end
end

View File

@@ -0,0 +1,69 @@
defmodule ElixirAiWeb.Telemetry do
use Supervisor
import Telemetry.Metrics
def start_link(arg) do
Supervisor.start_link(__MODULE__, arg, name: __MODULE__)
end
@impl true
def init(_arg) do
children = [
# Telemetry poller will execute the given period measurements
# every 10_000ms. Learn more here: https://hexdocs.pm/telemetry_metrics
{:telemetry_poller, measurements: periodic_measurements(), period: 10_000}
# Add reporters as children of your supervision tree.
# {Telemetry.Metrics.ConsoleReporter, metrics: metrics()}
]
Supervisor.init(children, strategy: :one_for_one)
end
def metrics do
[
# Phoenix Metrics
summary("phoenix.endpoint.start.system_time",
unit: {:native, :millisecond}
),
summary("phoenix.endpoint.stop.duration",
unit: {:native, :millisecond}
),
summary("phoenix.router_dispatch.start.system_time",
tags: [:route],
unit: {:native, :millisecond}
),
summary("phoenix.router_dispatch.exception.duration",
tags: [:route],
unit: {:native, :millisecond}
),
summary("phoenix.router_dispatch.stop.duration",
tags: [:route],
unit: {:native, :millisecond}
),
summary("phoenix.socket_connected.duration",
unit: {:native, :millisecond}
),
summary("phoenix.channel_joined.duration",
unit: {:native, :millisecond}
),
summary("phoenix.channel_handled_in.duration",
tags: [:event],
unit: {:native, :millisecond}
),
# VM Metrics
summary("vm.memory.total", unit: {:byte, :kilobyte}),
summary("vm.total_run_queue_lengths.total"),
summary("vm.total_run_queue_lengths.cpu"),
summary("vm.total_run_queue_lengths.io")
]
end
defp periodic_measurements do
[
# A module, function and arguments to be invoked periodically.
# This function must call :telemetry.execute/3 and a metric must be added above.
# {ElixirAiWeb, :count_users, []}
]
end
end