Packages

Elixir client for the Linear GraphQL API.

Current section

Files

Jump to
linear_client lib linear queries.ex
Raw

lib/linear/queries.ex

defmodule Linear.Queries do
@moduledoc false
alias Linear.{Client, Pagination}
@viewer_query """
query LinearViewer {
viewer { id name email displayName active admin }
}
"""
@teams_query """
query LinearTeams {
teams { nodes { id name key description } }
}
"""
@issue_query """
query LinearIssue($id: String!) {
issue(id: $id) {
id identifier title description priority url branchName
state { id name }
assignee { id name email }
labels { nodes { id name color } }
project { id name }
team { id name key }
createdAt updatedAt
}
}
"""
@issues_query """
query LinearIssues($filter: IssueFilter, $first: Int!, $after: String, $includeArchived: Boolean) {
issues(filter: $filter, first: $first, after: $after, includeArchived: $includeArchived) {
nodes {
id identifier title description priority url branchName
state { id name }
assignee { id name email }
labels { nodes { id name color } }
project { id name }
team { id name key }
createdAt updatedAt
}
pageInfo { hasNextPage endCursor }
}
}
"""
@workflow_states_query """
query LinearWorkflowStates($filter: WorkflowStateFilter) {
workflowStates(filter: $filter) {
nodes { id name color type position
team { id name key }
}
}
}
"""
@projects_query """
query LinearProjects($first: Int!, $after: String, $includeArchived: Boolean) {
projects(first: $first, after: $after, includeArchived: $includeArchived) {
nodes {
id name description state url
teams { nodes { id name key } }
createdAt updatedAt
}
pageInfo { hasNextPage endCursor }
}
}
"""
@spec viewer(Client.t(), keyword()) :: {:ok, map()} | {:error, term()}
def viewer(client, opts \\ []) do
case Client.query(client, @viewer_query, opts) do
{:ok, %{"viewer" => viewer}} -> {:ok, viewer}
error -> error
end
end
@spec list_teams(Client.t(), keyword()) :: {:ok, [map()]} | {:error, term()}
def list_teams(client, opts \\ []) do
case Client.query(client, @teams_query, opts) do
{:ok, %{"teams" => %{"nodes" => nodes}}} -> {:ok, nodes}
error -> error
end
end
@spec get_issue(Client.t(), String.t(), keyword()) :: {:ok, map()} | {:error, term()}
def get_issue(client, issue_id, opts \\ []) do
case Client.query(client, @issue_query, Keyword.merge(opts, variables: %{"id" => issue_id})) do
{:ok, %{"issue" => issue}} -> {:ok, issue}
error -> error
end
end
@spec list_issues(Client.t(), keyword()) :: {:ok, [map()]} | {:error, term()}
def list_issues(client, opts \\ []) do
first = Keyword.get(opts, :first, 50)
include_archived = Keyword.get(opts, :include_archived, false)
filter = build_issue_filter(opts)
query_opts = Keyword.take(opts, [:request_fn])
Pagination.paginate(fn after_cursor ->
variables =
%{"filter" => filter, "first" => first, "includeArchived" => include_archived}
|> put_cursor(after_cursor)
case Client.query(client, @issues_query, Keyword.merge(query_opts, variables: variables)) do
{:ok, %{"issues" => connection}} -> {:ok, connection}
error -> error
end
end)
end
@spec list_workflow_states(Client.t(), keyword()) :: {:ok, [map()]} | {:error, term()}
def list_workflow_states(client, opts \\ []) do
filter =
case Keyword.get(opts, :team_id) do
nil -> nil
id -> %{"team" => %{"id" => %{"eq" => id}}}
end
variables = if filter, do: %{"filter" => filter}, else: %{}
query_opts = Keyword.take(opts, [:request_fn])
case Client.query(client, @workflow_states_query, Keyword.merge(query_opts, variables: variables)) do
{:ok, %{"workflowStates" => %{"nodes" => nodes}}} -> {:ok, nodes}
error -> error
end
end
@spec list_projects(Client.t(), keyword()) :: {:ok, [map()]} | {:error, term()}
def list_projects(client, opts \\ []) do
first = Keyword.get(opts, :first, 50)
include_archived = Keyword.get(opts, :include_archived, false)
query_opts = Keyword.take(opts, [:request_fn])
Pagination.paginate(fn after_cursor ->
variables =
%{"first" => first, "includeArchived" => include_archived}
|> put_cursor(after_cursor)
case Client.query(client, @projects_query, Keyword.merge(query_opts, variables: variables)) do
{:ok, %{"projects" => connection}} -> {:ok, connection}
error -> error
end
end)
end
defp build_issue_filter(opts) do
%{}
|> maybe_filter(:team_id, opts, fn id -> %{"team" => %{"id" => %{"eq" => id}}} end)
|> maybe_filter(:project_id, opts, fn id -> %{"project" => %{"id" => %{"eq" => id}}} end)
|> maybe_filter(:state_names, opts, fn names -> %{"state" => %{"name" => %{"in" => names}}} end)
|> maybe_filter(:assignee_id, opts, fn id -> %{"assignee" => %{"id" => %{"eq" => id}}} end)
|> then(fn f -> if f == %{}, do: nil, else: f end)
end
defp maybe_filter(filter, key, opts, build_fn) do
case Keyword.get(opts, key) do
nil -> filter
[] -> filter
value -> Map.merge(filter, build_fn.(value))
end
end
defp put_cursor(variables, nil), do: variables
defp put_cursor(variables, cursor), do: Map.put(variables, "after", cursor)
end