Packages

phoenix_kit

1.7.8
1.7.208 1.7.207 1.7.206 1.7.205 1.7.204 1.7.203 1.7.202 1.7.201 1.7.200 1.7.199 1.7.198 1.7.197 1.7.196 1.7.194 1.7.193 1.7.192 1.7.191 1.7.190 1.7.189 1.7.187 1.7.186 1.7.185 1.7.184 1.7.183 1.7.182 1.7.181 1.7.180 1.7.179 1.7.178 1.7.177 1.7.176 1.7.175 1.7.174 1.7.173 1.7.172 1.7.171 1.7.170 1.7.169 1.7.168 1.7.167 1.7.166 1.7.165 1.7.164 1.7.162 1.7.161 1.7.160 1.7.159 1.7.157 1.7.156 1.7.155 1.7.154 1.7.153 1.7.152 1.7.151 1.7.150 1.7.149 1.7.146 1.7.145 1.7.144 1.7.143 1.7.138 1.7.133 1.7.132 1.7.131 1.7.130 1.7.128 1.7.126 1.7.125 1.7.121 1.7.120 1.7.119 1.7.118 1.7.117 1.7.116 1.7.115 1.7.114 1.7.113 1.7.112 1.7.111 1.7.110 1.7.109 1.7.108 1.7.107 1.7.106 1.7.105 1.7.104 1.7.103 1.7.102 1.7.101 1.7.100 1.7.99 1.7.98 1.7.97 1.7.96 1.7.95 1.7.94 1.7.93 1.7.92 1.7.91 1.7.90 1.7.89 1.7.88 1.7.87 1.7.86 1.7.85 1.7.84 1.7.83 1.7.82 1.7.81 1.7.80 1.7.79 1.7.78 1.7.77 1.7.76 1.7.75 1.7.74 1.7.71 1.7.70 1.7.69 1.7.66 1.7.65 1.7.64 1.7.63 1.7.62 1.7.61 1.7.59 1.7.58 1.7.57 1.7.56 1.7.55 1.7.54 1.7.53 1.7.52 1.7.51 1.7.49 1.7.44 1.7.43 1.7.42 1.7.41 1.7.39 1.7.38 1.7.37 1.7.36 1.7.34 1.7.33 1.7.31 1.7.30 1.7.29 1.7.28 1.7.27 1.7.26 1.7.25 1.7.24 1.7.23 1.7.22 1.7.21 1.7.20 1.7.19 1.7.18 1.7.17 1.7.16 1.7.15 1.7.14 1.7.13 1.7.12 1.7.11 1.7.10 1.7.9 1.7.8 1.7.7 1.7.6 1.7.5 1.7.4 1.7.3 1.7.2 1.7.1 1.7.0 1.6.20 1.6.19 1.6.18 1.6.17 1.6.16 1.6.15 1.6.14 1.6.13 1.6.12 1.6.11 1.6.10 1.6.9 1.6.8 1.6.7 1.6.6 1.6.5 1.6.4 1.6.3 1.5.2 1.5.1 1.5.0 1.4.9 1.4.8 1.4.7 1.4.6 1.4.5 1.4.4 1.4.3 1.4.2 1.4.1 1.4.0 1.3.2 1.3.1 1.3.0 1.2.10 1.2.9 1.2.8 1.2.7 1.2.5 1.2.4 1.2.2 1.2.1 1.2.0 1.1.0 1.0.0

A foundation for building Elixir Phoenix apps — SaaS, social networks, ERP systems, marketplaces, and more

Current section

Files

Jump to
phoenix_kit lib phoenix_kit install endpoint_integration.ex
Raw

lib/phoenix_kit/install/endpoint_integration.ex

