chore: next big god module down

Co-authored-by: Copilot <copilot@github.com>
This commit is contained in:
2026-05-01 10:47:25 +02:00
parent 13a86e92bd
commit 5a464920de
10 changed files with 1656 additions and 1537 deletions

View File

@@ -0,0 +1,204 @@
defmodule BDS.Scripting.Capabilities.Projects do
@moduledoc false
import BDS.Scripting.Capabilities.Crud
import BDS.Scripting.Capabilities.Util
alias BDS.Metadata
alias BDS.Projects, as: ProjectsCtx
alias BDS.Projects.Project
alias BDS.Repo
alias BDS.Tags
def create_project(attrs), do: attrs |> normalize_map() |> ProjectsCtx.create_project() |> unwrap_result()
def delete_project(project_id), do: boolean_result(ProjectsCtx.delete_project(string_or_nil(project_id)))
def delete_project_with_data(project_id) do
case string_or_nil(project_id) && ProjectsCtx.get_project(string_or_nil(project_id)) do
%Project{} = project ->
data_dir = ProjectsCtx.project_data_dir(project)
case ProjectsCtx.delete_project(project.id) do
{:ok, _deleted_project} ->
_ = File.rm_rf(data_dir)
true
{:error, _reason} ->
false
end
_other ->
false
end
end
def load_project(project_id) do
case string_or_nil(project_id) do
nil -> nil
id -> ProjectsCtx.get_project(id) |> sanitize_nilable()
end
end
def list_projects do
ProjectsCtx.list_projects()
|> Enum.map(&sanitize/1)
end
def set_active_project(project_id) do
project_id
|> string_or_nil()
|> then(fn
nil -> {:error, :not_found}
id -> ProjectsCtx.set_active_project(id)
end)
|> unwrap_result()
end
def update_project(project_id, attrs) do
case string_or_nil(project_id) && ProjectsCtx.get_project(string_or_nil(project_id)) do
%Project{} = project ->
attrs = normalize_map(attrs)
updates = %{
name: Map.get(attrs, "name", project.name),
description: Map.get(attrs, "description", project.description),
data_path: Map.get(attrs, "data_path", project.data_path),
updated_at: System.system_time(:millisecond),
is_active: Map.get(attrs, "is_active", project.is_active)
}
project
|> Project.changeset(updates)
|> Repo.update()
|> unwrap_result()
_other ->
nil
end
end
def load_metadata(project_id) do
{:ok, metadata} = Metadata.get_project_metadata(project_id)
sanitize(metadata)
end
def update_project_metadata(project_id, attrs) do
Metadata.update_project_metadata(project_id, normalize_map(attrs))
|> unwrap_result()
end
def add_category(project_id, name) do
Metadata.add_category(project_id, string_or_nil(name) || "")
|> unwrap_result()
end
def remove_category(project_id, name) do
Metadata.remove_category(project_id, string_or_nil(name) || "")
|> unwrap_result()
end
def metadata_categories(project_id) do
load_metadata(project_id)
|> Map.get("categories", [])
end
def metadata_tags(project_id) do
project_id
|> list_tags()
|> Enum.map(&Map.get(&1, "name"))
end
def add_meta_tag(project_id, name) do
normalized_name = string_or_nil(name) |> to_string() |> String.trim()
cond do
normalized_name == "" -> metadata_tags(project_id)
load_tag_by_name(project_id, normalized_name) -> metadata_tags(project_id)
true ->
create_tag(project_id, %{"name" => normalized_name})
metadata_tags(project_id)
end
end
def remove_meta_tag(project_id, name) do
case load_tag_by_name(project_id, name) do
%{"id" => tag_id} ->
_ = delete_tag(project_id, tag_id)
metadata_tags(project_id)
_other ->
metadata_tags(project_id)
end
end
def publishing_preferences(project_id) do
load_metadata(project_id)
|> Map.get("publishing_preferences")
end
def set_publishing_preferences(project_id, prefs) do
project_id
|> Metadata.set_publishing_preferences(normalize_map(prefs))
|> unwrap_result()
|> case do
nil -> nil
metadata -> Map.get(metadata, "publishing_preferences")
end
end
def clear_publishing_preferences(project_id) do
set_publishing_preferences(project_id, %{})
end
def sync_meta_on_startup(project_id) do
_ = Tags.sync_tags_from_posts(project_id)
%{
tags: metadata_tags(project_id),
categories: metadata_categories(project_id),
project_metadata: load_metadata(project_id)
}
end
def data_paths(project_id) do
database_path = Repo.config()[:database]
project_dir = project_path(project_id)
%{
database: database_path,
project: project_dir,
posts: Path.join(project_dir, "posts"),
media: Path.join(project_dir, "media")
}
end
def read_project_metadata(folder_path) do
case project_for_folder(folder_path) do
nil -> read_project_metadata_file(folder_path)
project -> load_metadata(project.id)
end
end
def project_for_folder(folder_path) do
normalized = string_or_nil(folder_path)
ProjectsCtx.list_projects()
|> Enum.find(fn project -> ProjectsCtx.project_data_dir(project) == normalized end)
end
def read_project_metadata_file(folder_path) do
path = Path.join([string_or_nil(folder_path) || "", "meta", "project.json"])
case File.read(path) do
{:ok, contents} ->
case Jason.decode(contents) do
{:ok, decoded} when is_map(decoded) -> sanitize(decoded)
_other -> nil
end
{:error, _reason} ->
nil
end
end
end