# `Tink.Helpers`
[🔗](https://github.com/iamkanishka/tink.ex/blob/v0.1.1/lib/tink/helpers.ex#L1)

Helper functions and utilities for Tink.

Provides common utility functions used throughout the library:

- URL building and encoding
- Query parameter handling
- Response parsing
- Date/time formatting
- Money/decimal handling

## Examples

    # Build URL with query params
    url = Tink.Helpers.build_url("/api/v1/accounts", page_size: 10, page_token: "abc")
    #=> "/api/v1/accounts?page_size=10&page_token=abc"

    # Parse money amount
    amount = Tink.Helpers.parse_money(%{"value" => "123.45", "currencyCode" => "USD"})
    #=> %{amount: #Decimal<123.45>, currency: "USD"}

# `build_query_string`

```elixir
@spec build_query_string(keyword() | map()) :: String.t()
```

Builds a query string from parameters.

Handles nil values, lists, and nested maps appropriately.

## Examples

    iex> Tink.Helpers.build_query_string(foo: "bar", baz: 123)
    "foo=bar&baz=123"

    iex> Tink.Helpers.build_query_string(foo: nil, bar: "baz")
    "bar=baz"

# `build_url`

```elixir
@spec build_url(String.t(), keyword() | map()) :: String.t()
```

Builds a URL with query parameters.

## Examples

    iex> Tink.Helpers.build_url("/api/v1/accounts", page_size: 10)
    "/api/v1/accounts?page_size=10"

    iex> Tink.Helpers.build_url("/api/v1/accounts", [])
    "/api/v1/accounts"

# `decode_json`

```elixir
@spec decode_json(String.t()) :: {:ok, term()} | {:error, Jason.DecodeError.t()}
```

Safely decodes JSON.

## Examples

    iex> Tink.Helpers.decode_json(~s({"foo":"bar"}))
    {:ok, %{"foo" => "bar"}}

    iex> Tink.Helpers.decode_json("invalid")
    {:error, %Jason.DecodeError{}}

# `encode_json`

```elixir
@spec encode_json(term()) :: {:ok, String.t() | nil} | {:error, term()}
```

Safely encodes body as JSON.

## Examples

    iex> Tink.Helpers.encode_json(%{foo: "bar"})
    {:ok, ~s({"foo":"bar"})}

    iex> Tink.Helpers.encode_json(nil)
    {:ok, nil}

# `format_date`

```elixir
@spec format_date(Date.t() | String.t()) :: String.t()
```

Formats a date for the Tink API (ISO 8601).

## Examples

    iex> date = ~D[2024-01-15]
    iex> Tink.Helpers.format_date(date)
    "2024-01-15"

    iex> Tink.Helpers.format_date("2024-01-15")
    "2024-01-15"

# `get_in_safe`

```elixir
@spec get_in_safe(map(), [String.t() | atom()]) :: term()
```

Safely gets a nested value from a map.

## Examples

    iex> map = %{"user" => %{"name" => "John"}}
    iex> Tink.Helpers.get_in_safe(map, ["user", "name"])
    "John"

    iex> Tink.Helpers.get_in_safe(map, ["user", "age"])
    nil

# `merge_pagination_params`

```elixir
@spec merge_pagination_params(
  keyword(),
  String.t() | nil
) :: keyword()
```

Merges pagination params into options.

## Examples

    iex> Tink.Helpers.merge_pagination_params([page_size: 10], "token123")
    [page_size: 10, page_token: "token123"]

# `parse_date`

```elixir
@spec parse_date(String.t()) :: {:ok, Date.t()} | {:error, atom()}
```

Parses a date from ISO 8601 string.

## Examples

    iex> Tink.Helpers.parse_date("2024-01-15")
    {:ok, ~D[2024-01-15]}

    iex> Tink.Helpers.parse_date("invalid")
    {:error, :invalid_date}

# `parse_decimal`

```elixir
@spec parse_decimal(String.t() | number() | nil) :: Decimal.t()
```

Parses a decimal value safely.

## Examples

    iex> Tink.Helpers.parse_decimal("123.45")
    #Decimal<123.45>

    iex> Tink.Helpers.parse_decimal(123.45)
    #Decimal<123.45>

    iex> Tink.Helpers.parse_decimal(nil)
    #Decimal<0>

# `parse_money`

```elixir
@spec parse_money(map()) :: %{amount: Decimal.t(), currency: String.t()} | nil
```

Parses a money amount from Tink API response.

## Examples

    iex> Tink.Helpers.parse_money(%{"value" => "123.45", "currencyCode" => "USD"})
    %{amount: Decimal.new("123.45"), currency: "USD"}

    iex> Tink.Helpers.parse_money(%{"value" => 123.45, "currencyCode" => "EUR"})
    %{amount: Decimal.new("123.45"), currency: "EUR"}

# `redact_sensitive`

```elixir
@spec redact_sensitive(map()) :: map()
```

Redacts sensitive information from logs.

## Examples

    iex> Tink.Helpers.redact_sensitive(%{access_token: "secret", data: "public"})
    %{access_token: "[REDACTED]", data: "public"}

# `to_camel_case`

```elixir
@spec to_camel_case(String.t() | atom()) :: String.t()
```

Converts snake_case to camelCase.

## Examples

    iex> Tink.Helpers.to_camel_case("page_size")
    "pageSize"

    iex> Tink.Helpers.to_camel_case("page_token")
    "pageToken"

# `validate_required`

```elixir
@spec validate_required(map(), [atom()]) :: :ok | {:error, String.t()}
```

Validates required parameters are present.

## Examples

    iex> params = %{user_id: "123", scope: "accounts:read"}
    iex> Tink.Helpers.validate_required(params, [:user_id, :scope])
    :ok

    iex> params = %{user_id: "123"}
    iex> Tink.Helpers.validate_required(params, [:user_id, :scope])
    {:error, "Missing required parameter: scope"}

---

*Consult [api-reference.md](api-reference.md) for complete listing*
