QlikElixir.REST.Helpers (qlik_elixir v0.4.0)
View SourceShared helper functions for REST API modules.
Provides common utilities for configuration handling, query building, and request body construction used across all REST endpoints.
Summary
Functions
Adds a parameter to a keyword list if the value is not nil.
Builds a request body map from params using provided field list.
Builds the full path with query string appended if present.
Builds a query string from options using a list of {api_key, opts_key} tuples.
Formats bytes into human readable string (B, KB, MB, GB).
Extracts configuration from options, falling back to default config.
Normalizes a repeatable query parameter into the comma-separated form Qlik
expects, leaving scalars and nil untouched.
Normalizes a delete response to :ok on success.
Normalizes a get response, converting :file_not_found to :not_found.
Puts a key-value pair into a map if the value is not nil.
Validates that a file path points to a regular file.
Validates file size against maximum allowed (500MB).
Validates that filename ends with .csv extension.
Functions
Adds a parameter to a keyword list if the value is not nil.
Examples
iex> QlikElixir.REST.Helpers.add_param([], :limit, 10)
[limit: 10]
iex> QlikElixir.REST.Helpers.add_param([], :limit, nil)
[]
Builds a request body map from params using provided field list.
Supports two formats:
- Atom list:
[:name, :description]- uses atom as both param key and API key - Tuple list:
[{"apiKey", :param_key}]- maps param key to different API key
Examples
iex> params = %{name: "Test", description: "Desc"}
iex> QlikElixir.REST.Helpers.build_body(params, [:name, :description])
%{"name" => "Test", "description" => "Desc"}
iex> params = %{space_id: "abc"}
iex> QlikElixir.REST.Helpers.build_body(params, [{"spaceId", :space_id}])
%{"spaceId" => "abc"}
Builds the full path with query string appended if present.
Examples
iex> QlikElixir.REST.Helpers.build_path("api/v1/apps", "limit=10")
"api/v1/apps?limit=10"
iex> QlikElixir.REST.Helpers.build_path("api/v1/apps", "")
"api/v1/apps"
Builds a query string from options using a list of {api_key, opts_key} tuples.
Cursor-paginated endpoints — most of them — get limit and next for free. Pass
base_mappings to override that for an endpoint that pages differently, as the
report templates one does with skip.
List values are comma-joined, so a repeatable parameter can be given as a list.
Examples
iex> QlikElixir.REST.Helpers.build_query([limit: 10, space_id: "abc"], [{:spaceId, :space_id}])
"limit=10&spaceId=abc"
iex> QlikElixir.REST.Helpers.build_query([skip: 20], [{:skip, :skip}], [{:limit, :limit}])
"skip=20"
iex> QlikElixir.REST.Helpers.build_query([sort: ["+name", "-createdAt"]], [{:sort, :sort}])
"sort=%2Bname%2C-createdAt"
@spec format_bytes(non_neg_integer()) :: String.t()
Formats bytes into human readable string (B, KB, MB, GB).
@spec get_config(keyword()) :: QlikElixir.Config.t()
Extracts configuration from options, falling back to default config.
Examples
iex> config = QlikElixir.Config.new(api_key: "key", tenant_url: "https://example.com")
iex> QlikElixir.REST.Helpers.get_config(config: config).api_key
"key"
Normalizes a repeatable query parameter into the comma-separated form Qlik
expects, leaving scalars and nil untouched.
Examples
iex> QlikElixir.REST.Helpers.join_param(["+name", "-updatedAt"])
"+name,-updatedAt"
iex> QlikElixir.REST.Helpers.join_param("+name")
"+name"
iex> QlikElixir.REST.Helpers.join_param(nil)
nil
@spec normalize_delete_response({:ok, any()} | {:error, any()}, String.t()) :: :ok | {:error, any()}
Normalizes a delete response to :ok on success.
Converts :file_not_found errors to :not_found with a custom message.
Examples
iex> QlikElixir.REST.Helpers.normalize_delete_response({:ok, %{}}, "User")
:ok
iex> {:error, error} = QlikElixir.REST.Helpers.normalize_delete_response({:error, %QlikElixir.Error{type: :file_not_found}}, "User")
iex> {error.type, error.message}
{:not_found, "User not found"}
@spec normalize_get_response({:ok, any()} | {:error, any()}, String.t()) :: {:ok, any()} | {:error, any()}
Normalizes a get response, converting :file_not_found to :not_found.
Examples
iex> QlikElixir.REST.Helpers.normalize_get_response({:ok, %{"id" => "123"}}, "User")
{:ok, %{"id" => "123"}}
iex> {:error, error} = QlikElixir.REST.Helpers.normalize_get_response({:error, %QlikElixir.Error{type: :file_not_found}}, "User")
iex> {error.type, error.message}
{:not_found, "User not found"}
Puts a key-value pair into a map if the value is not nil.
Examples
iex> QlikElixir.REST.Helpers.put_if_present(%{}, "name", "test")
%{"name" => "test"}
iex> QlikElixir.REST.Helpers.put_if_present(%{}, "name", nil)
%{}
@spec validate_file(String.t()) :: {:ok, File.Stat.t()} | {:error, QlikElixir.Error.t()}
Validates that a file path points to a regular file.
Examples
iex> {:ok, stat} = QlikElixir.REST.Helpers.validate_file("mix.exs")
iex> stat.type
:regular
iex> {:error, error} = QlikElixir.REST.Helpers.validate_file("/nonexistent")
iex> error.type
:file_not_found
@spec validate_file_size(non_neg_integer()) :: :ok | {:error, QlikElixir.Error.t()}
Validates file size against maximum allowed (500MB).
@spec validate_filename(String.t()) :: :ok | {:error, QlikElixir.Error.t()}
Validates that filename ends with .csv extension.