From 9b5badb255e3412493dad4ae4da9925c101f1099 Mon Sep 17 00:00:00 2001 From: Forest Carlisle <7829+forest@users.noreply.github.com> Date: Fri, 2 Jan 2026 15:08:29 -0800 Subject: [PATCH 1/2] Add config for Ecto.Repo prefix --- README.md | 8 ++++++++ lib/fyi.ex | 4 +++- lib/fyi/web/inbox_live.ex | 11 +++++++---- 3 files changed, 18 insertions(+), 5 deletions(-) diff --git a/README.md b/README.md index 8e1d90c..de413de 100644 --- a/README.md +++ b/README.md @@ -44,6 +44,7 @@ mix fyi.install ``` This will: + 1. Add `FYI.Application` to your supervision tree 2. Create a migration for the `fyi_events` table 3. Print instructions to add the `/fyi` route to your router @@ -63,6 +64,7 @@ config :fyi, app_name: "MyApp", persist_events: true, repo: MyApp.Repo, + prefix: "fyi", # optional sinks: [ {FYI.Sink.SlackWebhook, %{url: System.get_env("SLACK_WEBHOOK_URL")}}, {FYI.Sink.Telegram, %{ @@ -92,11 +94,13 @@ Messages will include the app name: `[MyApp] *purchase.created* by user_123` Add emojis to your notifications in three ways (in priority order): **1. Per-event override:** + ```elixir FYI.emit("error.critical", %{message: "DB down"}, emoji: "🚨") ``` **2. Pattern-based mapping:** + ```elixir config :fyi, emojis: %{ @@ -108,6 +112,7 @@ config :fyi, ``` **3. Default fallback:** + ```elixir config :fyi, emoji: "📣" ``` @@ -117,6 +122,7 @@ Messages will show as: `💰 [MyApp] *purchase.created* by user_123` ### Routing Routes use simple glob matching: + - `purchase.*` matches `purchase.created`, `purchase.updated`, etc. - `*` at the end matches any suffix @@ -135,6 +141,7 @@ FYI.emit("error.critical", %{message: "DB connection failed"}, emoji: "🚨", ta ``` Options: + - `:actor` - who triggered the event (user_id, email, etc.) - `:source` - where the event originated (e.g., "api", "web", "worker") - `:tags` - additional metadata map for filtering @@ -195,6 +202,7 @@ end ``` Visit `/fyi` to see the event inbox with: + - Activity histogram with time-based tooltips - Real-time event updates (requires PubSub config) - Time range filtering (5 minutes to all time) diff --git a/lib/fyi.ex b/lib/fyi.ex index 2265a71..0fb8539 100644 --- a/lib/fyi.ex +++ b/lib/fyi.ex @@ -25,6 +25,7 @@ defmodule FYI do config :fyi, persist_events: true, repo: MyApp.Repo, + prefix: "fyi", # optional sinks: [ {FYI.Sink.SlackWebhook, %{url: System.get_env("SLACK_WEBHOOK_URL")}}, {FYI.Sink.Telegram, %{ @@ -122,6 +123,7 @@ defmodule FYI do defp persist_event(event) do repo = Application.get_env(:fyi, :repo) + prefix = Application.get_env(:fyi, :prefix) if repo do attrs = %{ @@ -134,7 +136,7 @@ defmodule FYI do inserted_at: event.occurred_at } - case repo.insert(%FYI.Schema.Event{} |> struct(attrs)) do + case repo.insert(%FYI.Schema.Event{} |> struct(attrs), prefix: prefix) do {:ok, _} -> :ok {:error, changeset} -> {:error, changeset} end diff --git a/lib/fyi/web/inbox_live.ex b/lib/fyi/web/inbox_live.ex index a4dbd37..13bc0b3 100644 --- a/lib/fyi/web/inbox_live.ex +++ b/lib/fyi/web/inbox_live.ex @@ -802,6 +802,7 @@ if Code.ensure_loaded?(Phoenix.LiveView) do defp load_events(socket) do repo = Application.get_env(:fyi, :repo) + prefix = Application.get_env(:fyi, :prefix) if repo && Code.ensure_loaded?(Event) do import Ecto.Query @@ -833,7 +834,7 @@ if Code.ensure_loaded?(Phoenix.LiveView) do query end - events = repo.all(query) + events = repo.all(query, prefix: prefix) assign(socket, :events, events) else assign(socket, :events, []) @@ -842,6 +843,7 @@ if Code.ensure_loaded?(Phoenix.LiveView) do defp load_event_types(socket) do repo = Application.get_env(:fyi, :repo) + prefix = Application.get_env(:fyi, :prefix) if repo && Code.ensure_loaded?(Event) do import Ecto.Query @@ -852,11 +854,11 @@ if Code.ensure_loaded?(Phoenix.LiveView) do distinct: true, order_by: [asc: e.name] ) - |> repo.all() + |> repo.all(prefix: prefix) total_count = from(e in Event, select: count(e.id)) - |> repo.one() + |> repo.one(prefix: prefix) socket |> assign(:event_types, types) @@ -1016,9 +1018,10 @@ if Code.ensure_loaded?(Phoenix.LiveView) do defp load_event_detail(socket, id) do repo = Application.get_env(:fyi, :repo) + prefix = Application.get_env(:fyi, :prefix) if repo && Code.ensure_loaded?(Event) do - case repo.get(Event, id) do + case repo.get(Event, id, prefix: prefix) do nil -> assign(socket, :selected_event, nil) event -> assign(socket, :selected_event, event) end From 43fe2da2db8e5d66f85ba78b16dcc1aba1cffa57 Mon Sep 17 00:00:00 2001 From: Forest Carlisle <7829+forest@users.noreply.github.com> Date: Sat, 3 Jan 2026 12:24:30 -0800 Subject: [PATCH 2/2] Update Changelog --- CHANGELOG.md | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index a76cede..89af12f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,6 +7,9 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [Unreleased] +- **Ecto prefix configuration** - Support namespacing through PostgreSQL schemas, also called "prefixes" in Ecto. + - Excluding the `prefix` configuration will use primary schema (usually public). + ## [1.0.2] - 2025-12-28 ### Fixed @@ -50,4 +53,3 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - **Igniter installer** - `mix fyi.install` for one-command setup - **Emoji support** - Per-event, pattern-based, and default emoji configuration - **App name identification** - Identify events when multiple apps share channels -