defmodule Linear.Mutations do @moduledoc false alias Linear.Client @create_issue_mutation """ mutation LinearCreateIssue($input: IssueCreateInput!) { issueCreate(input: $input) { success issue { id identifier title url state { id name } team { id name key } } } } """ @update_issue_mutation """ mutation LinearUpdateIssue($id: String!, $input: IssueUpdateInput!) { issueUpdate(id: $id, input: $input) { success issue { id identifier title url state { id name } } } } """ @create_comment_mutation """ mutation LinearCreateComment($issueId: String!, $body: String!) { commentCreate(input: {issueId: $issueId, body: $body}) { success comment { id body createdAt } } } """ @state_lookup_query """ query LinearResolveState($issueId: String!, $stateName: String!) { issue(id: $issueId) { team { states(filter: {name: {eq: $stateName}}, first: 1) { nodes { id } } } } } """ @spec create_issue(Client.t(), map(), keyword()) :: {:ok, map()} | {:error, term()} def create_issue(client, attrs, opts \\ []) when is_map(attrs) do query_opts = Keyword.take(opts, [:request_fn]) case Client.query(client, @create_issue_mutation, Keyword.merge(query_opts, variables: %{"input" => attrs})) do {:ok, %{"issueCreate" => %{"success" => true, "issue" => issue}}} -> {:ok, issue} {:ok, %{"issueCreate" => %{"success" => false}}} -> {:error, :issue_create_failed} error -> error end end @spec update_issue(Client.t(), String.t(), map(), keyword()) :: {:ok, map()} | {:error, term()} def update_issue(client, issue_id, attrs, opts \\ []) when is_binary(issue_id) and is_map(attrs) do query_opts = Keyword.take(opts, [:request_fn]) case Client.query( client, @update_issue_mutation, Keyword.merge(query_opts, variables: %{"id" => issue_id, "input" => attrs}) ) do {:ok, %{"issueUpdate" => %{"success" => true, "issue" => issue}}} -> {:ok, issue} {:ok, %{"issueUpdate" => %{"success" => false}}} -> {:error, :issue_update_failed} error -> error end end @spec create_comment(Client.t(), String.t(), String.t(), keyword()) :: {:ok, map()} | {:error, term()} def create_comment(client, issue_id, body, opts \\ []) when is_binary(issue_id) and is_binary(body) do query_opts = Keyword.take(opts, [:request_fn]) case Client.query( client, @create_comment_mutation, Keyword.merge(query_opts, variables: %{"issueId" => issue_id, "body" => body}) ) do {:ok, %{"commentCreate" => %{"success" => true, "comment" => comment}}} -> {:ok, comment} {:ok, %{"commentCreate" => %{"success" => false}}} -> {:error, :comment_create_failed} error -> error end end @spec transition_issue(Client.t(), String.t(), String.t(), keyword()) :: {:ok, map()} | {:error, term()} def transition_issue(client, issue_id, state_name, opts \\ []) when is_binary(issue_id) and is_binary(state_name) do query_opts = Keyword.take(opts, [:request_fn]) with {:ok, state_id} <- resolve_state_id(client, issue_id, state_name, query_opts) do update_issue(client, issue_id, %{"stateId" => state_id}, opts) end end defp resolve_state_id(client, issue_id, state_name, query_opts) do case Client.query( client, @state_lookup_query, Keyword.merge(query_opts, variables: %{"issueId" => issue_id, "stateName" => state_name}) ) do {:ok, data} -> case get_in(data, ["issue", "team", "states", "nodes", Access.at(0), "id"]) do nil -> {:error, {:state_not_found, state_name}} id -> {:ok, id} end error -> error end end end