defmodule TerminusDB.Prefix do @moduledoc """ Prefix management API for TerminusDB. Wraps the `/api/prefix/{path}` and `/api/prefixes/{path}` endpoints for managing custom prefix mappings in a database. All functions require a `TerminusDB.Config` scoped to a database. ## Quick start config = TerminusDB.Config.new(endpoint: "http://localhost:6363") |> TerminusDB.Config.with_database("mydb") {:ok, uri} = TerminusDB.Prefix.get(config, "ex") {:ok, _} = TerminusDB.Prefix.add(config, "ex", "http://example.org/") {:ok, _} = TerminusDB.Prefix.update(config, "ex", "http://example.com/") {:ok, _} = TerminusDB.Prefix.delete(config, "ex") """ alias TerminusDB.{Client, Config, Error} @type prefix_opt :: {:organization, String.t()} | {:repo, String.t()} defp prefix_base_path(config, opts) do org = opts[:organization] || config.organization case config.database do nil -> {:error, %Error{reason: :config, message: "no database scoped in config"}} db -> repo = opts[:repo] || config.repo branch = config.branch {:ok, "prefix/#{org}/#{db}/#{repo}/branch/#{branch}"} end end defp prefixes_path(config, opts) do org = opts[:organization] || config.organization case config.database do nil -> {:error, %Error{reason: :config, message: "no database scoped in config"}} db -> {:ok, "prefixes/#{org}/#{db}"} end end @doc """ Gets a single prefix IRI by name. ## Examples iex> config = TerminusDB.Config.new( ...> endpoint: "http://localhost:6363", ...> adapter: fn req -> {req, Req.Response.new(status: 200, body: %{"api:prefix_uri" => "http://example.org/"})} end ...> ) |> TerminusDB.Config.with_database("mydb") iex> {:ok, uri} = TerminusDB.Prefix.get(config, "ex") iex> uri "http://example.org/" """ @spec get(Config.t(), String.t(), [prefix_opt()]) :: {:ok, String.t()} | {:error, Error.t()} def get(config, prefix_name, opts \\ []) do with {:ok, base} <- prefix_base_path(config, opts) do path = "#{base}/#{prefix_name}" case Client.request(config, :get, path, area: :prefix) do {:ok, %{"api:prefix_uri" => uri}} -> {:ok, uri} {:ok, body} -> {:ok, body} {:error, _} = error -> error end end end @doc """ Gets a single prefix IRI by name, or raises. ## Examples iex> config = TerminusDB.Config.new( ...> endpoint: "http://localhost:6363", ...> adapter: fn req -> {req, Req.Response.new(status: 200, body: %{"api:prefix_uri" => "http://example.org/"})} end ...> ) |> TerminusDB.Config.with_database("mydb") iex> TerminusDB.Prefix.get!(config, "ex") "http://example.org/" """ @spec get!(Config.t(), String.t(), [prefix_opt()]) :: String.t() def get!(config, prefix_name, opts \\ []) do case get(config, prefix_name, opts) do {:ok, uri} -> uri {:error, error} -> raise error end end @doc """ Adds a new prefix mapping. ## Examples iex> config = TerminusDB.Config.new( ...> endpoint: "http://localhost:6363", ...> adapter: fn req -> {req, Req.Response.new(status: 200, body: %{"api:status" => "api:success"})} end ...> ) |> TerminusDB.Config.with_database("mydb") iex> {:ok, resp} = TerminusDB.Prefix.add(config, "ex", "http://example.org/") iex> resp["api:status"] "api:success" """ @spec add(Config.t(), String.t(), String.t(), [prefix_opt()]) :: {:ok, map()} | {:error, Error.t()} def add(config, prefix_name, uri, opts \\ []) do with {:ok, base} <- prefix_base_path(config, opts) do path = "#{base}/#{prefix_name}" Client.request(config, :post, path, json: %{"uri" => uri}, area: :prefix) end end @doc """ Adds a new prefix mapping, or raises. ## Examples iex> config = TerminusDB.Config.new( ...> endpoint: "http://localhost:6363", ...> adapter: fn req -> {req, Req.Response.new(status: 200, body: %{"api:status" => "api:success"})} end ...> ) |> TerminusDB.Config.with_database("mydb") iex> TerminusDB.Prefix.add!(config, "ex", "http://example.org/") %{"api:status" => "api:success"} """ @spec add!(Config.t(), String.t(), String.t(), [prefix_opt()]) :: map() def add!(config, prefix_name, uri, opts \\ []) do case add(config, prefix_name, uri, opts) do {:ok, body} -> body {:error, error} -> raise error end end @doc """ Updates an existing prefix mapping. ## Examples iex> config = TerminusDB.Config.new( ...> endpoint: "http://localhost:6363", ...> adapter: fn req -> {req, Req.Response.new(status: 200, body: %{"api:status" => "api:success"})} end ...> ) |> TerminusDB.Config.with_database("mydb") iex> {:ok, resp} = TerminusDB.Prefix.update(config, "ex", "http://example.com/") iex> resp["api:status"] "api:success" """ @spec update(Config.t(), String.t(), String.t(), [prefix_opt()]) :: {:ok, map()} | {:error, Error.t()} def update(config, prefix_name, uri, opts \\ []) do with {:ok, base} <- prefix_base_path(config, opts) do path = "#{base}/#{prefix_name}" Client.request(config, :put, path, json: %{"uri" => uri}, area: :prefix) end end @doc """ Updates an existing prefix mapping, or raises. ## Examples iex> config = TerminusDB.Config.new( ...> endpoint: "http://localhost:6363", ...> adapter: fn req -> {req, Req.Response.new(status: 200, body: %{"api:status" => "api:success"})} end ...> ) |> TerminusDB.Config.with_database("mydb") iex> TerminusDB.Prefix.update!(config, "ex", "http://example.com/") %{"api:status" => "api:success"} """ @spec update!(Config.t(), String.t(), String.t(), [prefix_opt()]) :: map() def update!(config, prefix_name, uri, opts \\ []) do case update(config, prefix_name, uri, opts) do {:ok, body} -> body {:error, error} -> raise error end end @doc """ Creates or updates a prefix mapping (upsert). ## Examples iex> config = TerminusDB.Config.new( ...> endpoint: "http://localhost:6363", ...> adapter: fn req -> {req, Req.Response.new(status: 200, body: %{"api:status" => "api:success"})} end ...> ) |> TerminusDB.Config.with_database("mydb") iex> {:ok, resp} = TerminusDB.Prefix.upsert(config, "ex", "http://example.org/") iex> resp["api:status"] "api:success" """ @spec upsert(Config.t(), String.t(), String.t(), [prefix_opt()]) :: {:ok, map()} | {:error, Error.t()} def upsert(config, prefix_name, uri, opts \\ []) do with {:ok, base} <- prefix_base_path(config, opts) do path = "#{base}/#{prefix_name}" Client.request(config, :put, path, json: %{"uri" => uri}, params: [create: true], area: :prefix ) end end @doc """ Creates or updates a prefix mapping (upsert), or raises. ## Examples iex> config = TerminusDB.Config.new( ...> endpoint: "http://localhost:6363", ...> adapter: fn req -> {req, Req.Response.new(status: 200, body: %{"api:status" => "api:success"})} end ...> ) |> TerminusDB.Config.with_database("mydb") iex> TerminusDB.Prefix.upsert!(config, "ex", "http://example.org/") %{"api:status" => "api:success"} """ @spec upsert!(Config.t(), String.t(), String.t(), [prefix_opt()]) :: map() def upsert!(config, prefix_name, uri, opts \\ []) do case upsert(config, prefix_name, uri, opts) do {:ok, body} -> body {:error, error} -> raise error end end @doc """ Deletes a prefix mapping. ## Examples iex> config = TerminusDB.Config.new( ...> endpoint: "http://localhost:6363", ...> adapter: fn req -> {req, Req.Response.new(status: 200, body: %{"api:status" => "api:success"})} end ...> ) |> TerminusDB.Config.with_database("mydb") iex> {:ok, resp} = TerminusDB.Prefix.delete(config, "ex") iex> resp["api:status"] "api:success" """ @spec delete(Config.t(), String.t(), [prefix_opt()]) :: {:ok, map()} | {:error, Error.t()} def delete(config, prefix_name, opts \\ []) do with {:ok, base} <- prefix_base_path(config, opts) do path = "#{base}/#{prefix_name}" Client.request(config, :delete, path, area: :prefix) end end @doc """ Deletes a prefix mapping, or raises. ## Examples iex> config = TerminusDB.Config.new( ...> endpoint: "http://localhost:6363", ...> adapter: fn req -> {req, Req.Response.new(status: 200, body: %{"api:status" => "api:success"})} end ...> ) |> TerminusDB.Config.with_database("mydb") iex> TerminusDB.Prefix.delete!(config, "ex") %{"api:status" => "api:success"} """ @spec delete!(Config.t(), String.t(), [prefix_opt()]) :: map() def delete!(config, prefix_name, opts \\ []) do case delete(config, prefix_name, opts) do {:ok, body} -> body {:error, error} -> raise error end end @doc """ Gets all prefix mappings for the database. ## Examples iex> config = TerminusDB.Config.new( ...> endpoint: "http://localhost:6363", ...> adapter: fn req -> {req, Req.Response.new(status: 200, body: %{"@base" => "terminusdb:///data/", "@schema" => "terminusdb:///schema#"})} end ...> ) |> TerminusDB.Config.with_database("mydb") iex> {:ok, prefixes} = TerminusDB.Prefix.all(config) iex> prefixes["@schema"] "terminusdb:///schema#" """ @spec all(Config.t(), [prefix_opt()]) :: {:ok, map()} | {:error, Error.t()} def all(config, opts \\ []) do with {:ok, path} <- prefixes_path(config, opts) do Client.request(config, :get, path, area: :prefix) end end @doc """ Gets all prefix mappings, or raises. ## Examples iex> config = TerminusDB.Config.new( ...> endpoint: "http://localhost:6363", ...> adapter: fn req -> {req, Req.Response.new(status: 200, body: %{"@base" => "terminusdb:///data/", "@schema" => "terminusdb:///schema#"})} end ...> ) |> TerminusDB.Config.with_database("mydb") iex> TerminusDB.Prefix.all!(config)["@schema"] "terminusdb:///schema#" """ @spec all!(Config.t(), [prefix_opt()]) :: map() def all!(config, opts \\ []) do case all(config, opts) do {:ok, body} -> body {:error, error} -> raise error end end end