defmodule PhoenixKit.Install.EndpointIntegration do
@moduledoc """
Handles endpoint integration for PhoenixKit installation.
This module adds PhoenixKit sockets (like DB Sync) to the parent app's endpoint.
"""
use PhoenixKit.Install.IgniterCompat
alias Igniter.Code.{Common, Function}
alias Igniter.Project.Application
alias Igniter.Project.Module, as: IgniterModule
alias PhoenixKit.Install.IgniterHelpers
@doc """
Adds PhoenixKit socket integration to the Phoenix endpoint.
## Parameters
- `igniter` - The igniter context
## Returns
Updated igniter with endpoint socket integration or warnings if endpoint not found.
"""
def add_endpoint_integration(igniter) do
case find_endpoint(igniter) do
{igniter, nil} ->
warning = create_endpoint_not_found_warning()
Igniter.add_warning(igniter, warning)
{igniter, endpoint_module} ->
add_phoenix_kit_socket_to_endpoint(igniter, endpoint_module)
end
end
# Find endpoint module
defp find_endpoint(igniter) do
# Check if this is the PhoenixKit library itself
case Application.app_name(igniter) do
:phoenix_kit ->
{igniter, nil}
_app_name ->
endpoint_module = IgniterHelpers.get_parent_app_module_web_endpoint(igniter)
case IgniterModule.module_exists(igniter, endpoint_module) do
{true, igniter} ->
{igniter, endpoint_module}
{false, igniter} ->
{igniter, nil}
end
end
end
# Add PhoenixKit socket to endpoint
defp add_phoenix_kit_socket_to_endpoint(igniter, endpoint_module) do
{_igniter, _source, zipper} = IgniterModule.find_module!(igniter, endpoint_module)
# Check if phoenix_kit_socket() already exists
case Function.move_to_function_call(zipper, :phoenix_kit_socket, 0) do
{:ok, _} ->
Igniter.add_notice(
igniter,
"PhoenixKit socket already exists in endpoint #{inspect(endpoint_module)}, skipping."
)
:error ->
# Check if the DBSyncSocket is already defined directly
case check_db_sync_socket_exists(zipper) do
true ->
Igniter.add_notice(
igniter,
"DB Sync socket already exists in endpoint #{inspect(endpoint_module)}, skipping."
)
false ->
# Add import and socket call
igniter
|> add_import_to_endpoint_module(endpoint_module)
|> add_socket_call_to_endpoint_module(endpoint_module)
end
end
end
# Check if DBSyncSocket is already defined in endpoint
defp check_db_sync_socket_exists(zipper) do
case Function.move_to_function_call(zipper, :socket, 2) do
{:ok, socket_zipper} ->
case Function.move_to_nth_argument(socket_zipper, 0) do
{:ok, arg_zipper} ->
node = Sourceror.Zipper.node(arg_zipper)
node == "/db-sync" or check_db_sync_socket_exists_next(socket_zipper)
:error ->
check_db_sync_socket_exists_next(socket_zipper)
end
:error ->
false
end
end
# Continue searching for DBSyncSocket in remaining socket calls
defp check_db_sync_socket_exists_next(zipper) do
case Sourceror.Zipper.next(zipper) do
nil -> false
next_zipper -> check_db_sync_socket_exists(next_zipper)
end
end
# Add import PhoenixKitWeb.Integration to endpoint
defp add_import_to_endpoint_module(igniter, endpoint_module) do
IgniterModule.find_and_update_module!(igniter, endpoint_module, fn zipper ->
if import_already_exists?(zipper) do
{:ok, zipper}
else
add_import_after_use_statement(zipper)
end
end)
end
# Check if PhoenixKitWeb.Integration import already exists
defp import_already_exists?(zipper) do
case Function.move_to_function_call(zipper, :import, 1, &check_import_argument/1) do
{:ok, _} -> true
:error -> false
end
end
# Check if import argument matches PhoenixKitWeb.Integration
defp check_import_argument(call_zipper) do
case Function.move_to_nth_argument(call_zipper, 0) do
{:ok, arg_zipper} -> Common.nodes_equal?(arg_zipper, PhoenixKitWeb.Integration)
:error -> false
end
end
# Add import statement after use statement
defp add_import_after_use_statement(zipper) do
case Function.move_to_function_call(zipper, :use, 2) do
{:ok, use_zipper} ->
import_code = "import PhoenixKitWeb.Integration"
{:ok, Common.add_code(use_zipper, import_code, placement: :after)}
:error ->
{:warning,
"Could not add import PhoenixKitWeb.Integration to endpoint. Please add manually."}
end
end
# Add phoenix_kit_socket() call after the /live socket
defp add_socket_call_to_endpoint_module(igniter, endpoint_module) do
IgniterModule.find_and_update_module!(igniter, endpoint_module, fn zipper ->
# Try to find the /live socket to add after it
case find_live_socket(zipper) do
{:ok, live_socket_zipper} ->
add_socket_code(live_socket_zipper)
:error ->
# Fallback: try import statement or use statement
add_socket_code_fallback(zipper)
end
end)
end
defp add_socket_code(target_zipper) do
socket_code = """
# PhoenixKit sockets (for DB Sync, etc.)
phoenix_kit_socket()
"""
{:ok, Common.add_code(target_zipper, socket_code, placement: :after)}
end
defp add_socket_code_fallback(zipper) do
# Try: add after the import statement we just added
case find_phoenix_kit_import(zipper) do
{:ok, import_zipper} ->
add_socket_code(import_zipper)
:error ->
# Last resort: add after use statement
add_socket_code_after_use(zipper)
end
end
defp add_socket_code_after_use(zipper) do
case Function.move_to_function_call(zipper, :use, 2) do
{:ok, use_zipper} ->
add_socket_code(use_zipper)
:error ->
{:warning, "Could not add phoenix_kit_socket() to endpoint. Please add manually."}
end
end
# Find the PhoenixKitWeb.Integration import statement
defp find_phoenix_kit_import(zipper) do
Function.move_to_function_call(zipper, :import, 1, &check_import_argument/1)
end
# Find the /live socket definition
defp find_live_socket(zipper) do
case Function.move_to_function_call(zipper, :socket, 2) do
{:ok, socket_zipper} ->
case Function.move_to_nth_argument(socket_zipper, 0) do
{:ok, arg_zipper} ->
node = Sourceror.Zipper.node(arg_zipper)
if node == "/live" do
{:ok, socket_zipper}
else
find_live_socket_next(socket_zipper)
end
:error ->
find_live_socket_next(socket_zipper)
end
:error ->
:error
end
end
# Continue searching for /live socket
defp find_live_socket_next(zipper) do
case Sourceror.Zipper.next(zipper) do
nil -> :error
next_zipper -> find_live_socket(next_zipper)
end
end
# Create warning when endpoint is not found
defp create_endpoint_not_found_warning do
"""
🚨 Endpoint Detection Failed
PhoenixKit could not automatically detect your Phoenix endpoint.
📋 MANUAL SETUP REQUIRED:
1. Open your endpoint file (usually lib/your_app_web/endpoint.ex)
2. Add the following lines:
defmodule YourAppWeb.Endpoint do
use Phoenix.Endpoint, otp_app: :your_app
# Add this import
import PhoenixKitWeb.Integration
# Add after your /live socket definition
phoenix_kit_socket()
# ... rest of your endpoint config
end
💡 The phoenix_kit_socket() macro adds:
- /db-sync socket for cross-site data sync
📖 Common endpoint locations:
• lib/my_app_web/endpoint.ex
• apps/my_app_web/lib/my_app_web/endpoint.ex (umbrella apps)
"""
end
end