Sheetshow.Token (Sheetshow v0.1.0)

Copy Markdown View Source

An access token and the moment it stops working.

A token is a value. Sheetshow hands you one and takes no further interest: where you keep it, when you refresh it and whether you share it between processes are your decisions, not the library's.

iex> token = Sheetshow.Token.new("ya29.abc", ~U[2026-09-12 09:00:00Z])
iex> Sheetshow.Token.expired?(token, ~U[2026-09-12 08:59:00Z])
false
iex> Sheetshow.Token.authorization(token)
"Bearer ya29.abc"

Inspecting a token shows everything but the token itself, so one can be printed in a log or a test failure without leaking.

Summary

Functions

The Authorization header's value.

Whether the token has run out. Pass a moment in the future for a margin: expired?(token, DateTime.add(DateTime.utc_now(), 60)) asks whether it will still be good in a minute.

A token from what the token endpoint answered, with expires_in turned into a moment. Options: :now (default now) and :scopes, used when the answer does not name them.

Builds a token. Options: :type (default "Bearer") and :scopes.

Types

t()

@type t() :: %Sheetshow.Token{
  access_token: String.t(),
  expires_at: DateTime.t(),
  scopes: [String.t()],
  type: String.t()
}

Functions

authorization(token)

@spec authorization(t()) :: String.t()

The Authorization header's value.

iex> Sheetshow.Token.new("ya29.abc", ~U[2026-09-12 09:00:00Z]) |> Sheetshow.Token.authorization()
"Bearer ya29.abc"

expired?(token, at \\ DateTime.utc_now())

@spec expired?(t(), DateTime.t()) :: boolean()

Whether the token has run out. Pass a moment in the future for a margin: expired?(token, DateTime.add(DateTime.utc_now(), 60)) asks whether it will still be good in a minute.

iex> token = Sheetshow.Token.new("ya29.abc", ~U[2026-09-12 09:00:00Z])
iex> Sheetshow.Token.expired?(token, ~U[2026-09-12 09:00:00Z])
true

from_response(response, opts \\ [])

@spec from_response(map(), keyword()) :: {:ok, t()} | {:error, Sheetshow.Error.t()}

A token from what the token endpoint answered, with expires_in turned into a moment. Options: :now (default now) and :scopes, used when the answer does not name them.

iex> {:ok, token} =
...>   Sheetshow.Token.from_response(%{"access_token" => "ya29.abc", "expires_in" => 3600},
...>     now: ~U[2026-09-12 08:00:00Z]
...>   )
iex> token.expires_at
~U[2026-09-12 09:00:00Z]

iex> {:error, %Sheetshow.Error{reason: :auth}} =
...>   Sheetshow.Token.from_response(%{"error" => "invalid_grant"})

from_response!(response, opts \\ [])

@spec from_response!(map(), keyword()) :: t()

Same as from_response/2, raising on failure.

new(access_token, expires_at, opts \\ [])

@spec new(String.t(), DateTime.t(), keyword()) :: t()

Builds a token. Options: :type (default "Bearer") and :scopes.

iex> Sheetshow.Token.new("ya29.abc", ~U[2026-09-12 09:00:00Z], scopes: ["a"]).scopes
["a"]