diff --git a/CHANGELOG.md b/CHANGELOG.md
index 7cdafb90..b42cb2c8 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,5 +1,8 @@
## Unreleased
+- BREAKING: Moving REST client to its own repo. Check the new REST entry in the [README](./#REST)
+ If the REST client is used you must include the new REST client repo:
+ `{:shopify_api_rest, github: "orbit-apps/elixir-shopifyapi-rest", tag: "v0.1.0"}`
- BREAKING: AppServer now defaults to a single app instance, this is a compile env if you want to use the old multi app config add `config :shopify_api, :app_server, :multi_app` to your `config/config.exs`
- New: Single app mode for AppServer, is API compatible with the multi app setup. This greatly simplifies the most common setup, one app <> one phoenix setup.
- New: Add handle and raw app config to the App struct
diff --git a/README.md b/README.md
index bc454821..e5930866 100644
--- a/README.md
+++ b/README.md
@@ -13,6 +13,7 @@
- [AuthTokens](#AuthTokens)
- [Webhooks](#Webhooks)
- [GraphQL](#GraphQL)
+ - [REST](#REST)
- [Telemetry](#Telemetry)
## Installation
@@ -223,6 +224,17 @@ config :shopify_api, ShopifyAPI.GraphQL, graphql_version: "2024-10"
We are soft deprecating the old `ShopifyAPI.graphql_request/4`. It will not be marked as deprecated until people have had a chance to move over to the new method. The reasons for the move include 1) moving away from HTTPoison and towards Req. 2) Better handling of partial failures. 3) Overall cleaner implementations and more access to proper errors.
+## REST
+
+The REST client has been moved to its [own repo](https://github.com/orbit-apps/elixir-shopifyapi-rest)
+
+Using:
+
+- include the new dependency `{:shopify_api, github: "pixelunion/elixir-shopifyapi-rest", tag: "v0.1.0"}`
+- make clean and compile `mix clean && mix compile`, as there is an optional endpoint `ShopifyAPI.request/2`
+ that is not compiled in unless the REST client is included.
+- make a REST call `iex> ShopifyAPI.REST.Product.all(token)`
+
## Telemetry
The `shopify_api` library will emit events using the [`:telemetry`](https://github.com/beam-telemetry/telemetry) library. Consumers of `shopify_api` can then use these events for customized metrics aggregation and more.
diff --git a/lib/shopify_api.ex b/lib/shopify_api.ex
index 825204ba..3276dd67 100644
--- a/lib/shopify_api.ex
+++ b/lib/shopify_api.ex
@@ -1,7 +1,6 @@
defmodule ShopifyAPI do
alias ShopifyAPI.GraphQL.GraphQLQuery
alias ShopifyAPI.GraphQL.GraphQLResponse
- alias ShopifyAPI.RateLimiting
alias ShopifyAPI.Throttled
@shopify_admin_uri URI.new!("https://admin.shopify.com")
@@ -40,7 +39,10 @@ defmodule ShopifyAPI do
def execute_graphql(%GraphQLQuery{} = query, scope, opts \\ []),
do: ShopifyAPI.GraphQL.execute(query, scope, opts)
- def request(token, func), do: Throttled.request(func, token, RateLimiting.RESTTracker)
+ if function_exported?(ShopifyAPI.RateLiting.RESTTracker, :init, 0) do
+ def request(token, func),
+ do: ShopifyAPIThrottled.request(func, token, ShopifyAPI.RateLimiting.RESTTracker)
+ end
@doc false
# Accessor for API transport layer, defaults to `https://`.
diff --git a/lib/shopify_api/application.ex b/lib/shopify_api/application.ex
index 53a3f4ba..f63221d3 100644
--- a/lib/shopify_api/application.ex
+++ b/lib/shopify_api/application.ex
@@ -6,7 +6,6 @@ defmodule ShopifyAPI.Application do
# See https://hexdocs.pm/elixir/Application.html
# for more information on OTP Applications
def start(_type, _args) do
- RateLimiting.RESTTracker.init()
RateLimiting.GraphQLTracker.init()
# Define workers and child supervisors to be supervised
diff --git a/lib/shopify_api/rate_limiting/rest.ex b/lib/shopify_api/rate_limiting/rest.ex
deleted file mode 100644
index 59dcac79..00000000
--- a/lib/shopify_api/rate_limiting/rest.ex
+++ /dev/null
@@ -1,16 +0,0 @@
-defmodule ShopifyAPI.RateLimiting.REST do
- @plus_bucket 400
- @nonplus_bucket 40
- @plus_requests_per_second 20
- @nonplus_requests_per_second 2
-
- @over_limit_status_code 429
-
- def over_limit_status_code, do: @over_limit_status_code
-
- def request_bucket(%{plus: true}), do: @plus_bucket
- def request_bucket(%{plus: false}), do: @nonplus_bucket
-
- def requests_per_second(%{plus: true}), do: @plus_requests_per_second
- def requests_per_second(%{plus: false}), do: @nonplus_requests_per_second
-end
diff --git a/lib/shopify_api/rate_limiting/rest_call_limits.ex b/lib/shopify_api/rate_limiting/rest_call_limits.ex
deleted file mode 100644
index 27afc9a3..00000000
--- a/lib/shopify_api/rate_limiting/rest_call_limits.ex
+++ /dev/null
@@ -1,57 +0,0 @@
-defmodule ShopifyAPI.RateLimiting.RESTCallLimits do
- @moduledoc """
- Responsible for handling ShopifyAPI call limits in a HTTPoison.Response
- """
- @shopify_call_limit_header "X-Shopify-Shop-Api-Call-Limit"
- @shopify_retry_after_header "Retry-After"
- @over_limit_status_code 429
- # API Overlimit error code
- @spec limit_header_or_status_code(any) :: nil | :over_limit
- def limit_header_or_status_code(%{status_code: @over_limit_status_code}),
- do: :over_limit
-
- def limit_header_or_status_code(%{headers: headers}),
- do: get_header(headers, @shopify_call_limit_header)
-
- def limit_header_or_status_code(_conn), do: nil
-
- def get_api_remaining_calls(nil), do: 0
-
- def get_api_remaining_calls(:over_limit), do: 0
-
- def get_api_remaining_calls(header_value) do
- # comes in the form "1/40": 1 taken of 40
- header_value
- |> String.split("/")
- |> Enum.map(&String.to_integer/1)
- |> calculate_available
- end
-
- def get_retry_after_header(%{headers: headers}),
- do: get_header(headers, @shopify_retry_after_header, "2.0")
-
- def get_retry_after_milliseconds(header_value) do
- {seconds, remainder} = Integer.parse(header_value)
-
- {milliseconds, ""} =
- remainder
- |> String.replace_prefix(".", "")
- |> String.pad_trailing(3, "0")
- |> Integer.parse()
-
- seconds * 1000 + milliseconds
- end
-
- def get_header(headers, header_name, default \\ nil) do
- Enum.find_value(
- headers,
- default,
- fn
- {^header_name, value} -> value
- _ -> nil
- end
- )
- end
-
- defp calculate_available([used, total]), do: total - used
-end
diff --git a/lib/shopify_api/rate_limiting/rest_tracker.ex b/lib/shopify_api/rate_limiting/rest_tracker.ex
deleted file mode 100644
index a7d108b6..00000000
--- a/lib/shopify_api/rate_limiting/rest_tracker.ex
+++ /dev/null
@@ -1,70 +0,0 @@
-defmodule ShopifyAPI.RateLimiting.RESTTracker do
- @moduledoc """
- Handles Tracking of API throttling and when the API will be available for a request.
- """
- alias ShopifyAPI.RateLimiting
-
- @behaviour RateLimiting.Tracker
-
- @name :shopify_api_rest_availability_tracker
-
- @impl RateLimiting.Tracker
- def init, do: :ets.new(@name, [:named_table, :public])
-
- @impl RateLimiting.Tracker
- def all, do: :ets.tab2list(@name)
-
- @impl RateLimiting.Tracker
- def api_hit_limit(%ShopifyAPI.AuthToken{} = token, http_response, now \\ DateTime.utc_now()) do
- available_modifier =
- http_response
- |> RateLimiting.RESTCallLimits.get_retry_after_header()
- |> RateLimiting.RESTCallLimits.get_retry_after_milliseconds()
-
- set(token, 0, available_modifier, now)
- end
-
- @impl RateLimiting.Tracker
- def update_api_call_limit(%ShopifyAPI.AuthToken{} = token, http_response) do
- http_response
- |> RateLimiting.RESTCallLimits.limit_header_or_status_code()
- |> RateLimiting.RESTCallLimits.get_api_remaining_calls()
- |> case do
- # Wait for a second to allow time for a bucket fill
- 0 -> set(token, 0, 1_000)
- remaining -> set(token, remaining, 0)
- end
- end
-
- @impl RateLimiting.Tracker
- def get(%ShopifyAPI.AuthToken{} = token, now \\ DateTime.utc_now(), _estimated_cost) do
- case :ets.lookup(@name, ShopifyAPI.AuthToken.create_key(token)) do
- [] ->
- {RateLimiting.REST.request_bucket(token), 0}
-
- [{_key, count, time} | _] ->
- diff = time |> DateTime.diff(now, :millisecond) |> max(0)
-
- {count, diff}
- end
- end
-
- @impl RateLimiting.Tracker
- def set(token, available_count, availability_delay, now \\ DateTime.utc_now())
-
- # Do nothing
- def set(_token, nil, _availability_delay, _now), do: {0, 0}
-
- # Sets the current availability count and when the API will be available
- def set(
- %ShopifyAPI.AuthToken{} = token,
- available_count,
- availability_delay,
- now
- ) do
- available_at = DateTime.add(now, availability_delay, :millisecond)
-
- :ets.insert(@name, {ShopifyAPI.AuthToken.create_key(token), available_count, available_at})
- {available_count, availability_delay}
- end
-end
diff --git a/lib/shopify_api/rest.ex b/lib/shopify_api/rest.ex
deleted file mode 100644
index 51b8d646..00000000
--- a/lib/shopify_api/rest.ex
+++ /dev/null
@@ -1,90 +0,0 @@
-defmodule ShopifyAPI.REST do
- @moduledoc """
- Provides core REST actions for interacting with the Shopify API.
- Uses an `AuthToken` for authorization and request rate limiting.
-
- Please don't use this module directly. Instead prefer the higher-level modules
- implementing appropriate resource endpoints, such as `ShopifyAPI.REST.Product`
- """
-
- alias ShopifyAPI.AuthToken
- alias ShopifyAPI.JSONSerializer
- alias ShopifyAPI.REST.Request
-
- @default_pagination Application.compile_env(:shopify_api, :pagination, :auto)
-
- @doc """
- Underlying utility retrieval function. The options passed affect both the
- return value and, ultimately, the number of requests made to Shopify.
-
- ## Options
-
- `:pagination` - Can be `:none`, `:stream`, or `:auto`. Defaults to :auto
- `:auto` will block until all the pages have been retrieved and concatenated together.
- `:none` will only return the first page. You won't have access to the headers to manually
- paginate.
- `:stream` will return a `Stream`, prepopulated with the first page.
- """
- @spec get(AuthToken.t(), path :: String.t(), keyword(), keyword()) ::
- {:ok, %{required(String.t()) => [map()]}} | Enumerable.t()
- def get(%AuthToken{} = auth, path, params \\ [], options \\ []) do
- {pagination, opts} = Keyword.pop(options, :pagination, @default_pagination)
-
- case pagination do
- :none ->
- with {:ok, response} <- Request.perform(auth, :get, path, "", params, opts) do
- {:ok, fetch_body(response)}
- end
-
- :stream ->
- Request.stream(auth, path, params, opts)
-
- :auto ->
- auth
- |> Request.stream(path, params, opts)
- |> collect_results()
- end
- end
-
- @spec collect_results(Enumerable.t()) ::
- {:ok, list()} | {:error, HTTPoison.Response.t() | any()}
- defp collect_results(stream) do
- stream
- |> Enum.reduce_while({:ok, []}, fn
- {:error, _} = error, {:ok, _acc} -> {:halt, error}
- result, {:ok, acc} -> {:cont, {:ok, [result | acc]}}
- end)
- |> case do
- {:ok, results} -> {:ok, Enum.reverse(results)}
- error -> error
- end
- end
-
- @doc false
- def post(%AuthToken{} = auth, path, object \\ %{}, options \\ []) do
- with {:ok, body} <- JSONSerializer.encode(object) do
- perform_request(auth, :post, path, body, options)
- end
- end
-
- @doc false
- def put(%AuthToken{} = auth, path, object, options \\ []) do
- with {:ok, body} <- JSONSerializer.encode(object) do
- perform_request(auth, :put, path, body, options)
- end
- end
-
- @doc false
- def delete(%AuthToken{} = auth, path), do: perform_request(auth, :delete, path)
-
- defp perform_request(auth, method, path, body \\ "", options \\ []) do
- with {:ok, response} <- Request.perform(auth, method, path, body, [], options),
- response_body <- fetch_body(response) do
- {:ok, response_body}
- end
- end
-
- defp fetch_body(http_response) do
- Map.fetch!(http_response, :body)
- end
-end
diff --git a/lib/shopify_api/rest/access_scope.ex b/lib/shopify_api/rest/access_scope.ex
deleted file mode 100644
index 53f52ea7..00000000
--- a/lib/shopify_api/rest/access_scope.ex
+++ /dev/null
@@ -1,25 +0,0 @@
-defmodule ShopifyAPI.REST.AccessScope do
- @moduledoc """
- Shopify REST API Access Scope resources.
- """
-
- alias ShopifyAPI.AuthToken
- alias ShopifyAPI.REST
-
- @doc """
- Return a list of all access scopes associated with the access token.
-
- ## Example
-
- iex> ShopifyAPI.REST.AccessScope.get(auth)
- {:ok, [] = access_scopes}
- """
- def get(%AuthToken{} = auth, params \\ [], options \\ []),
- do:
- REST.get(
- auth,
- "/admin/oauth/access_scopes.json",
- params,
- Keyword.merge([pagination: :none], options)
- )
-end
diff --git a/lib/shopify_api/rest/application_charge.ex b/lib/shopify_api/rest/application_charge.ex
deleted file mode 100644
index ae2ad2f9..00000000
--- a/lib/shopify_api/rest/application_charge.ex
+++ /dev/null
@@ -1,75 +0,0 @@
-defmodule ShopifyAPI.REST.ApplicationCharge do
- @moduledoc """
- ShopifyAPI REST API ApplicationCharge resource
- """
-
- alias ShopifyAPI.AuthToken
- alias ShopifyAPI.REST
-
- @doc """
- Create an application charge.
-
- ## Example
-
- iex> ShopifyAPI.REST.ApplicationCharge.create(auth, map)
- {:ok, { "application_charge" => %{} }}
- """
- def create(
- %AuthToken{} = auth,
- %{application_charge: %{}} = application_charge
- ),
- do: REST.post(auth, "application_charges.json", application_charge)
-
- @doc """
- Get a single application charge.
-
- ## Example
-
- iex> ShopifyAPI.REST.ApplicationCharge.get(auth, integer)
- {:ok, %{} = application_charge}
- """
- def get(%AuthToken{} = auth, application_charge_id, params \\ [], options \\ []),
- do:
- REST.get(
- auth,
- "application_charges/#{application_charge_id}.json",
- params,
- Keyword.merge([pagination: :none], options)
- )
-
- @doc """
- Get a list of all application charges.
-
- ## Example
-
- iex> ShopifyAPI.REST.ApplicationCharge.all(auth)
- {:ok, [%{}, ...] = application_charges}
- """
- def all(%AuthToken{} = auth, params \\ [], options \\ []),
- do:
- REST.get(
- auth,
- "application_charges.json",
- params,
- Keyword.merge([pagination: :none], options)
- )
-
- @doc """
- Active an application charge.
-
- ## Example
-
- iex> ShopifyAPI.REST.ApplicationCharge.activate(auth)
- {:ok, %{} = application_charge}
- """
- def activate(
- %AuthToken{} = auth,
- %{application_charge: %{id: application_charge_id}} = application_charge
- ) do
- REST.post(
- auth,
- "application_charges/#{application_charge_id}/activate.json",
- application_charge
- )
- end
-end
diff --git a/lib/shopify_api/rest/application_credit.ex b/lib/shopify_api/rest/application_credit.ex
deleted file mode 100644
index 6dfdbd85..00000000
--- a/lib/shopify_api/rest/application_credit.ex
+++ /dev/null
@@ -1,53 +0,0 @@
-defmodule ShopifyAPI.REST.ApplicationCredit do
- @moduledoc """
- ShopifyAPI REST API ApplicationCredit resource
- """
-
- alias ShopifyAPI.AuthToken
- alias ShopifyAPI.REST
-
- @doc """
- Create an application credit.
-
- ## Example
-
- iex> ShopifyAPI.REST.ApplicationCredit.create(auth, map)
- {:ok, { "application_credit" => %{} }}
- """
- def create(%AuthToken{} = auth, %{application_credit: %{}} = application_credit),
- do: REST.post(auth, "application_credits.json", application_credit)
-
- @doc """
- Get a single application credit.
-
- ## Example
-
- iex> ShopifyAPI.REST.ApplicationCredit.get(auth, integer)
- {:ok, %{} = application_credit}
- """
- def get(%AuthToken{} = auth, application_credit_id, params \\ [], options \\ []),
- do:
- REST.get(
- auth,
- "application_credits/#{application_credit_id}.json",
- params,
- Keyword.merge([pagination: :none], options)
- )
-
- @doc """
- Get a list of all application credits.
-
- ## Example
-
- iex> ShopifyAPI.REST.ApplicationCredit.all(auth)
- {:ok, [%{}, ...] = application_credits}
- """
- def all(%AuthToken{} = auth, params \\ [], options \\ []),
- do:
- REST.get(
- auth,
- "application_credits.json",
- params,
- Keyword.merge([pagination: :none], options)
- )
-end
diff --git a/lib/shopify_api/rest/asset.ex b/lib/shopify_api/rest/asset.ex
deleted file mode 100644
index b8110d88..00000000
--- a/lib/shopify_api/rest/asset.ex
+++ /dev/null
@@ -1,75 +0,0 @@
-defmodule ShopifyAPI.REST.Asset do
- @moduledoc """
- ShopifyAPI REST API Theme Asset resource
- """
-
- alias ShopifyAPI.AuthToken
- alias ShopifyAPI.REST
-
- @doc """
- Get a single theme asset.
-
- ## Example
-
- iex> ShopifyAPI.REST.Asset.get(auth, integer, params)
- {:ok, %{} = asset}
- """
- def get(%AuthToken{} = auth, theme_id, params \\ [], options \\ []),
- do:
- REST.get(
- auth,
- "themes/#{theme_id}/assets.json",
- params,
- Keyword.merge([pagination: :none], options)
- )
-
- @doc """
- Return a list of all theme assets.
-
- ## Example
-
- iex> ShopifyAPI.REST.Asset.all(auth, theme_id)
- {:ok, [%{}, ...] = assets}
- """
- def all(%AuthToken{} = auth, theme_id, params \\ [], options \\ []),
- do:
- REST.get(
- auth,
- "themes/#{theme_id}/assets.json",
- params,
- Keyword.merge([pagination: :none], options)
- )
-
- @doc """
- Update a theme asset.
-
- ## Example
-
- iex> ShopifyAPI.REST.Asset.update(auth, theme_id, map)
- {:ok, %{ "asset" => %{} }}
- """
- def update(%AuthToken{} = auth, theme_id, asset),
- do: REST.put(auth, "themes/#{theme_id}/assets.json", asset)
-
- @doc """
- Delete a theme asset.
-
- ## Example
-
- iex> ShopifyAPI.REST.Asset.delete(auth, theme_id, map)
- {:ok, 200 }
- """
- def delete(%AuthToken{} = auth, theme_id, params),
- do: REST.delete(auth, "themes/#{theme_id}/assets.json?" <> URI.encode_query(params))
-
- @doc """
- Create a new theme asset.
-
- ## Example
-
- iex> ShopifyAPI.REST.Theme.create(auth, theme_id, map)
- {:ok, %{ "asset" => %{} }}
- """
- def create(%AuthToken{} = auth, theme_id, asset),
- do: update(auth, theme_id, asset)
-end
diff --git a/lib/shopify_api/rest/carrier_service.ex b/lib/shopify_api/rest/carrier_service.ex
deleted file mode 100644
index 7b75651d..00000000
--- a/lib/shopify_api/rest/carrier_service.ex
+++ /dev/null
@@ -1,73 +0,0 @@
-defmodule ShopifyAPI.REST.CarrierService do
- @moduledoc """
- ShopifyAPI REST API CarrierService resource
- """
-
- alias ShopifyAPI.AuthToken
- alias ShopifyAPI.REST
-
- @doc """
- Return a list of all carrier services.
-
- ## Example
-
- iex> ShopifyAPI.REST.CarrierService.all(auth)
- {:ok, [%{}, ...] = carrier_services}
- """
- def all(%AuthToken{} = auth, params \\ [], options \\ []),
- do:
- REST.get(auth, "carrier_services.json", params, Keyword.merge([pagination: :none], options))
-
- @doc """
- Get a single carrier service.
-
- ## Example
-
- iex> ShopifyAPI.REST.CarrierService.get(auth, string)
- {:ok, %{} = carrier_service}
- """
- def get(%AuthToken{} = auth, carrier_service_id, params \\ [], options \\ []),
- do:
- REST.get(
- auth,
- "carrier_services/#{carrier_service_id}.json",
- params,
- Keyword.merge([pagination: :none], options)
- )
-
- @doc """
- Create a carrier service.
-
- ## Example
-
- iex> ShopifyAPI.REST.CarrierService.create(auth, map)
- {:ok, %{} = carrier_service}
- """
- def create(%AuthToken{} = auth, %{carrier_service: %{}} = carrier_service),
- do: REST.post(auth, "carrier_services.json", carrier_service)
-
- @doc """
- Update a carrier service.
-
- ## Example
-
- iex> ShopifyAPI.REST.CarrierService.update(auth)
- {:ok, %{} = carrier_service}
- """
- def update(
- %AuthToken{} = auth,
- %{carrier_service: %{id: carrier_service_id}} = carrier_service
- ),
- do: REST.put(auth, "carrier_services/#{carrier_service_id}.json", carrier_service)
-
- @doc """
- Delete a carrier service.
-
- ## Example
-
- iex> ShopifyAPI.REST.CarrierService.delete(auth, string)
- {:ok, 200 }
- """
- def delete(%AuthToken{} = auth, carrier_service_id),
- do: REST.delete(auth, "carrier_services/#{carrier_service_id}.json")
-end
diff --git a/lib/shopify_api/rest/checkout.ex b/lib/shopify_api/rest/checkout.ex
deleted file mode 100644
index ebcf4f00..00000000
--- a/lib/shopify_api/rest/checkout.ex
+++ /dev/null
@@ -1,73 +0,0 @@
-defmodule ShopifyAPI.REST.Checkout do
- @moduledoc """
- Shopify REST API Checkout resources.
- """
-
- require Logger
- alias ShopifyAPI.AuthToken
- alias ShopifyAPI.REST
-
- @doc """
- Return a single checkout resource.
-
- ## Example
-
- iex> ShopifyAPI.REST.Checkout.get(auth, string)
- {:ok, %{} = checkout}
- """
- def get(%AuthToken{} = auth, checkout_token, options \\ []) do
- REST.get(
- auth,
- "checkouts/#{checkout_token}.json",
- [],
- Keyword.merge([pagination: :none], options)
- )
- end
-
- @doc """
- Create a new checkout for a customer.
-
- ## Example
-
- iex> ShopifyAPI.REST.Checkout.create(auth, map)
- {:ok, %{} = checkout}
- """
- def create(%AuthToken{} = auth, %{checkout: %{}} = checkout),
- do: REST.post(auth, "checkouts.json", checkout)
-
- @doc """
- Update an existing checkout.
-
- ## Example
-
- iex> ShopifyAPI.REST.Checkout.update(auth, map)
- {:ok, %{} = checkout}
- """
- def update(%AuthToken{} = auth, %{checkout: %{id: checkout_token}} = checkout) do
- REST.put(auth, "checkouts/#{checkout_token}.json", checkout)
- end
-
- @doc """
- Completes an existing checkout.
-
- ## Example
-
- iex> ShopifyAPI.REST.Checkout.complete(auth, string)
- {:ok, %{} = checkout}
- """
- def complete(%AuthToken{} = auth, checkout_token) do
- REST.post(auth, "checkouts/#{checkout_token}/complete.json", %{})
- end
-
- @doc """
- Gets shipping rates for a checkout.
-
- ## Example
-
- iex> ShopifyAPI.REST.Checkout.shipping_rates(auth, string)
- {:ok, %{"shipping_rates" => [] = shipping_rates}}
- """
- def shipping_rates(%AuthToken{} = auth, checkout_token) do
- REST.get(auth, "checkouts/#{checkout_token}/shipping_rates.json")
- end
-end
diff --git a/lib/shopify_api/rest/collect.ex b/lib/shopify_api/rest/collect.ex
deleted file mode 100644
index a2709934..00000000
--- a/lib/shopify_api/rest/collect.ex
+++ /dev/null
@@ -1,69 +0,0 @@
-defmodule ShopifyAPI.REST.Collect do
- @moduledoc """
- ShopifyAPI REST API Collect resource
- """
-
- alias ShopifyAPI.AuthToken
- alias ShopifyAPI.REST
-
- @doc """
- Add a product to custom collection.
-
- ## Example
-
- iex> ShopifyAPI.REST.Collect.add(auth, %{collect: collect})
- {:ok, %{} = collect}
- """
- def add(%AuthToken{} = auth, %{collect: %{}} = collect),
- do: REST.post(auth, "collects.json", collect)
-
- @doc """
- Remove a product from a custom collection.
-
- ## Example
-
- iex> ShopifyAPI.REST.Collect.delete(auth, collect_id)
- {:ok, 200}
- """
- def delete(%AuthToken{} = auth, collect_id),
- do: REST.delete(auth, "collects/#{collect_id}.json")
-
- @doc """
- Get list of all collects.
-
- ## Example
-
- iex> ShopifyAPI.REST.Collect.all(auth)
- {:ok, [%{}, ...] = collects}
- """
- def all(%AuthToken{} = auth, params \\ [], options \\ []),
- do: REST.get(auth, "collects.json", params, options)
-
- @doc """
- Get a count of collects.
-
- ## Example
-
- iex> ShopifyAPI.REST.Collect.count(auth)
- {:ok, 123 = count}
- """
- def count(%AuthToken{} = auth, params \\ [], options \\ []),
- do: REST.get(auth, "collects/count.json", params, Keyword.merge([pagination: :none], options))
-
- @doc """
- Get a specific collect.
-
- ## Example
-
- iex> ShopifyAPI.REST.Collect.get(auth, id)
- {:ok, %{} = collect}
- """
- def get(%AuthToken{} = auth, collect_id, params \\ [], options \\ []),
- do:
- REST.get(
- auth,
- "collects/#{collect_id}.json",
- params,
- Keyword.merge([pagination: :none], options)
- )
-end
diff --git a/lib/shopify_api/rest/custom_collection.ex b/lib/shopify_api/rest/custom_collection.ex
deleted file mode 100644
index d3a369d0..00000000
--- a/lib/shopify_api/rest/custom_collection.ex
+++ /dev/null
@@ -1,83 +0,0 @@
-defmodule ShopifyAPI.REST.CustomCollection do
- @moduledoc """
- Shopify REST API Custom Collection resources
- """
-
- alias ShopifyAPI.AuthToken
- alias ShopifyAPI.REST
-
- @doc """
- Get a list of all the custom collections.
-
- ## Example
- iex> ShopifyAPI.REST.CustomCollection.all(token)
- {:ok, [%{}, ...] = custom_collections}
- """
- def all(%AuthToken{} = auth, params \\ [], options \\ []),
- do: REST.get(auth, "custom_collections.json", params, options)
-
- @doc """
- Get a count of all custom collections.
-
- ## Example
- iex> ShopifyAPI.REST.CustomCollection.count(token)
- {:ok, integer}
- """
- def count(%AuthToken{} = auth, params \\ [], options \\ []),
- do:
- REST.get(
- auth,
- "custom_collections/count.json",
- params,
- Keyword.merge([pagination: :none], options)
- )
-
- @doc """
- Return a single custom collection.
-
- ## Example
- iex> ShopifyAPI.REST.CustomCollection.get(auth, string)
- {:ok, %{} = custom_collections}
- """
- def get(%AuthToken{} = auth, custom_collection_id, params \\ [], options \\ []),
- do:
- REST.get(
- auth,
- "custom_collections/#{custom_collection_id}.json",
- params,
- Keyword.merge([pagination: :none], options)
- )
-
- @doc """
- Create a custom collection.
-
- ## Example
- iex> ShopifyAPI.REST.CustomCollection.create(auth, map)
- {:ok, %{} = custom_collection}
- """
- def create(%AuthToken{} = auth, %{custom_collection: %{}} = custom_collection),
- do: REST.post(auth, "custom_collections.json", custom_collection)
-
- @doc """
- Update an existing custom collection.
-
- ## Example
- iex> ShopifyAPI.REST.CustomCollection.update(auth, string, map)
- {:ok, %{} = custom_collection}
- """
- def update(
- %AuthToken{} = auth,
- %{custom_collection: %{id: custom_collection_id}} = custom_collection
- ),
- do: REST.put(auth, "custom_collections/#{custom_collection_id}.json", custom_collection)
-
- @doc """
- Delete a custom collection.
-
- ## Example
- iex> ShopifyAPI.REST.CustomCollection.delete(auth, string)
- {:ok, %{ "response": 200 }}
- """
- def delete(%AuthToken{} = auth, custom_collection_id),
- do: REST.delete(auth, "custom_collections/#{custom_collection_id}.json")
-end
diff --git a/lib/shopify_api/rest/customer.ex b/lib/shopify_api/rest/customer.ex
deleted file mode 100644
index a2707c31..00000000
--- a/lib/shopify_api/rest/customer.ex
+++ /dev/null
@@ -1,156 +0,0 @@
-defmodule ShopifyAPI.REST.Customer do
- @moduledoc """
- Shopify REST API Customer resource
- """
-
- require Logger
- alias ShopifyAPI.AuthToken
- alias ShopifyAPI.REST
-
- @doc """
- Returns all the customers.
-
- ## Example
-
- iex> ShopifyAPI.REST.Customer.all(auth)
- {:ok, [%{}, ...] = customers}
- """
- def all(%AuthToken{} = auth, params \\ [], options \\ []),
- do: REST.get(auth, "customers.json", params, options)
-
- @doc """
- Return a single customer.
-
- ## Example
-
- iex> ShopifyAPI.REST.Customer.get(auth, integer)
- {:ok, %{} = customer}
- """
- def get(%AuthToken{} = auth, customer_id, params \\ [], options \\ []) do
- REST.get(
- auth,
- "customers/#{customer_id}.json",
- params,
- Keyword.merge([pagination: :none], options)
- )
- end
-
- @doc """
- Return a customers that match supplied query.
-
- NOTE: Not implemented.
-
- ## Example
-
- iex> ShopifyAPI.REST.Customer.getQuery()
- {:error, "Not implemented"}
- """
- def get_query do
- Logger.warning("#{__MODULE__} error, resource not implemented.")
- {:error, "Not implemented"}
- end
-
- @doc """
- Creates a customer.
-
- ## Example
-
- iex> ShopifyAPI.REST.Customer.create(auth, map)
- {:ok, %{} = customer}
- """
- def create(%AuthToken{} = auth, %{customer: %{}} = customer),
- do: REST.post(auth, "customers.json", customer)
-
- @doc """
- Updates a customer.
-
- ## Example
-
- iex> ShopifyAPI.REST.Customer.update(auth, map)
- {:ok, %{} = customer}
- """
- def update(%AuthToken{} = auth, %{customer: %{id: customer_id}} = customer),
- do: REST.put(auth, "customers/#{customer_id}.json", customer)
-
- @doc """
- Create an account activation URL.
-
- ## Example
-
- iex> ShopifyAPI.REST.Customer.CreateActivationUrl(auth, integer)
- {:ok, "" = account_activation_url}
- """
- def create_activation_url(
- %AuthToken{} = auth,
- %{customer: %{id: customer_id}} = customer
- ),
- do: REST.post(auth, "customers/#{customer_id}/account_activation.json", customer)
-
- @doc """
- Send an account invite to customer.
-
- ## Example
-
- iex> ShopifyAPI.REST.Customer.sendInvite(auth, integer)
- {:ok, %{} = customer_invite}
- """
- def send_invite(%AuthToken{} = auth, customer_id),
- do: REST.post(auth, "customers/#{customer_id}/send_invite.json")
-
- @doc """
- Delete a customer.
-
- ## Example
-
- iex> ShopifyAPI.REST.Customer.delete(auth, integer)
- {:ok, 200 }
- """
- def delete(%AuthToken{} = auth, customer_id),
- do: REST.delete(auth, "customers/#{customer_id}")
-
- @doc """
- Return a count of all customers.
-
- ## Example
-
- iex> ShopifyAPI.REST.Customer.count(auth)
- {:ok, integer}
- """
- def count(%AuthToken{} = auth, params \\ [], options \\ []),
- do:
- REST.get(auth, "customers/count.json", params, Keyword.merge([pagination: :none], options))
-
- @doc """
- Return all orders from a customer.
-
- ## Example
-
- iex> ShopifyAPI.REST.Customer.GetOrder(auth, integer)
- {:ok, [%{}, ...] = orders}
- """
- def get_orders(%AuthToken{} = auth, customer_id, params \\ [], options \\ []),
- do:
- REST.get(
- auth,
- "customers/#{customer_id}/orders.json",
- params,
- Keyword.merge([pagination: :none], options)
- )
-
- @doc """
- Search for customers that match a supplied query
-
- ## Example
-
- iex> ShopifyAPI.REST.Customer.search(auth, params)
- {:ok, [%{}, ...] = customers}
-
- The search params must be passed in as follows:
- %{"query" => "store::7020"} - returns all customers with a tag of store::7020
- %{"query" => "country:Canada"} - returns all customers with an address in Canada
- %{"query" => "Bob country:Canada"} - returns all customers with an address in Canada and the name "Bob"
- """
- # TODO (BJ) - Consider refactoring to use a KW List of options params
- def search(%AuthToken{} = auth, params, options \\ []),
- do: REST.get(auth, "customers/search.json", params, options)
-end
diff --git a/lib/shopify_api/rest/customer_address.ex b/lib/shopify_api/rest/customer_address.ex
deleted file mode 100644
index fe8ce717..00000000
--- a/lib/shopify_api/rest/customer_address.ex
+++ /dev/null
@@ -1,114 +0,0 @@
-defmodule ShopifyAPI.REST.CustomerAddress do
- @moduledoc """
- Shopify REST API Customer Address resources.
- """
-
- require Logger
- alias ShopifyAPI.AuthToken
- alias ShopifyAPI.REST
-
- @doc """
- Return a list of all addresses for a customer.
-
- ## Example
-
- iex> ShopifyAPI.REST.CustomerAddress.all(auth, string)
- {:ok, [%{}, ...] = addresses}
- """
- def all(%AuthToken{} = auth, customer_id, params \\ [], options \\ []),
- do: REST.get(auth, "customers/#{customer_id}/addresses.json", params, options)
-
- @doc """
- Return a single address for a customer.
-
- ## Example
-
- iex> ShopifyAPI.REST.CustomerAddress.get(auth, string, string)
- {:ok, %{} = customer_address}
- """
- def get(%AuthToken{} = auth, customer_id, address_id, params \\ [], options \\ []),
- do:
- REST.get(
- auth,
- "customers/#{customer_id}/addresses/#{address_id}.json",
- params,
- Keyword.merge([pagination: :none], options)
- )
-
- @doc """
- Create a new address for a customer.
-
- ## Example
-
- iex> ShopifyAPI.REST.CustomerAddress.create(auth, string, map)
- {:ok, %{} = customer_address}
- """
- def create(%AuthToken{} = auth, customer_id, %{address: %{}} = address),
- do: REST.post(auth, "customers/#{customer_id}/addresses.json", address)
-
- @doc """
- Update an existing customer address.
-
- ## Example
-
- iex> ShopifyAPI.REST.CustomerAddress.update(auth, string, string)
- {:ok, %{} = customer_address}
- """
- def update(
- %AuthToken{} = auth,
- customer_id,
- %{address: %{id: address_id}} = address
- ) do
- REST.put(
- auth,
- "customers/#{customer_id}/addresses/#{address_id}.json",
- address
- )
- end
-
- @doc """
- Delete an address from a customers address list.
-
- ## Example
-
- iex> ShopifyAPI.REST.CustomerAddress.delete(auth, string, string)
- {:ok, 200 }
- """
- def delete(%AuthToken{} = auth, customer_id, address_id),
- do: REST.delete(auth, "customers/#{customer_id}/addresses/#{address_id}.json")
-
- @doc """
- Perform bulk operations for multiple customer addresses.
-
- NOTE: Not implemented.
-
- ## Example
-
- iex> ShopifyAPI.REST.CustomerAddress.action()
- {:error, "Not implemented" }
- """
- def action do
- Logger.warning("#{__MODULE__} error, resource not implemented.")
- {:error, "Not implemented"}
- end
-
- @doc """
- Set the default address for a customer.
-
- ## Example
-
- iex> ShopifyAPI.REST.CustomerAddress.setDefault(auth, string, string)
- {:ok, %{} = customer_address}
- """
- def set_default(
- %AuthToken{} = auth,
- customer_id,
- %{address: %{id: address_id}} = address
- ) do
- REST.put(
- auth,
- "customers/#{customer_id}/addresses/#{address_id}/default.json",
- address
- )
- end
-end
diff --git a/lib/shopify_api/rest/customer_saved_search.ex b/lib/shopify_api/rest/customer_saved_search.ex
deleted file mode 100644
index 263538bd..00000000
--- a/lib/shopify_api/rest/customer_saved_search.ex
+++ /dev/null
@@ -1,98 +0,0 @@
-defmodule ShopifyAPI.REST.CustomerSavedSearch do
- @moduledoc """
- ShopifyAPI REST API CustomerSavedSearch resource
- """
-
- require Logger
-
- @doc """
- Get a list of all the customer saved searches.
-
- ## Example
-
- iex> ShopifyAPI.REST.CustomerSavedSearch.all()
- {:error, "Not implemented" }
- """
- def all do
- Logger.warning("#{__MODULE__} error, resource not implemented.")
- {:error, "Not implemented"}
- end
-
- @doc """
- Return a count of all the customer saved searches.
-
- ## Example
-
- iex> ShopifyAPI.REST.CustomerSavedSearch.count()
- {:error, "Not implemented" }
- """
- def count do
- Logger.warning("#{__MODULE__} error, resource not implemented.")
- {:error, "Not implemented"}
- end
-
- @doc """
- Get a single customer saved searches.
-
- ## Example
-
- iex> ShopifyAPI.REST.CustomerSavedSearch.get()
- {:error, "Not implemented" }
- """
- def get do
- Logger.warning("#{__MODULE__} error, resource not implemented.")
- {:error, "Not implemented"}
- end
-
- @doc """
- Retrieve all customers returned by a customer saved search.
-
- ## Example
-
- iex> ShopifyAPI.REST.CustomerSavedSearch.query()
- {:error, "Not implemented" }
- """
- def query do
- Logger.warning("#{__MODULE__} error, resource not implemented.")
- {:error, "Not implemented"}
- end
-
- @doc """
- Create a customer saved search.
-
- ## Example
-
- iex> ShopifyAPI.REST.CustomerSavedSearch.create()
- {:error, "Not implemented" }
- """
- def create do
- Logger.warning("#{__MODULE__} error, resource not implemented.")
- {:error, "Not implemented"}
- end
-
- @doc """
- Update a customer saved search.
-
- ## Example
-
- iex> ShopifyAPI.REST.CustomerSavedSearch.update()
- {:error, "Not implemented" }
- """
- def update do
- Logger.warning("#{__MODULE__} error, resource not implemented.")
- {:error, "Not implemented"}
- end
-
- @doc """
- Delete a customer saved search.
-
- ## Example
-
- iex> ShopifyAPI.REST.CustomerSavedSearch.delete()
- {:error, "Not implemented" }
- """
- def delete do
- Logger.warning("#{__MODULE__} error, resource not implemented.")
- {:error, "Not implemented"}
- end
-end
diff --git a/lib/shopify_api/rest/discount_code.ex b/lib/shopify_api/rest/discount_code.ex
deleted file mode 100644
index 152d3242..00000000
--- a/lib/shopify_api/rest/discount_code.ex
+++ /dev/null
@@ -1,146 +0,0 @@
-defmodule ShopifyAPI.REST.DiscountCode do
- @moduledoc """
- ShopifyAPI REST API DiscountCode resource
- """
-
- alias ShopifyAPI.AuthToken
- alias ShopifyAPI.REST
-
- @doc """
- Create a discount code.
-
- ## Example
-
- iex> ShopifyAPI.REST.DiscountCode.create(auth, map)
- {:ok, %{} = discount_code}
- """
- def create(
- %AuthToken{} = auth,
- %{discount_code: %{price_rule_id: price_rule_id}} = discount_code
- ) do
- REST.post(auth, "price_rules/#{price_rule_id}/discount_codes.json", discount_code)
- end
-
- @doc """
- Update an existing discount code.
-
- ## Example
-
- iex> ShopifyAPI.REST.DiscountCode.update(auth, integer, map)
- {:ok, %{} = discount_code}
- """
- def update(
- %AuthToken{} = auth,
- price_rule_id,
- %{discount_code: %{id: discount_code_id}} = discount_code
- ) do
- REST.put(
- auth,
- "price_rules/#{price_rule_id}/discount_codes/#{discount_code_id}.json",
- discount_code
- )
- end
-
- @doc """
- Return all the discount codes.
-
- ## Example
-
- iex> ShopifyAPI.REST.DiscountCode.all(auth, integer)
- {:ok, [%{}, ...] = discount_codes}
- """
- def all(%AuthToken{} = auth, price_rule_id, params \\ [], options \\ []) do
- REST.get(auth, "price_rules/#{price_rule_id}/discount_codes.json", params, options)
- end
-
- @doc """
- Get a single discount code.
-
- ## Example
-
- iex> ShopifyAPI.REST.DiscountCode.get(auth, integer, integer)
- {:ok, %{} = discount_code}
- """
- def get(%AuthToken{} = auth, price_rule_id, discount_code_id, params \\ [], options \\ []),
- do:
- REST.get(
- auth,
- "price_rules/#{price_rule_id}/discount_codes/#{discount_code_id}.json",
- params,
- Keyword.merge([pagination: :none], options)
- )
-
- @doc """
- Retrieve the location of a discount code.
-
- ## Example
-
- iex> ShopifyAPI.REST.DiscountCode.query(auth, string)
- {:ok, "" = location}
- """
- def query(%AuthToken{} = auth, coupon_code, params \\ [], options \\ []),
- do:
- REST.get(
- auth,
- "discount_codes/lookup.json",
- Keyword.merge([code: coupon_code], params),
- Keyword.merge([pagination: :none], options)
- )
-
- @doc """
- Delete a discount code.
-
- ## Example
-
- iex> ShopifyAPI.REST.DiscountCode.delete(auth, integer, integer)
- {:ok, 204 }}
- """
- def delete(%AuthToken{} = auth, price_rule_id, discount_code_id),
- do: REST.delete(auth, "price_rules/#{price_rule_id}/discount_codes/#{discount_code_id}.json")
-
- @doc """
- Creates a discount code creation job.
-
- ## Example
-
- iex> ShopifyAPI.REST.DiscountCode.createBatch(auth, list)
- {:ok, [%{}, ...] = discount_codes}
- """
- def create_batch(auth, price_rule_id, %{discount_codes: []} = discount_codes),
- do: REST.post(auth, "price_rules/#{price_rule_id}/batch.json", discount_codes)
-
- @doc """
- Get a discount code creation job.
-
- ## Example
-
- iex> ShopifyAPI.REST.DiscountCode.get_batch(auth, integer, integer)
- {:ok, %{} = discount_code_creation}
- """
- def get_batch(%AuthToken{} = auth, price_rule_id, batch_id, params \\ [], options \\ []),
- do:
- REST.get(
- auth,
- "price_rules/#{price_rule_id}/batch/#{batch_id}.json",
- params,
- Keyword.merge([pagination: :none], options)
- )
-
- @doc """
- Return a list of discount codes for a discount code creation job.
-
- ## Example
-
- iex> ShopifyAPI.REST.DiscountCode.all_batch(auth, integer, integer)
- {:ok, [] = discount_codes}
- """
- def(all_batch(%AuthToken{} = auth, price_rule_id, batch_id, params \\ [], options \\ []),
- do:
- REST.get(
- auth,
- "price_rules/#{price_rule_id}/batch/#{batch_id}/discount_code.json",
- params,
- Keyword.merge([pagination: :none], options)
- )
- )
-end
diff --git a/lib/shopify_api/rest/draft_order.ex b/lib/shopify_api/rest/draft_order.ex
deleted file mode 100644
index da02a570..00000000
--- a/lib/shopify_api/rest/draft_order.ex
+++ /dev/null
@@ -1,154 +0,0 @@
-defmodule ShopifyAPI.REST.DraftOrder do
- @moduledoc """
- ShopifyAPI REST API DraftOrder resource
-
- This resource contains methods for working with draft orders in Shopify
- """
- alias ShopifyAPI.AuthToken
- alias ShopifyAPI.REST
-
- @doc """
- Create a new draft order with the provided attributes
-
- ## Example
-
- iex> ShopifyAPI.REST.DraftOrder.create(auth_token, %{draft_order: %{}})
- {:ok, %{"draft_order" => %{...}}}
- """
- def create(%AuthToken{} = auth, %{draft_order: %{}} = draft_order),
- do: REST.post(auth, "draft_orders.json", draft_order)
-
- @doc """
- Update a draft order
-
- ## Example
-
- iex> ShopifyAPI.REST.DraftOrder.update(auth_token, %{draft_order: %{}})
- {:ok, %{...} = draft_order}
-
- To add a note to a draft order:
- %{
- draft_order: %{
- id: 994118539,
- note: "Customer contacted us about a custom engraving on the item"
- }
- }
- """
- def update(%AuthToken{} = auth, %{draft_order: %{id: draft_order_id}} = draft_order),
- do: REST.put(auth, "draft_orders/#{draft_order_id}.json", draft_order)
-
- @doc """
- Retrieve a list of all draft orders
-
- ## Example
-
- iex> ShopifyAPI.REST.DraftOrder.all(auth)
- {:ok, [%{}, ...] = draft_orders}
- """
- def all(%AuthToken{} = auth, params \\ [], options \\ []),
- do: REST.get(auth, "draft_orders.json", params, options)
-
- @doc """
- Retrieve a specific draft order
-
- ## Example
-
- iex> ShopifyAPI.REST.DraftOrder.get(auth, integer)
- {:ok, %{...} = draft_order}
- """
- def get(%AuthToken{} = auth, draft_order_id, params \\ [], options \\ []),
- do:
- REST.get(
- auth,
- "draft_orders/#{draft_order_id}.json",
- params,
- Keyword.merge([pagination: :none], options)
- )
-
- @doc """
- Retrieve a count of all draft orders
-
- ## Example
-
- iex> ShopifyAPI.REST.DraftOrder.count(auth)
- {:ok, %{count: integer}}
- """
- def count(%AuthToken{} = auth, params \\ [], options \\ []),
- do:
- REST.get(
- auth,
- "draft_orders/count.json",
- params,
- Keyword.merge([pagination: :none], options)
- )
-
- @doc """
- Send an invoice for a draft order
-
- ## Example
-
- iex> ShopifyAPI.REST.DraftOrder.send_invoice(auth, %{draft_order_invoice: %{}})
- {:ok, %{...} = draft_order_invoice}
-
- To send the default invoice:
- %{
- draft_order_invoice: %{}
- }
-
- To send a customized invoice:
- %{
- draft_order_invoice: %{
- to: "first@example.com",
- from: "steve@apple.com",
- bcc: [
- "steve@apple.com"
- ],
- subject: "Apple Computer Invoice",
- custom_message: "Thank you for ordering!"
- }
- }
- """
- def send_invoice(
- %AuthToken{} = auth,
- draft_order_id,
- %{draft_order_invoice: %{}} = draft_order_invoice
- ),
- do:
- REST.post(
- auth,
- "draft_orders/#{draft_order_id}/send_invoice.json",
- draft_order_invoice
- )
-
- @doc """
- Delete a draft order
-
- ## Example
-
- iex> ShopifyAPI.REST.DraftOrder.delete(auth, integer)
- {:ok, %{}}
- """
- def delete(%AuthToken{} = auth, draft_order_id),
- do: REST.delete(auth, "draft_orders/#{draft_order_id}.json")
-
- @doc """
- Complete a draft order
-
- ## Example
-
- To complete a draft order, marking it as paid:
- iex> ShopifyAPI.REST.DraftOrder.complete(auth, integer)
-
- To complete a draft order, marking it as pending:
- iex> ShopifyAPI.REST.DraftOrder.complete(auth, integer, %{"payment_pending" => true})
-
- {:ok, %{...} = draft_order}
- """
- def complete(%AuthToken{} = auth, draft_order_id, params \\ %{}),
- do:
- REST.put(
- auth,
- "draft_orders/#{draft_order_id}/complete.json?" <> URI.encode_query(params),
- %{}
- )
-end
diff --git a/lib/shopify_api/rest/event.ex b/lib/shopify_api/rest/event.ex
deleted file mode 100644
index 35be39ed..00000000
--- a/lib/shopify_api/rest/event.ex
+++ /dev/null
@@ -1,49 +0,0 @@
-defmodule ShopifyAPI.REST.Event do
- @moduledoc """
- ShopifyAPI REST API Event resource
-
- More via: https://help.shopify.com/api/reference/events/event#index
- """
-
- alias ShopifyAPI.AuthToken
- alias ShopifyAPI.REST
-
- @doc """
- Return a list of all Events.
-
- ## Example
-
- iex> ShopifyAPI.REST.Event.all(auth)
- {:ok, [%{}, ...] = events}
- """
- def all(%AuthToken{} = auth, params \\ [], options \\ []),
- do: REST.get(auth, "events.json", params, options)
-
- @doc """
- Get a single event.
-
- ## Example
-
- iex> ShopifyAPI.REST.Event.get(auth, integer)
- {:ok, %{} = event}
- """
- def get(%AuthToken{} = auth, event_id, params \\ [], options \\ []),
- do:
- REST.get(
- auth,
- "events/#{event_id}.json",
- params,
- Keyword.merge([pagination: :none], options)
- )
-
- @doc """
- Get a count of all Events.
-
- ## Example
-
- iex> ShopifyAPI.REST.Event.count(auth)
- {:ok, integer = events}
- """
- def count(%AuthToken{} = auth, params \\ [], options \\ []),
- do: REST.get(auth, "events/count.json", params, Keyword.merge([pagination: :none], options))
-end
diff --git a/lib/shopify_api/rest/fulfillment.ex b/lib/shopify_api/rest/fulfillment.ex
deleted file mode 100644
index be403e83..00000000
--- a/lib/shopify_api/rest/fulfillment.ex
+++ /dev/null
@@ -1,128 +0,0 @@
-defmodule ShopifyAPI.REST.Fulfillment do
- @moduledoc """
- ShopifyAPI REST API Fulfillment resource
- """
-
- alias ShopifyAPI.AuthToken
- alias ShopifyAPI.REST
-
- @doc """
- Return a list of all fulfillments.
-
- ## Example
-
- iex> ShopifyAPI.REST.Fulfillment.all(auth, string)
- {:ok, [%{}, ...] = fulfillments}
- """
- def all(%AuthToken{} = auth, order_id, params \\ [], options \\ []),
- do: REST.get(auth, "orders/#{order_id}/fulfillments.json", params, options)
-
- @doc """
- Return a count of all fulfillments.
-
- ## Example
-
- iex> ShopifyAPI.REST.Fulfillment.count(auth, string)
- {:ok, integer}
- """
- def count(%AuthToken{} = auth, order_id, params \\ [], options \\ []),
- do:
- REST.get(
- auth,
- "orders/#{order_id}/fulfillments/count.json",
- params,
- Keyword.merge([pagination: :none], options)
- )
-
- @doc """
- Get a single fulfillment.
-
- ## Example
-
- iex> ShopifyAPI.REST.Fulfillment.get(auth, string, string)
- {:ok, %{} = fulfillment}
- """
- def get(%AuthToken{} = auth, order_id, fulfillment_id, params \\ [], options \\ []),
- do:
- REST.get(
- auth,
- "orders/#{order_id}/fulfillments/#{fulfillment_id}.json",
- params,
- Keyword.merge([pagination: :none], options)
- )
-
- @doc """
- Create a new fulfillment.
-
- ## Example
-
- iex> ShopifyAPI.REST.Fulfillment.create(auth, string, map)
- {:ok, %{} = fulfillment}
- """
- def create(%AuthToken{} = auth, order_id, %{fulfillment: %{}} = fulfillment, options \\ []) do
- REST.post(auth, "orders/#{order_id}/fulfillments.json", fulfillment, options)
- end
-
- @doc """
- Update an existing fulfillment.
-
- ## Example
-
- iex> ShopifyAPI.REST.Fulfillment.update(auth, string, map)
- {:ok, %{} = fulfillment}
- """
- def update(
- %AuthToken{} = auth,
- order_id,
- %{fulfillment: %{id: fulfillment_id}} = fulfillment
- ),
- do: REST.put(auth, "orders/#{order_id}/fulfillments/#{fulfillment_id}.json", fulfillment)
-
- @doc """
- Complete a fulfillment.
-
- ## Example
-
- iex> ShopifyAPI.REST.Fulfillment.complete(auth, string, map)
- {:ok, %{} = fulfillment}
- """
- def complete(%AuthToken{} = auth, order_id, %{fulfillment: %{id: fulfillment_id}} = fulfillment) do
- REST.post(
- auth,
- "orders/#{order_id}/fulfillments/#{fulfillment_id}/complete.json",
- fulfillment
- )
- end
-
- @doc """
- Open a fulfillment.
-
- ## Example
-
- iex> ShopifyAPI.REST.Fulfillment.open(auth, string)
- {:ok, %{} = fulfillment}
- """
- def open(%AuthToken{} = auth, order_id, %{fulfillment: %{id: fulfillment_id}} = fulfillment) do
- REST.post(
- auth,
- "orders/#{order_id}/fulfillments/#{fulfillment_id}/open.json",
- fulfillment
- )
- end
-
- @doc """
- Cancel a fulfillment.
-
- ## Example
-
- iex> ShopifyAPI.REST.Fulfillment.cancel(auth, string)
- {:ok, %{} = fulfillment}
- """
- def cancel(%AuthToken{} = auth, order_id, %{fulfillment: %{id: fulfillment_id}} = fulfillment) do
- REST.post(
- auth,
- "orders/#{order_id}/fulfillments/#{fulfillment_id}/cancel.json",
- fulfillment
- )
- end
-end
diff --git a/lib/shopify_api/rest/fulfillment_event.ex b/lib/shopify_api/rest/fulfillment_event.ex
deleted file mode 100644
index ed74c4c3..00000000
--- a/lib/shopify_api/rest/fulfillment_event.ex
+++ /dev/null
@@ -1,77 +0,0 @@
-defmodule ShopifyAPI.REST.FulfillmentEvent do
- @moduledoc """
- ShopifyAPI REST API FulfillmentEvent resource
- """
-
- alias ShopifyAPI.AuthToken
- alias ShopifyAPI.REST
-
- @doc """
- Return a list of all fulfillment events.
-
- ## Example
-
- iex> ShopifyAPI.REST.FulfillmentEvent.all(auth, string, string)
- {:ok, [] = fulfillment_events}
- """
- def all(%AuthToken{} = auth, order_id, fulfillment_id, params \\ [], options \\ []),
- do:
- REST.get(
- auth,
- "orders/#{order_id}/fulfillments/#{fulfillment_id}/events.json",
- params,
- Keyword.merge([pagination: :none], options)
- )
-
- @doc """
- Get a single fulfillment event.
-
- ## Example
-
- iex> ShopifyAPI.REST.FulfillmentEvent.get(auth, string, string, string)
- {:ok, %{} = fulfillment_event}
- """
- def get(%AuthToken{} = auth, order_id, fulfillment_id, event_id, params \\ [], options \\ []),
- do:
- REST.get(
- auth,
- "orders/#{order_id}/fulfillments/#{fulfillment_id}/events/#{event_id}.json",
- params,
- Keyword.merge([pagination: :none], options)
- )
-
- @doc """
- Create a new fulfillment event.
-
- ## Example
-
- iex> ShopifyAPI.REST.FulfillmentEvent.post(auth, map)
- {:ok, %{} = fulfillment_event}
- """
- def post(
- %AuthToken{} = auth,
- order_id,
- %{fulfillment_event: %{id: fulfillment_id}} = fulfillment_event
- ) do
- REST.post(
- auth,
- "orders/#{order_id}/fulfillments/#{fulfillment_id}/events.json",
- fulfillment_event
- )
- end
-
- @doc """
- Delete a fulfillment event.
-
- ## Example
-
- iex> ShopifyAPI.REST.FulfillmentEvent.delete(auth, string, string, string)
- {:ok, 200 }
- """
- def delete(%AuthToken{} = auth, order_id, fulfillment_id, event_id) do
- REST.delete(
- auth,
- "orders/#{order_id}/fulfillments/#{fulfillment_id}/events/#{event_id}.json"
- )
- end
-end
diff --git a/lib/shopify_api/rest/fulfillment_service.ex b/lib/shopify_api/rest/fulfillment_service.ex
deleted file mode 100644
index fac4a39d..00000000
--- a/lib/shopify_api/rest/fulfillment_service.ex
+++ /dev/null
@@ -1,79 +0,0 @@
-defmodule ShopifyAPI.REST.FulfillmentService do
- @moduledoc """
- ShopifyAPI REST API FulfillmentService resource
- """
-
- alias ShopifyAPI.AuthToken
- alias ShopifyAPI.REST
-
- @doc """
- Return a list of all the fulfillment services.
-
- ## Example
-
- iex> ShopifyAPI.REST.FulfillmentService.all(auth)
- {:ok, [] = fulfillment_services}
- """
- def all(%AuthToken{} = auth, params \\ [], options \\ []),
- do:
- REST.get(
- auth,
- "fulfillment_services.json",
- params,
- Keyword.merge([pagination: :none], options)
- )
-
- @doc """
- Get a single fulfillment service.
-
- ## Example
-
- iex> ShopifyAPI.REST.FulfillmentService.get(auth, string)
- {:ok, %{} = fulfillment_service}
- """
- def get(%AuthToken{} = auth, fulfillment_service_id, params \\ [], options \\ []),
- do:
- REST.get(
- auth,
- "fulfillment_services/#{fulfillment_service_id}.json",
- params,
- Keyword.merge([pagination: :none], options)
- )
-
- @doc """
- Create a new fulfillment service.
-
- ## Example
-
- iex> ShopifyAPI.REST.FulfillmentService.create(auth)
- {:ok, %{} = fulfillment_service}
- """
- def create(%AuthToken{} = auth, %{fulfillment_service: %{}} = fulfillment_service),
- do: REST.post(auth, "fulfillment_services.json", fulfillment_service)
-
- @doc """
- Update an existing fulfillment service.
-
- ## Example
-
- iex> ShopifyAPI.REST.FulfillmentService.update(auth)
- {:ok, %{} = fulfillment_service}
- """
- def update(
- %AuthToken{} = auth,
- %{fulfillment_service: %{id: fulfillment_service_id}} = fulfillment_service
- ) do
- REST.put(auth, "fulfillment_services/#{fulfillment_service_id}.json", fulfillment_service)
- end
-
- @doc """
- Delete a fulfillment service.
-
- ## Example
-
- iex> ShopifyAPI.REST.FulfillmentService.delete(auth, string)
- {:ok, 200 }
- """
- def delete(%AuthToken{} = auth, fulfillment_service_id),
- do: REST.delete(auth, "fulfillment_services/#{fulfillment_service_id}.json")
-end
diff --git a/lib/shopify_api/rest/inventory_item.ex b/lib/shopify_api/rest/inventory_item.ex
deleted file mode 100644
index df1b207f..00000000
--- a/lib/shopify_api/rest/inventory_item.ex
+++ /dev/null
@@ -1,51 +0,0 @@
-defmodule ShopifyAPI.REST.InventoryItem do
- @moduledoc """
- ShopifyAPI REST API InventoryItem resource
- """
- require Logger
- alias ShopifyAPI.AuthToken
- alias ShopifyAPI.REST
-
- @doc """
- Return a list of inventory items.
-
- NOTE: Not implemented.
-
- ## Example
-
- iex> ShopifyAPI.REST.InventoryItem.all(auth)
- {:error, "Not implemented" }
- """
- def all do
- Logger.warning("#{__MODULE__} error, resource not implemented.")
- {:error, "Not implemented"}
- end
-
- @doc """
- Get a single inventory item by its ID.
-
- ## Example
-
- iex> ShopifyAPI.REST.InventoryItem.get(auth, integer)
- {:ok, %{} = inventory_item}
- """
- def get(%AuthToken{} = auth, inventory_item_id, params \\ [], options \\ []),
- do:
- REST.get(
- auth,
- "inventory_items/#{inventory_item_id}.json",
- params,
- Keyword.merge([pagination: :none], options)
- )
-
- @doc """
- Update an existing inventory item.
-
- ## Example
-
- iex> ShopifyAPI.REST.InventoryItem.update(auth, map)
- {:ok, %{} = inventory_item}
- """
- def update(%AuthToken{} = auth, %{inventory_item: %{id: inventory_item_id}} = inventory_item),
- do: REST.put(auth, "inventory_items/#{inventory_item_id}.json", inventory_item)
-end
diff --git a/lib/shopify_api/rest/inventory_level.ex b/lib/shopify_api/rest/inventory_level.ex
deleted file mode 100644
index 0859499e..00000000
--- a/lib/shopify_api/rest/inventory_level.ex
+++ /dev/null
@@ -1,50 +0,0 @@
-defmodule ShopifyAPI.REST.InventoryLevel do
- @moduledoc """
- ShopifyAPI REST API InventoryLevel resource
- """
- alias ShopifyAPI.AuthToken
- alias ShopifyAPI.REST
-
- @doc """
- Return a list of inventory levels.
-
- ## Example
-
- iex> ShopifyAPI.REST.InventoryLevel.all(auth)
- {:ok, [%{}, ...] = inventory_level}
- """
- def all(%AuthToken{} = auth, params \\ [], options \\ []),
- do: REST.get(auth, "inventory_levels.json", params, options)
-
- @doc """
- Sets the inventory level for an inventory item at a location.
-
- ## Example
-
- iex> ShopifyAPI.REST.InventoryLevel.set(auth, %{ inventory_level: %{inventory_item_id: integer, location_id: integer, available: integer}})
- {:ok, [] = inventory_level}
- """
- def set(
- %AuthToken{} = auth,
- %{
- inventory_level: %{inventory_item_id: _, location_id: _, available: _} = inventory_level
- }
- ) do
- REST.post(auth, "inventory_levels/set.json", inventory_level)
- end
-
- @doc """
- Delete an inventory level of an inventory item at a location.
-
- ## Example
-
- iex> ShopifyAPI.REST.InventoryLevel.delete(auth, integer, integer)
- {:ok, 200 }}
- """
- def delete(%AuthToken{} = auth, inventory_item_id, location_id) do
- REST.delete(
- auth,
- "inventory_levels.json?inventory_item_id=#{inventory_item_id}&location_id=#{location_id}"
- )
- end
-end
diff --git a/lib/shopify_api/rest/location.ex b/lib/shopify_api/rest/location.ex
deleted file mode 100644
index 5e8932c7..00000000
--- a/lib/shopify_api/rest/location.ex
+++ /dev/null
@@ -1,57 +0,0 @@
-defmodule ShopifyAPI.REST.Location do
- @moduledoc """
- ShopifyAPI REST API Location resource
- """
- require Logger
- alias ShopifyAPI.AuthToken
- alias ShopifyAPI.REST
-
- @doc """
- Return a list of locations.
-
- ## Example
-
- iex> ShopifyAPI.REST.Location.all(auth)
- {:ok, [] = locations}
- """
- def all(%AuthToken{} = auth, params \\ [], options \\ []),
- do: REST.get(auth, "locations.json", params, Keyword.merge([pagination: :none], options))
-
- @doc """
- Return a single location.
-
- ## Example
-
- iex> ShopifyAPI.REST.Location.get(auth, integer)
- {:ok, %{} = location}
- """
- def get(%AuthToken{} = auth, location_id, params \\ [], options \\ []),
- do:
- REST.get(
- auth,
- "locations/#{location_id}.json",
- params,
- Keyword.merge([pagination: :none], options)
- )
-
- @doc """
- Return a count of locations.
-
- ## Example
-
- iex> ShopifyAPI.REST.Location.count(auth)
- {:ok, integer = count}
- """
- def count(%AuthToken{} = auth, params \\ []), do: REST.get(auth, "locations/count.json", params)
-
- @doc """
- Returns a list of inventory levels for a location.
-
- ## Example
-
- iex> ShopifyAPI.REST.Location.inventory_levels(auth, integer)
- {:ok, %{} = inventory_levels}
- """
- def inventory_levels(%AuthToken{} = auth, location_id, params \\ [], options \\ []),
- do: REST.get(auth, "locations/#{location_id}/inventory_levels.json", params, options)
-end
diff --git a/lib/shopify_api/rest/marketing_event.ex b/lib/shopify_api/rest/marketing_event.ex
deleted file mode 100644
index 08f93c62..00000000
--- a/lib/shopify_api/rest/marketing_event.ex
+++ /dev/null
@@ -1,108 +0,0 @@
-defmodule ShopifyAPI.REST.MarketingEvent do
- @moduledoc """
- ShopifyAPI REST API MarketingEvent resource
- """
-
- require Logger
- alias ShopifyAPI.AuthToken
- alias ShopifyAPI.REST
-
- @doc """
- Return a list of all marketing events.
-
- ## Example
-
- iex> ShopifyAPI.REST.MarketingEvent.all(auth)
- {:ok, [] = marketing_events}
- """
- def all(%AuthToken{} = auth, params \\ [], options \\ []),
- do: REST.get(auth, "marketing_events.json", params, options)
-
- @doc """
- Get a count of all marketing events.
-
- ## Example
-
- iex> ShopifyAPI.REST.MarketingEvent.count(auth)
- {:ok, integer = count}
- """
- def count(%AuthToken{} = auth, params \\ [], options \\ []),
- do:
- REST.get(
- auth,
- "marketing_events/count.json",
- params,
- Keyword.merge([pagination: :none], options)
- )
-
- @doc """
- Get a single marketing event.
-
- ## Example
-
- iex> ShopifyAPI.REST.MarketingEvent.get(auth, integer)
- {:ok, %{} = marketing_event}
- """
- def get(%AuthToken{} = auth, marketing_event_id, params \\ [], options \\ []),
- do:
- REST.get(
- auth,
- "marketing_events/#{marketing_event_id}.json",
- params,
- Keyword.merge([pagination: :none], options)
- )
-
- @doc """
- Create a marketing event.
-
- ## Example
-
- iex> ShopifyAPI.REST.MarketingEvent.create(auth, map)
- {:ok, %{} = marketing_event}
- """
- def create(
- %AuthToken{} = auth,
- %{marketing_event: %{id: marketing_event_id}} = marketing_event
- ),
- do: REST.post(auth, "marketing_events/#{marketing_event_id}.json", marketing_event)
-
- @doc """
- Update a marketing event.
-
- ## Example
-
- iex> ShopifyAPI.REST.MarketingEvent.update(auth, map)
- {:ok, %{} = marketing_event}
- """
- def update(
- %AuthToken{} = auth,
- %{marketing_event: %{id: marketing_event_id}} = marketing_event
- ),
- do: REST.put(auth, "marketing_events/#{marketing_event_id}.json", marketing_event)
-
- @doc """
- Delete a marketing event.
-
- ## Example
-
- iex> ShopifyAPI.REST.MarketingEvent.delete(auth)
- {:ok, 200 }
- """
- def delete(%AuthToken{} = auth, marketing_event_id),
- do: REST.delete(auth, "marketing_events/#{marketing_event_id}.json")
-
- @doc """
- Creates a marketing engagements on a marketing event.
-
- NOTE: Not implemented.
-
- ## Example
-
- iex> ShopifyAPI.REST.MarketingEvent.create_engagement()
- {:error, "Not implemented" }
- """
- def create_engagement do
- Logger.warning("#{__MODULE__} error, resource not implemented.")
- {:error, "Not implemented"}
- end
-end
diff --git a/lib/shopify_api/rest/metafield.ex b/lib/shopify_api/rest/metafield.ex
deleted file mode 100644
index 040d17b1..00000000
--- a/lib/shopify_api/rest/metafield.ex
+++ /dev/null
@@ -1,149 +0,0 @@
-defmodule ShopifyAPI.REST.Metafield do
- @enforce_keys [:key, :namespace, :value, :value_type]
- defstruct key: "",
- namespace: "",
- value: 0,
- value_type: ""
-
- @moduledoc """
- ShopifyAPI REST API Metafield resource
- """
-
- alias ShopifyAPI.AuthToken
- alias ShopifyAPI.REST
-
- @doc """
- Get a list of all metafields that belong to a resource.
-
- ## Example
-
- iex> ShopifyAPI.REST.Metafields.all(auth)
- {:ok, [] = metafields }}
-
- iex> ShopifyAPI.REST.Metafields.all(token, atom, integer)
- {:ok, [] = metafields }}
- """
- # TODO(BJ) - add options without defaults conflicting
- def all(%AuthToken{} = auth, params \\ []),
- do: REST.get(auth, "metafields.json", params)
-
- def all(%AuthToken{} = auth, type, resource_id, params \\ []),
- do: REST.get(auth, resource_path(type, resource_id), params)
-
- @doc """
- Return a count of metafields that belong to a Shop resource.
-
- ## Example
-
- iex> ShopifyAPI.REST.Metafields.count(token)
- {:ok, integer = count}
- """
- # TODO(BJ) - add options without defaults conflicting
- def count(%AuthToken{} = auth, params \\ []),
- do: REST.get(auth, "metafields/count.json", params, pagination: :none)
-
- @doc """
- Return a count that belong to a resource and its metafields.
-
- ## Example
-
- iex> ShopifyAPI.REST.Metafields.count(auth, atom, integer)
- {:ok, integer = count}
- """
- def count(%AuthToken{} = auth, type, resource_id, params \\ []),
- do: REST.get(auth, resource_path(type, resource_id), params, pagination: :none)
-
- @doc """
- Return a list of metafields for a resource by it's ID.
-
- ## Example
-
- iex> ShopifyAPI.REST.Metafields.get(auth, atom, integer)
- {:ok, [] = metafields}
- """
- def get(%AuthToken{} = auth, type, resource_id, params \\ [], options \\ []),
- do:
- REST.get(
- auth,
- resource_path(type, resource_id),
- params,
- Keyword.merge([pagination: :none], options)
- )
-
- @doc """
- Creates a new metafield.
-
- ## Example
-
- iex> ShopifyAPI.REST.Metafields.create(auth, map)
- {:ok, %{} = metafield}
- """
- def create(%AuthToken{} = auth, metafield), do: REST.post(auth, "metafields.json", metafield)
-
- @doc """
- Creates a new metafield for a resource.
-
- ## Example
-
- iex> ShopifyAPI.REST.Metafields.create(auth, atom, integer, map)
- {:ok, %{} = metafield}
- """
- def create(%AuthToken{} = auth, type, resource_id, metafield),
- do: REST.post(auth, resource_path(type, resource_id), metafield)
-
- @doc """
- Update a metafield.
-
- ## Example
-
- iex> ShopifyAPI.REST.Metafields.update(auth, atom, integer, map)
- {:ok, %{} = metafield}
- """
- def update(%AuthToken{} = auth, type, resource_id, %{metafield: %{id: id}} = metafield),
- do: REST.put(auth, resource_path(type, resource_id, id), metafield)
-
- @doc """
- Delete a metafield by its Metafield ID.
-
- ## Example
-
- iex> ShopifyAPI.REST.Metafields.update(auth, integer)
- {:ok, %{} = metafield}
- """
- def delete(%AuthToken{} = auth, metafield_id),
- do: REST.delete(auth, resource_path(:metafield, metafield_id))
-
- ## Private
-
- defp resource_path(resource, id) when is_binary(resource),
- do: resource_path(String.to_existing_atom(resource), id)
-
- defp resource_path(:blog, blog_id), do: "blogs/#{blog_id}/metafields.json"
-
- defp resource_path(:collection, collection_id),
- do: "collections/#{collection_id}/metafields.json"
-
- defp resource_path(:customer, customer_id), do: "customers/#{customer_id}/metafields.json"
- defp resource_path(:draft_order, draft_id), do: "draft_orders/#{draft_id}/metafields.json"
- defp resource_path(:metafield, metafield_id), do: "metafields/#{metafield_id}.json"
- defp resource_path(:order, order_id), do: "orders/#{order_id}/metafields.json"
- defp resource_path(:page, page_id), do: "pages/#{page_id}/metafields.json"
- defp resource_path(:product, product_id), do: "products/#{product_id}/metafields.json"
- defp resource_path(:variant, variant_id), do: "variants/#{variant_id}/metafields.json"
-
- defp resource_path(resource, id, meta_id) when is_binary(resource),
- do: resource_path(String.to_existing_atom(resource), id, meta_id)
-
- defp resource_path(:blog, blog_id, id), do: "blogs/#{blog_id}/metafields/#{id}.json"
-
- defp resource_path(:collection, collection_id, id),
- do: "collections/#{collection_id}/metafields/#{id}.json"
-
- defp resource_path(:draft_order, draft_id, id),
- do: "draft_orders/#{draft_id}/metafields/#{id}.json"
-
- defp resource_path(:order, order_id, id), do: "orders/#{order_id}/metafields/#{id}.json"
- defp resource_path(:page, page_id, id), do: "pages/#{page_id}/metafields/#{id}.json"
- defp resource_path(:product, product_id, id), do: "products/#{product_id}/metafields/#{id}.json"
- defp resource_path(:variant, variant_id, id), do: "variants/#{variant_id}/metafields/#{id}.json"
-end
diff --git a/lib/shopify_api/rest/order.ex b/lib/shopify_api/rest/order.ex
deleted file mode 100644
index dc086440..00000000
--- a/lib/shopify_api/rest/order.ex
+++ /dev/null
@@ -1,86 +0,0 @@
-defmodule ShopifyAPI.REST.Order do
- @moduledoc """
- """
- alias ShopifyAPI.AuthToken
- alias ShopifyAPI.REST
-
- @shopify_per_page_max 250
-
- @doc """
- Return a single Order.
- """
- def get(%AuthToken{} = auth, order_id, params \\ [], options \\ []),
- do:
- REST.get(
- auth,
- "orders/#{order_id}.json",
- params,
- Keyword.merge([pagination: :none], options)
- )
-
- @doc """
- Return all of a shops Orders filtered by query parameters.
-
- iex> ShopifyAPI.REST.Order.all(token)
- iex> ShopifyAPI.REST.Order.all(auth, [param1: "value", param2: "value2"])
- """
- def all(%AuthToken{} = auth, params \\ [], options \\ []),
- do: REST.get(auth, "orders.json", params, options)
-
- @doc """
- Delete an Order.
-
- iex> ShopifyAPI.REST.Order.delete(auth, order_id)
- """
- def delete(%AuthToken{} = auth, order_id), do: REST.delete(auth, "orders/#{order_id}.json")
-
- @doc """
- Create a new Order.
-
- iex> ShopifyAPI.REST.Order.create(auth, %Order{})
- """
- def create(%AuthToken{} = auth, %{order: %{}} = order),
- do: REST.post(auth, "orders.json", order)
-
- @doc """
- Update an Order.
-
- iex> ShopifyAPI.REST.Order.update(auth, order_id)
- """
- def update(%AuthToken{} = auth, %{order: %{id: order_id}} = order),
- do: REST.put(auth, "orders/#{order_id}.json", order)
-
- @doc """
- Return a count of all Orders.
-
- iex> ShopifyAPI.REST.Order.get(token)
- {:ok, integer = count}
- """
- def count(%AuthToken{} = auth, params \\ [], options \\ []),
- do: REST.get(auth, "orders/count.json", params, Keyword.merge([pagination: :none], options))
-
- @doc """
- Close an Order.
-
- iex> ShopifyAPI.REST.Order.close(auth, order_id)
- """
- def close(%AuthToken{} = auth, order_id),
- do: REST.post(auth, "orders/#{order_id}/close.json")
-
- @doc """
- Re-open a closed Order.
-
- iex> ShopifyAPI.REST.Order.open(auth, order_id)
- """
- def open(%AuthToken{} = auth, order_id), do: REST.post(auth, "orders/#{order_id}/open.json")
-
- @doc """
- Cancel an Order.
-
- iex> ShopifyAPI.REST.Order.cancel(auth, order_id)
- """
- def cancel(%AuthToken{} = auth, order_id),
- do: REST.post(auth, "orders/#{order_id}/cancel.json")
-
- def max_per_page, do: @shopify_per_page_max
-end
diff --git a/lib/shopify_api/rest/price_rule.ex b/lib/shopify_api/rest/price_rule.ex
deleted file mode 100644
index a5135479..00000000
--- a/lib/shopify_api/rest/price_rule.ex
+++ /dev/null
@@ -1,69 +0,0 @@
-defmodule ShopifyAPI.REST.PriceRule do
- @moduledoc """
- ShopifyAPI REST API PriceRule resource
- """
-
- alias ShopifyAPI.AuthToken
- alias ShopifyAPI.REST
-
- @doc """
- Create a price rule.
-
- ## Example
-
- iex> ShopifyAPI.REST.PriceRule.create(auth, map)
- {:ok, %{} = price_rule}
- """
- def create(%AuthToken{} = auth, %{price_rule: %{}} = price_rule),
- do: REST.post(auth, "price_rules.json", price_rule)
-
- @doc """
- Update an existing price rule.
-
- ## Example
-
- iex> ShopifyAPI.REST.PriceRule.update(auth, map)
- {:ok, %{} = price_rule}
- """
- def update(%AuthToken{} = auth, %{price_rule: %{id: price_rule_id}} = price_rule),
- do: REST.put(auth, "price_rules/#{price_rule_id}.json", price_rule)
-
- @doc """
- Return a list of all price rules.
-
- ## Example
-
- iex> ShopifyAPI.REST.PriceRule.all(auth)
- {:ok, [] = price_rules}
- """
- def all(%AuthToken{} = auth, params \\ [], options \\ []),
- do: REST.get(auth, "price_rules.json", params, options)
-
- @doc """
- Get a single price rule.
-
- ## Example
-
- iex> ShopifyAPI.REST.PriceRule.get(auth, integer)
- {:ok, %{} = price_rule}
- """
- def get(%AuthToken{} = auth, price_rule_id, params \\ [], options \\ []),
- do:
- REST.get(
- auth,
- "price_rules/#{price_rule_id}.json",
- params,
- Keyword.merge([pagination: :none], options)
- )
-
- @doc """
- Delete a price rule.
-
- ## Example
-
- iex> ShopifyAPI.REST.PriceRule.delete(auth, string)
- {:ok, 204 }}
- """
- def delete(%AuthToken{} = auth, price_rule_id),
- do: REST.delete(auth, "price_rules/#{price_rule_id}.json")
-end
diff --git a/lib/shopify_api/rest/product.ex b/lib/shopify_api/rest/product.ex
deleted file mode 100644
index a9ea8846..00000000
--- a/lib/shopify_api/rest/product.ex
+++ /dev/null
@@ -1,86 +0,0 @@
-defmodule ShopifyAPI.REST.Product do
- @moduledoc """
- Shopify REST API Product resources
- """
-
- alias ShopifyAPI.AuthToken
- alias ShopifyAPI.REST
-
- @doc """
- Get a list of all the products.
-
- ## Example
-
- iex> ShopifyAPI.REST.Product.all(auth)
- {:ok, [] = products}
- """
- def all(%AuthToken{} = auth, params \\ [], options \\ []),
- do: REST.get(auth, "products.json", params, options)
-
- @doc """
- Return a single product.
-
- ## Example
-
- iex> ShopifyAPI.REST.Product.get(auth, integer)
- {:ok, %{} = product}
- """
- def get(%AuthToken{} = auth, product_id, params \\ [], options \\ []),
- do:
- REST.get(
- auth,
- "products/#{product_id}.json",
- params,
- Keyword.merge([pagination: :none], options)
- )
-
- @doc """
- Return a count of products.
-
- ## Example
-
- iex> ShopifyAPI.REST.Product.count(auth)
- {:ok, integer = count}
- """
- def count(%AuthToken{} = auth, params \\ [], options \\ []),
- do: REST.get(auth, "products/count.json", params, Keyword.merge([pagination: :none], options))
-
- @doc """
- Update a product.
-
- ## Example
-
- iex> ShopifyAPI.REST.Product.update(auth, map)
- {:ok, %{} = product}
- """
- def update(%AuthToken{} = auth, %{"product" => %{"id" => product_id} = product}),
- do: update(auth, %{product: Map.put(product, :id, product_id)})
-
- def update(%AuthToken{} = auth, %{product: %{id: product_id}} = product),
- do: REST.put(auth, "products/#{product_id}.json", product)
-
- @doc """
- Delete a product.
-
- ## Example
-
- iex> ShopifyAPI.REST.Product.delete(auth, integer)
- {:ok, 200 }
- """
- def delete(%AuthToken{} = auth, product_id),
- do: REST.delete(auth, "products/#{product_id}.json")
-
- @doc """
- Create a new product.
-
- ## Example
-
- iex> ShopifyAPI.REST.Product.create(auth, map)
- {:ok, %{} = product}
- """
- def create(%AuthToken{} = auth, %{"product" => %{} = product}),
- do: create(auth, %{product: product})
-
- def create(%AuthToken{} = auth, %{product: %{}} = product),
- do: REST.post(auth, "products.json", product)
-end
diff --git a/lib/shopify_api/rest/product_image.ex b/lib/shopify_api/rest/product_image.ex
deleted file mode 100644
index 1a22272f..00000000
--- a/lib/shopify_api/rest/product_image.ex
+++ /dev/null
@@ -1,104 +0,0 @@
-defmodule ShopifyAPI.REST.ProductImage do
- @moduledoc """
- ShopifyApi REST API Product Image resource
- """
-
- alias ShopifyAPI.AuthToken
- alias ShopifyAPI.REST
-
- @doc """
- Return a list of all products images.
-
- ## Example
-
- iex> ShopifyApi.Rest.ProductImage.all(auth, integer)
- {:ok, [] = images}
- """
- def all(%AuthToken{} = auth, product_id, params \\ [], options \\ []),
- do:
- REST.get(
- auth,
- "products/#{product_id}/images.json",
- params,
- Keyword.merge([pagination: :none], options)
- )
-
- @doc """
- Get a count of all product images.
-
- ## Example
-
- iex> ShopifyApi.Rest.ProductImage.count(auth)
- {:ok, integer = count}
- """
- def count(%AuthToken{} = auth, product_id, params \\ [], options \\ []),
- do:
- REST.get(
- auth,
- "products/#{product_id}/images/count.json",
- params,
- Keyword.merge([pagination: :none], options)
- )
-
- @doc """
- Get all images for a single product.
-
- ## Example
-
- iex> ShopifyApi.Rest.ProductImage.get(auth, map)
- {:ok, %{} = image}
- """
- @deprecated "Duplicate of all/2"
- def get(%AuthToken{} = auth, product_id),
- do: REST.get(auth, "products/#{product_id}/images.json")
-
- @doc """
- Get a single product image.
-
- ## Example
-
- iex> ShopifyApi.Rest.ProductImage.get(auth, map)
- {:ok, %{} = image}
- """
- def get(%AuthToken{} = auth, product_id, image_id, params \\ [], options \\ []),
- do:
- REST.get(
- auth,
- "products/#{product_id}/images/#{image_id}.json",
- params,
- Keyword.merge([pagination: :none], options)
- )
-
- @doc """
- Create a new product image.
-
- ## Example
-
- iex> ShopifyApi.Rest.ProductImage.create(auth, integer, map)
- {:ok, %{} = image}
- """
- def create(%AuthToken{} = auth, product_id, %{image: %{}} = image),
- do: REST.post(auth, "products/#{product_id}/images.json", image)
-
- @doc """
- Update an existing product image.
-
- ## Example
-
- iex> ShopifyApi.Rest.ProductImage.update(auth, integer, map)
- {:ok, %{} = image}
- """
- def update(%AuthToken{} = auth, product_id, %{image: %{id: image_id}} = image),
- do: REST.put(auth, "products/#{product_id}/images/#{image_id}.json", image)
-
- @doc """
- Delete a product image.
-
- ## Example
-
- iex> ShopifyApi.Rest.ProductImage.delete(auth, integer, integer)
- {:ok, 200 }}
- """
- def delete(%AuthToken{} = auth, product_id, image_id),
- do: REST.delete(auth, "products/#{product_id}/images/#{image_id}.json")
-end
diff --git a/lib/shopify_api/rest/recurring_application_charge.ex b/lib/shopify_api/rest/recurring_application_charge.ex
deleted file mode 100644
index 573f9180..00000000
--- a/lib/shopify_api/rest/recurring_application_charge.ex
+++ /dev/null
@@ -1,101 +0,0 @@
-defmodule ShopifyAPI.REST.RecurringApplicationCharge do
- @moduledoc """
- ShopifyAPI REST API Recurring Application Charge resource
- """
-
- require Logger
- alias ShopifyAPI.AuthToken
- alias ShopifyAPI.REST
-
- @doc """
- Create a recurring application charge.
-
- ## Example
-
- iex> ShopifyAPI.REST.RecurringApplicationCharge.create(auth, map)
- {:ok, %{} = recurring_application_charge}
- """
- def create(
- %AuthToken{} = auth,
- %{recurring_application_charge: %{}} = recurring_application_charge
- ) do
- REST.post(auth, "recurring_application_charges.json", recurring_application_charge)
- end
-
- @doc """
- Get a single charge.
-
- ## Example
-
- iex> ShopifyAPI.REST.RecurringApplicationCharge.get(auth, integer)
- {:ok, %{} = recurring_application_charge}
- """
- def get(%AuthToken{} = auth, recurring_application_charge_id, params \\ [], options \\ []) do
- REST.get(
- auth,
- "recurring_application_charges/#{recurring_application_charge_id}.json",
- params,
- Keyword.merge([pagination: :none], options)
- )
- end
-
- @doc """
- Get a list of all recurring application charges.
-
- ## Example
-
- iex> ShopifyAPI.REST.RecurringApplicationCharge.all(auth)
- {:ok, [] = recurring_application_charges}
- """
- def all(%AuthToken{} = auth, params \\ [], options \\ []),
- do:
- REST.get(
- auth,
- "recurring_application_charges.json",
- params,
- Keyword.merge([pagination: :none], options)
- )
-
- @doc """
- Activates a recurring application charge.
-
- ## Example
-
- iex> ShopifyAPI.REST.RecurringApplicationCharge.activate(auth, integer)
- {:ok, %{} = recurring_application_charge}
- """
- def activate(%AuthToken{} = auth, recurring_application_charge_id) do
- REST.post(
- auth,
- "recurring_application_charges/#{recurring_application_charge_id}/activate.json"
- )
- end
-
- @doc """
- Cancels a recurring application charge.
-
- ## Example
-
- iex> ShopifyAPI.REST.RecurringApplicationCharge.cancel(auth, integer)
- {:ok, 200 }
- """
- def cancel(%AuthToken{} = auth, recurring_application_charge_id),
- do:
- REST.delete(
- auth,
- "recurring_application_charges/#{recurring_application_charge_id}.json"
- )
-
- @doc """
- Updates a capped amount of recurring application charge.
-
- ## Example
-
- iex> ShopifyAPI.REST.RecurringApplicationCharge.update()
- {:error, "Not implemented" }
- """
- def update do
- Logger.warning("#{__MODULE__} error, resource not implemented.")
- {:error, "Not implemented"}
- end
-end
diff --git a/lib/shopify_api/rest/redirect.ex b/lib/shopify_api/rest/redirect.ex
deleted file mode 100644
index 55753b3e..00000000
--- a/lib/shopify_api/rest/redirect.ex
+++ /dev/null
@@ -1,117 +0,0 @@
-defmodule ShopifyAPI.REST.Redirect do
- @moduledoc """
- Shopify REST API Redirect resources
- """
-
- alias ShopifyAPI.AuthToken
- alias ShopifyAPI.REST
-
- @doc """
- Get a list of all the redirects.
-
- ## Example
-
- iex> ShopifyAPI.REST.Redirect.all(auth)
- {:ok, [] = redirects}
- """
- def all(%AuthToken{} = auth, params \\ [], options \\ []),
- do: REST.get(auth, "redirects.json", params, options)
-
- @doc """
- Return a single redirect.
-
- ## Example
-
- iex> ShopifyAPI.REST.Redirect.get(auth, integer)
- {:ok, %{} = redirect}
- """
- def get(%AuthToken{} = auth, redirect_id, params \\ [], options \\ []),
- do:
- REST.get(
- auth,
- "redirects/#{redirect_id}.json",
- params,
- Keyword.merge([pagination: :none], options)
- )
-
- @doc """
- Return a count of redirects.
-
- ## Example
-
- iex> ShopifyAPI.REST.Redirect.count(auth)
- {:ok, integer = count}
- """
- def count(%AuthToken{} = auth, params \\ [], options \\ []),
- do:
- REST.get(auth, "redirects/count.json", params, Keyword.merge([pagination: :none], options))
-
- @doc """
- Update a redirect.
-
- ## Expected Shape
-
- ### Request Redirect Map Shape Example
- %{
- id: 668809255,
- path: "/tiger"
- }
-
- ### Response Map Shape Example
- %{
- "id": 668809255,
- "path": "/tiger",
- "target": "/pages/macosx"
- }
-
- ## Example
-
- iex> ShopifyAPI.REST.Redirect.update(auth, map)
- {:ok, %{} = redirect}
- """
- def update(%AuthToken{} = auth, %{"redirect" => %{"id" => redirect_id} = redirect}),
- do: update(auth, %{redirect: Map.put(redirect, :id, redirect_id)})
-
- def update(%AuthToken{} = auth, %{redirect: %{id: redirect_id}} = redirect),
- do: REST.put(auth, "redirects/#{redirect_id}.json", redirect)
-
- @doc """
- Delete a redirect.
-
- ## Example
-
- iex> ShopifyAPI.REST.Redirect.delete(auth, integer)
- {:ok, 200 }
- """
- def delete(%AuthToken{} = auth, redirect_id),
- do: REST.delete(auth, "redirects/#{redirect_id}.json")
-
- @doc """
- Create a new redirect.
-
- ## Expected Shape
-
- ###Request Redirect Map Shape Example
- %{
- path: "/ipod",
- target: "/pages/itunes"
- }
-
- ### Response Map Shape Example
- %{
- "id": 979034144,
- "path": "/ipod",
- "target": "/pages/itunes"
- }
-
- ## Example
-
- iex> ShopifyAPI.REST.Redirect.create(auth, map)
- {:ok, %{} = redirect}
- """
- def create(%AuthToken{} = auth, %{"redirect" => %{} = redirect}),
- do: create(auth, %{redirect: redirect})
-
- def create(%AuthToken{} = auth, %{redirect: %{}} = redirect),
- do: REST.post(auth, "redirects.json", redirect)
-end
diff --git a/lib/shopify_api/rest/refund.ex b/lib/shopify_api/rest/refund.ex
deleted file mode 100644
index dd291e58..00000000
--- a/lib/shopify_api/rest/refund.ex
+++ /dev/null
@@ -1,58 +0,0 @@
-defmodule ShopifyAPI.REST.Refund do
- @moduledoc """
- ShopifyAPI REST API Refund resource
- """
-
- alias ShopifyAPI.AuthToken
- alias ShopifyAPI.REST
-
- @doc """
- Return a list of all refunds for an order.
-
- ## Example
-
- iex> ShopifyAPI.REST.Refund.all(auth, string)
- {:ok, [] = refunds}
- """
- def all(%AuthToken{} = auth, order_id, params \\ [], options \\ []),
- do: REST.get(auth, "orders/#{order_id}/refunds.json", params, options)
-
- @doc """
- Get a specific refund.
-
- ## Example
-
- iex> ShopifyAPI.REST.Refund.get(auth, string, string)
- {:ok, %{} = refund}
- """
- def get(%AuthToken{} = auth, order_id, refund_id, params \\ [], options \\ []),
- do:
- REST.get(
- auth,
- "orders/#{order_id}/refunds/#{refund_id}.json",
- params,
- Keyword.merge([pagination: :none], options)
- )
-
- @doc """
- Calculate a refund.
-
- ## Example
-
- iex> ShopifyAPI.REST.Refund.calculate(auth, integer, map)
- {:ok, %{} = refund}
- """
- def calculate(%AuthToken{} = auth, order_id, %{refund: %{}} = refund),
- do: REST.post(auth, "orders/#{order_id}/refunds/calculate.json", refund)
-
- @doc """
- Create a refund.
-
- ## Example
-
- iex> ShopifyAPI.REST.Refund.create(auth, integer, map)
- {:ok, %{} = refund}
- """
- def create(%AuthToken{} = auth, order_id, %{refund: %{}} = refund),
- do: REST.post(auth, "orders/#{order_id}/refunds.json", refund)
-end
diff --git a/lib/shopify_api/rest/report.ex b/lib/shopify_api/rest/report.ex
deleted file mode 100644
index d7628fcc..00000000
--- a/lib/shopify_api/rest/report.ex
+++ /dev/null
@@ -1,69 +0,0 @@
-defmodule ShopifyAPI.REST.Report do
- @moduledoc """
- ShopifyAPI REST API Report resource
- """
-
- alias ShopifyAPI.AuthToken
- alias ShopifyAPI.REST
-
- @doc """
- Get a list of all reports.
-
- ## Example
-
- iex> ShopifyAPI.REST.Report.all(auth)
- {:ok, [] = reports}
- """
- def all(%AuthToken{} = auth, params \\ [], options \\ []),
- do: REST.get(auth, "reports.json", params, options)
-
- @doc """
- Return a single report.
-
- ## Example
-
- iex> ShopifyAPI.REST.Report.get(auth, integer)
- {:ok, %{} = report}
- """
- def get(%AuthToken{} = auth, report_id, params \\ [], options \\ []),
- do:
- REST.get(
- auth,
- "reports/#{report_id}.json",
- params,
- Keyword.merge([pagination: :none], options)
- )
-
- @doc """
- Create a new report.
-
- ## Example
-
- iex> ShopifyAPI.REST.Report.create(auth, map)
- {:ok, %{} = report}
- """
- def create(%AuthToken{} = auth, %{report: %{}} = report),
- do: REST.post(auth, "reports.json", report)
-
- @doc """
- Update a report.
-
- ## Example
-
- iex> ShopifyAPI.REST.Report.update(auth, map)
- {:ok, %{} = report}
- """
- def update(%AuthToken{} = auth, %{report: %{id: report_id}} = report),
- do: REST.put(auth, "reports/#{report_id}.json", report)
-
- @doc """
- Delete.
-
- ## Example
-
- iex> ShopifyAPI.REST.Report.Delete(auth)
- {:ok, 200 }}
- """
- def delete(%AuthToken{} = auth, report_id),
- do: REST.delete(auth, "reports/#{report_id}.json")
-end
diff --git a/lib/shopify_api/rest/request.ex b/lib/shopify_api/rest/request.ex
deleted file mode 100644
index ec4aa771..00000000
--- a/lib/shopify_api/rest/request.ex
+++ /dev/null
@@ -1,266 +0,0 @@
-defmodule ShopifyAPI.REST.Request do
- @moduledoc """
- The internal interface to Shopify's REST Admin API, built on HTTPoison.
-
- Adds support for building URLs and authentication headers from an AuthToken,
- as well as functionality to throttle/log requests and parse responses.
- """
-
- use HTTPoison.Base
- require Logger
-
- alias HTTPoison.Error
- alias ShopifyAPI.{AuthToken, JSONSerializer, RateLimiting, Throttled}
-
- @default_api_version "2020-10"
-
- @rest_receive_timeout Application.compile_env(:shopify_api, :rest_recv_timeout)
-
- @type http_method :: :get | :post | :put | :delete
-
- ## Public Interface
-
- @spec perform(
- AuthToken.t(),
- http_method(),
- path :: String.t(),
- body :: String.t(),
- params :: keyword(),
- options :: keyword()
- ) :: {:ok, HTTPoison.Response.t()} | {:error, HTTPoison.Response.t() | any()}
- def perform(%AuthToken{} = token, method, path, body \\ "", params \\ [], options \\ []) do
- url = token |> url(path) |> add_params_to_url(params)
- headers = headers(token)
-
- opts = Keyword.put_new(options, :token, token)
-
- transform_response(
- Throttled.request(
- fn -> logged_request(method, url, body, headers, opts) end,
- token,
- RateLimiting.RESTTracker
- )
- )
- end
-
- defguard is_success_status(status) when status >= 200 and status < 300
-
- @spec transform_response(HTTPoison.Response.t()) :: {:error, any()} | {:ok, any()}
- def transform_response(response) do
- case response do
- {:ok, %{status_code: status} = response}
- when is_success_status(status) ->
- {:ok, response}
-
- {:ok, response} ->
- {:error, response}
-
- {:error, _} = value ->
- value
-
- response ->
- {:error, response}
- end
- end
-
- @spec stream(AuthToken.t(), String.t(), keyword(), keyword()) :: Enumerable.t()
- def stream(auth, path, params, options \\ []) do
- headers = headers(auth)
- opts = Keyword.put_new(options, :token, auth)
-
- start_fun = fn -> auth |> url(path) |> add_params_to_url(params) end
-
- next_fun = fn
- url when is_binary(url) ->
- shopify_response =
- Throttled.request(
- fn -> logged_request(:get, url, "", headers, opts) end,
- auth,
- RateLimiting.RESTTracker
- )
-
- case transform_response(shopify_response) do
- {:ok, resp} ->
- extract_results_and_next_link(resp)
-
- value ->
- {[value], nil}
- end
-
- _ ->
- {:halt, nil}
- end
-
- Stream.resource(
- start_fun,
- next_fun,
- fn _ -> :ok end
- )
- end
-
- def version do
- Keyword.get(
- Application.get_env(:shopify_api, ShopifyAPI.REST) || [],
- :api_version,
- @default_api_version
- )
- end
-
- ## HTTPoison Overrides
-
- def logged_request(method, url, body, headers, options) do
- {time, response} = :timer.tc(&request/5, [method, url, body, headers, options])
- token = Keyword.get(options, :token, %ShopifyAPI.AuthToken{})
-
- log_request(token, method, url, time, response)
- send_telemetry(token, method, url, time, response)
-
- response
- end
-
- @impl true
- def process_request_options(opts) do
- Keyword.put_new(opts, :recv_timeout, @rest_receive_timeout)
- end
-
- @impl true
- def process_response_body(body) do
- with {:ok, results_map} when is_map(results_map) <- JSONSerializer.decode(body),
- [{_key, results}] <- Map.to_list(results_map) do
- results
- end
- end
-
- ## Private Helpers
-
- defp send_telemetry(
- %{app_name: app, shop_name: shop} = _token,
- method,
- url,
- time,
- {:ok, %{status_code: status}} = response
- ) do
- :telemetry.execute(
- [:shopify_api, :rest_request, :success],
- %{request_time: time, remaining_calls: remaining_calls(response)},
- %{
- app: app,
- shop: shop,
- url: url,
- status_code: status,
- method: method,
- module: module_name()
- }
- )
- end
-
- defp send_telemetry(
- %{app_name: app, shop_name: shop} = _token,
- method,
- url,
- time,
- {:error, %Error{reason: reason}} = _response
- ) do
- :telemetry.execute(
- [:shopify_api, :rest_request, :failure],
- %{request_time: time},
- %{
- app: app,
- shop: shop,
- url: url,
- method: method,
- module: module_name(),
- reason: reason
- }
- )
- end
-
- defp send_telemetry(_token, _method, _url, _time, _response), do: nil
-
- defp log_request(token, method, url, time, response) do
- Logger.debug(fn ->
- %{app_name: app, shop_name: shop} = token
- module = module_name()
- method = method |> to_string() |> String.upcase()
-
- "#{module} #{method} #{url} #{app} #{shop} (#{remaining_calls(response)}) [#{div(time, 1_000)}ms]"
- end)
- end
-
- defp module_name do
- __MODULE__ |> to_string() |> String.trim_leading("Elixir.")
- end
-
- defp remaining_calls({:ok, response}) do
- response
- |> RateLimiting.RESTCallLimits.limit_header_or_status_code()
- |> RateLimiting.RESTCallLimits.get_api_remaining_calls()
- end
-
- defp remaining_calls(_), do: nil
-
- # Absolute URL generator
- defp url(%{shop_name: domain}, </, path::binary>>),
- do: "#{ShopifyAPI.transport()}://#{domain}/#{path}"
-
- # Relative with version URL generator
- defp url(shop, path), do: url(shop, "/admin/api/#{version()}/#{path}")
-
- defp headers(%{token: access_token}) do
- [
- {"Content-Type", "application/json"},
- {"X-Shopify-Access-Token", access_token}
- ]
- end
-
- @spec add_params_to_url(url :: binary, params :: list | map) :: binary
- defp add_params_to_url(url, params) do
- url
- |> URI.parse()
- |> merge_uri_params(params)
- |> to_string()
- end
-
- @spec merge_uri_params(URI.t(), params :: list | map) :: URI.t()
- defp merge_uri_params(%URI{query: nil} = uri, params) when is_list(params) or is_map(params) do
- Map.put(uri, :query, URI.encode_query(params))
- end
-
- defp merge_uri_params(%URI{} = uri, params) when is_list(params) or is_map(params) do
- Map.update!(uri, :query, fn q ->
- q
- |> URI.decode_query()
- |> Map.merge(param_list_to_map_with_string_keys(params))
- |> URI.encode_query()
- end)
- end
-
- @spec param_list_to_map_with_string_keys(list) :: map
- defp param_list_to_map_with_string_keys(params) when is_list(params) or is_map(params) do
- for {key, value} <- params, into: Map.new() do
- {"#{key}", value}
- end
- end
-
- @link_regex ~r/<(?.*)>;\s*rel=\"(?.*)\"/
-
- @spec extract_next_link(list) :: binary | nil
- defp extract_next_link(headers) do
- for {header, link_header} <- headers,
- String.downcase(header) == "link",
- links <- String.split(link_header, ",") do
- case Regex.named_captures(@link_regex, links) do
- %{"link" => link, "rel" => "next"} -> link
- _ -> nil
- end
- end
- |> Enum.filter(&(not is_nil(&1)))
- |> List.first()
- end
-
- @spec extract_results_and_next_link(HTTPoison.Response.t()) :: {any(), nil | binary}
- def extract_results_and_next_link(%HTTPoison.Response{body: body, headers: headers}) do
- next_link = extract_next_link(headers)
- {body, next_link}
- end
-end
diff --git a/lib/shopify_api/rest/shop.ex b/lib/shopify_api/rest/shop.ex
deleted file mode 100644
index 1c0e53ca..00000000
--- a/lib/shopify_api/rest/shop.ex
+++ /dev/null
@@ -1,19 +0,0 @@
-defmodule ShopifyAPI.REST.Shop do
- @moduledoc """
- ShopifyAPI REST API Shop resource
- """
-
- alias ShopifyAPI.AuthToken
- alias ShopifyAPI.REST
-
- @doc """
- Get a shop's configuration.
-
- ## Example
-
- iex> ShopifyAPI.REST.Shop.get(auth)
- {:ok, %{} = shop}
- """
- def get(%AuthToken{} = auth, params \\ [], options \\ []),
- do: REST.get(auth, "shop.json", params, Keyword.merge([pagination: :none], options))
-end
diff --git a/lib/shopify_api/rest/smart_collection.ex b/lib/shopify_api/rest/smart_collection.ex
deleted file mode 100644
index 9f5745a8..00000000
--- a/lib/shopify_api/rest/smart_collection.ex
+++ /dev/null
@@ -1,83 +0,0 @@
-defmodule ShopifyAPI.REST.SmartCollection do
- @moduledoc """
- Shopify REST API Smart Collection resources
- """
-
- alias ShopifyAPI.AuthToken
- alias ShopifyAPI.REST
-
- @doc """
- Get a list of all SmartCollections.
-
- ## Example
- iex> ShopifyAPI.REST.SmartCollection.all(token)
- {:ok, [] = smart_collections}
- """
- def all(%AuthToken{} = auth, params \\ [], options \\ []),
- do: REST.get(auth, "smart_collections.json", params, options)
-
- @doc """
- Get a count of all SmartCollections.
-
- ## Example
- iex> ShopifyAPI.REST.SmartCollection.count(token)
- {:ok,teger = count}
- """
- def count(%AuthToken{} = auth, params \\ [], options \\ []),
- do:
- REST.get(
- auth,
- "smart_collections/count.json",
- params,
- Keyword.merge([pagination: :none], options)
- )
-
- @doc """
- Return a single SmartCollection.
-
- ## Example
- iex> ShopifyAPI.REST.SmartCollection.get(auth, string)
- {:ok, %{} = smart_collection}
- """
- def get(%AuthToken{} = auth, smart_collection_id, params \\ [], options \\ []),
- do:
- REST.get(
- auth,
- "smart_collections/#{smart_collection_id}.json",
- params,
- Keyword.merge([pagination: :none], options)
- )
-
- @doc """
- Create a SmartCollection.
-
- ## Example
- iex> ShopifyAPI.REST.SmartCollection.create(auth, map)
- {:ok, %{} = smart_collection}
- """
- def create(%AuthToken{} = auth, %{smart_collection: %{}} = smart_collection),
- do: REST.post(auth, "smart_collections.json", smart_collection)
-
- @doc """
- Update an existing SmartCollection.
-
- ## Example
- iex> ShopifyAPI.REST.SmartCollection.update(auth, map)
- {:ok, %{} = smart_collection}
- """
- def update(
- %AuthToken{} = auth,
- %{smart_collection: %{id: smart_collection_id}} = smart_collection
- ),
- do: REST.put(auth, "smart_collections/#{smart_collection_id}.json", smart_collection)
-
- @doc """
- Delete a SmartCollection.
-
- ## Example
- iex> ShopifyAPI.REST.SmartCollection.delete(auth, string)
- {:ok, %{ "response": 200 }}
- """
- def delete(%AuthToken{} = auth, smart_collection_id),
- do: REST.delete(auth, "smart_collections/#{smart_collection_id}.json")
-end
diff --git a/lib/shopify_api/rest/tender_transaction.ex b/lib/shopify_api/rest/tender_transaction.ex
deleted file mode 100644
index b02c4c32..00000000
--- a/lib/shopify_api/rest/tender_transaction.ex
+++ /dev/null
@@ -1,16 +0,0 @@
-defmodule ShopifyAPI.REST.TenderTransaction do
- @moduledoc """
- """
- alias ShopifyAPI.AuthToken
- alias ShopifyAPI.REST
-
- @shopify_per_page_max 250
-
- @doc """
- Return all the Tender Transactions.
- """
- def all(%AuthToken{} = auth, params \\ [], options \\ []),
- do: REST.get(auth, "tender_transactions.json", params, options)
-
- def max_per_page, do: @shopify_per_page_max
-end
diff --git a/lib/shopify_api/rest/theme.ex b/lib/shopify_api/rest/theme.ex
deleted file mode 100644
index 56a31787..00000000
--- a/lib/shopify_api/rest/theme.ex
+++ /dev/null
@@ -1,75 +0,0 @@
-defmodule ShopifyAPI.REST.Theme do
- @moduledoc """
- ShopifyAPI REST API Theme resource
- """
-
- alias ShopifyAPI.AuthToken
- alias ShopifyAPI.REST
-
- @doc """
- Get a single theme.
-
- ## Example
-
- iex> ShopifyAPI.REST.Theme.get(auth, integer)
- {:ok, %{} = theme}
- """
- def get(%AuthToken{} = auth, theme_id, params \\ [], options \\ []),
- do:
- REST.get(
- auth,
- "themes/#{theme_id}.json",
- params,
- Keyword.merge([pagination: :none], options)
- )
-
- @doc """
- Return a list of all themes.
-
- ## Example
-
- iex> ShopifyAPI.REST.Theme.all(auth)
- {:ok, [] = themes}
- """
- def all(%AuthToken{} = auth, params \\ [], options \\ []),
- do: REST.get(auth, "themes.json", params, Keyword.merge([pagination: :none], options))
-
- @doc """
- Update a theme.
-
- ## Example
-
- iex> ShopifyAPI.REST.Theme.update(auth, map)
- {:ok, %{} = theme}
- """
- def update(%AuthToken{} = auth, %{"theme" => %{"id" => theme_id} = theme}),
- do: update(auth, %{theme: Map.put(theme, :id, theme_id)})
-
- def update(%AuthToken{} = auth, %{theme: %{id: theme_id}} = theme),
- do: REST.put(auth, "themes/#{theme_id}.json", theme)
-
- @doc """
- Delete a theme.
-
- ## Example
-
- iex> ShopifyAPI.REST.Theme.delete(auth, integer)
- {:ok, 200 }
- """
- def delete(%AuthToken{} = auth, theme_id),
- do: REST.delete(auth, "themes/#{theme_id}.json")
-
- @doc """
- Create a new theme.
-
- ## Example
-
- iex> ShopifyAPI.REST.Theme.create(auth, map)
- {:ok, %{} = theme}
- """
- def create(%AuthToken{} = auth, %{"theme" => %{} = theme}),
- do: create(auth, %{theme: theme})
-
- def create(%AuthToken{} = auth, %{theme: %{}} = theme),
- do: REST.post(auth, "themes.json", theme)
-end
diff --git a/lib/shopify_api/rest/transaction.ex b/lib/shopify_api/rest/transaction.ex
deleted file mode 100644
index 51788262..00000000
--- a/lib/shopify_api/rest/transaction.ex
+++ /dev/null
@@ -1,15 +0,0 @@
-defmodule ShopifyAPI.REST.Transaction do
- @moduledoc """
- """
- alias ShopifyAPI.AuthToken
- alias ShopifyAPI.REST
-
- @doc """
- Return all the Transactions for an Order.
- """
- def all(%AuthToken{} = auth, order_id, params \\ [], options \\ []),
- do: REST.get(auth, "orders/#{order_id}/transactions.json", params, options)
-
- def create(%AuthToken{} = auth, %{transaction: %{order_id: order_id}} = transaction),
- do: REST.post(auth, "orders/#{order_id}/transactions.json", transaction)
-end
diff --git a/lib/shopify_api/rest/usage_charge.ex b/lib/shopify_api/rest/usage_charge.ex
deleted file mode 100644
index 8dfc2cb1..00000000
--- a/lib/shopify_api/rest/usage_charge.ex
+++ /dev/null
@@ -1,68 +0,0 @@
-defmodule ShopifyAPI.REST.UsageCharge do
- @moduledoc """
- ShopifyAPI REST API UsageCharge resource
- """
-
- alias ShopifyAPI.AuthToken
- alias ShopifyAPI.REST
-
- @doc """
- Create a usage charge.
-
- ## Example
-
- iex> ShopifyAPI.REST.UsageCharge.create(auth, integer, map)
- {:ok, %{} = usage_charge}
- """
- def create(
- %AuthToken{} = auth,
- recurring_application_charge_id,
- usage_charge
- ) do
- REST.post(
- auth,
- "recurring_application_charges/#{recurring_application_charge_id}/usage_charges.json",
- usage_charge
- )
- end
-
- @doc """
- Retrieve a single charge.
-
- ## Example
-
- iex> ShopifyAPI.REST.UsageCharge.get(auth, integer, %{usage_charge: %{id: integer}})
- {:ok, %{} = usage_charge}
- """
- def get(
- %AuthToken{} = auth,
- recurring_application_charge_id,
- %{usage_charge: %{id: usage_charge_id}},
- params \\ [],
- options \\ []
- ) do
- REST.get(
- auth,
- "recurring_application_charges/#{recurring_application_charge_id}/usage_charges/#{usage_charge_id}.json",
- params,
- Keyword.merge([pagination: :none], options)
- )
- end
-
- @doc """
- Get of all the usage charges.
-
- ## Example
-
- iex> ShopifyAPI.REST.UsageCharge.all(auth, integer)
- {:ok, [] = usage_charges}
- """
- def all(%AuthToken{} = auth, recurring_application_charge_id, params \\ [], options \\ []) do
- REST.get(
- auth,
- "recurring_application_charges/#{recurring_application_charge_id}/usage_charges.json",
- params,
- Keyword.merge([pagination: :none], options)
- )
- end
-end
diff --git a/lib/shopify_api/rest/user.ex b/lib/shopify_api/rest/user.ex
deleted file mode 100644
index d5596f00..00000000
--- a/lib/shopify_api/rest/user.ex
+++ /dev/null
@@ -1,42 +0,0 @@
-defmodule ShopifyAPI.REST.User do
- @moduledoc """
- ShopifyAPI REST API User resource
- """
-
- alias ShopifyAPI.AuthToken
- alias ShopifyAPI.REST
-
- @doc """
- Get a single user.
-
- ## Example
-
- iex> ShopifyAPI.REST.User.get(auth, integer)
- {:ok, %{} = user}
- """
- def get(%AuthToken{} = auth, user_id, params \\ [], options \\ []),
- do:
- REST.get(auth, "users/#{user_id}.json", params, Keyword.merge([pagination: :none], options))
-
- @doc """
- Return a list of all users.
-
- ## Example
-
- iex> ShopifyAPI.REST.User.all(auth)
- {:ok, [] = users}
- """
- def all(%AuthToken{} = auth, params \\ [], options \\ []),
- do: REST.get(auth, "users.json", params, Keyword.merge([pagination: :none], options))
-
- @doc """
- Get the currently logged-in user.
-
- ## Example
-
- iex> ShopifyAPI.REST.User.current(auth)
- {:ok, %{} = user}
- """
- def current(%AuthToken{} = auth, params \\ [], options \\ []),
- do: REST.get(auth, "users/current.json", params, Keyword.merge([pagination: :none], options))
-end
diff --git a/lib/shopify_api/rest/variant.ex b/lib/shopify_api/rest/variant.ex
deleted file mode 100644
index 9fc1e4de..00000000
--- a/lib/shopify_api/rest/variant.ex
+++ /dev/null
@@ -1,72 +0,0 @@
-defmodule ShopifyAPI.REST.Variant do
- @moduledoc """
- """
- alias ShopifyAPI.AuthToken
- alias ShopifyAPI.REST
-
- @doc """
- Return a single Product Variant
- """
- def get(%AuthToken{} = auth, variant_id, params \\ [], options \\ []),
- do:
- REST.get(
- auth,
- "variants/#{variant_id}.json",
- params,
- Keyword.merge([pagination: :none], options)
- )
-
- @doc """
- Return all of a Product's Variants.
-
- iex> ShopifyAPI.REST.Variant.get(auth, product_id)
-
- """
- def all(%AuthToken{} = auth, product_id, params \\ [], options \\ []),
- do:
- REST.get(
- auth,
- "products/#{product_id}/variants.json",
- params,
- Keyword.merge([pagination: :none], options)
- )
-
- @doc """
- Return a count of all Product Variants.
-
- iex> ShopifyAPI.REST.Variant.get(auth, product_id)
- {:ok, integer = count}
- """
-
- def count(%AuthToken{} = auth, product_id, params \\ [], options \\ []),
- do:
- REST.get(
- auth,
- "products/#{product_id}/variants/count.json",
- params,
- Keyword.merge([pagination: :none], options)
- )
-
- @doc """
- Delete a Product Variant.
-
- iex> ShopifyAPI.REST.Variant.delete(auth, product_id, variant_id)
- {:ok, %{}}
- """
- def delete(%AuthToken{} = auth, product_id, variant_id),
- do: REST.delete(auth, "products/#{product_id}/variants/#{variant_id}.json")
-
- @doc """
- Create a new Product Variant.
-
- iex> ShopifyAPI.REST.Variant.create(auth, product_id, %{variant: %{body_html: "Testing variant create", title: "Testing Create Product Variant"}})
- """
- def create(%AuthToken{} = auth, product_id, %{variant: %{}} = variant),
- do: REST.post(auth, "products/#{product_id}/variants.json", variant)
-
- @doc """
- Update a Product Variant.
- """
- def update(%AuthToken{} = auth, %{variant: %{id: variant_id}} = variant),
- do: REST.put(auth, "variants/#{variant_id}.json", variant)
-end
diff --git a/lib/shopify_api/rest/webhook.ex b/lib/shopify_api/rest/webhook.ex
deleted file mode 100644
index 2ce55cf6..00000000
--- a/lib/shopify_api/rest/webhook.ex
+++ /dev/null
@@ -1,58 +0,0 @@
-defmodule ShopifyAPI.REST.Webhook do
- @moduledoc """
- """
- alias ShopifyAPI.AuthToken
- alias ShopifyAPI.REST
-
- @doc """
- ## Helper method to generate the callback URI this server responds to.
-
- ## Example
-
- iex> ShopifyAPI.REST.Webhook.webhook_uri(%AuthToken{app_name: "some-shopify-app"})
- "https://shopifyapi-server.example.com/shop/webhook/some-shopify-app"
- """
- def webhook_uri(%AuthToken{app_name: app}) do
- # TODO this is brittle, we need to leverage URI and build correct paths here
- Application.get_env(:shopify_api, ShopifyAPI.Webhook)[:uri] <> "/#{app}"
- end
-
- @doc """
- ## Example
-
- iex> ShopifyAPI.REST.Webhook.all(auth)
- {:ok, [%{"webhook_id" => "_", "address" => "https://example.com"}] = webhooks}
- """
- def all(%AuthToken{} = auth, params \\ [], options \\ []),
- do: REST.get(auth, "webhooks.json", params, options)
-
- def get(%AuthToken{} = auth, webhook_id, params \\ [], options \\ []),
- do:
- REST.get(
- auth,
- "webhooks/#{webhook_id}.json",
- params,
- Keyword.merge([pagination: :none], options)
- )
-
- def update(%AuthToken{} = auth, %{webhook: %{webhook_id: webhook_id}} = webhook),
- do: REST.put(auth, "webhooks/#{webhook_id}.json", webhook)
-
- @doc """
- ## Example
-
- iex> ShopifyAPI.REST.Webhook.delete(auth, webhook_id)
- {:ok, %{}}
- """
- def delete(%AuthToken{} = auth, webhook_id),
- do: REST.delete(auth, "webhooks/#{webhook_id}.json")
-
- @doc """
- ## Example
-
- iex> ShopifyAPI.REST.Webhook.create(auth, %{webhook: %{address: "https://example.com"}})
- {:ok, %{"webhook_id" => "_", "address" => "https://example.com"} = webhook}
- """
- def create(%AuthToken{} = auth, %{webhook: %{}} = webhook),
- do: REST.post(auth, "webhooks.json", webhook)
-end
diff --git a/lib/shopify_api/throttled.ex b/lib/shopify_api/throttled.ex
index 74fdce68..a511eaa6 100644
--- a/lib/shopify_api/throttled.ex
+++ b/lib/shopify_api/throttled.ex
@@ -26,6 +26,10 @@ defmodule ShopifyAPI.Throttled do
@request_max_tries 10
+ @over_limit_status_code 429
+
+ def over_limit_status_code, do: @over_limit_status_code
+
def graphql_request(func, token, estimated_cost, depth \\ 1, max_tries \\ @request_max_tries) do
max_query_cost = RateLimiting.GraphQL.max_query_cost()
@@ -50,7 +54,7 @@ defmodule ShopifyAPI.Throttled do
def request(func, token, max_tries, depth, estimated_cost, tracker_impl)
when is_function(func) do
- over_limit_status_code = RateLimiting.REST.over_limit_status_code()
+ over_limit_status_code = over_limit_status_code()
token
|> tracker_impl.get(estimated_cost)
diff --git a/test/shopify_api/rate_limiting/rest_call_limits_test.exs b/test/shopify_api/rate_limiting/rest_call_limits_test.exs
deleted file mode 100644
index cdd51f21..00000000
--- a/test/shopify_api/rate_limiting/rest_call_limits_test.exs
+++ /dev/null
@@ -1,83 +0,0 @@
-defmodule ShopifyAPI.RateLimiting.RESTCallLimitsTest do
- use ExUnit.Case
-
- alias ShopifyAPI.RateLimiting.RESTCallLimits
-
- alias HTTPoison.{Error, Response}
-
- describe "limit_header_or_status_code/1" do
- test "pulls the call_limit header out of response headers" do
- call_limit_header = {"X-Shopify-Shop-Api-Call-Limit", "32/50"}
- response = %Response{headers: [{"foo", "bar"}, call_limit_header, {"bat", "biz"}]}
-
- assert RESTCallLimits.limit_header_or_status_code(response) == "32/50"
- end
-
- test "returns :over_limit on status code 429" do
- call_limit_header = {"X-Shopify-Shop-Api-Call-Limit", "32/50"}
-
- response = %Response{
- status_code: 429,
- headers: [{"foo", "bar"}, call_limit_header, {"bat", "biz"}]
- }
-
- assert RESTCallLimits.limit_header_or_status_code(response) == :over_limit
- end
-
- test "returns nil if no call limit header" do
- response = %Response{headers: [{"foo", "bar"}]}
-
- assert RESTCallLimits.limit_header_or_status_code(response) == nil
- end
-
- test "returns nil on error" do
- assert RESTCallLimits.limit_header_or_status_code(%Error{}) == nil
- end
- end
-
- describe "get_api_remaining_calls/1" do
- test "calculates the call limit from the header" do
- header = "32/50"
-
- assert RESTCallLimits.get_api_remaining_calls(header) == 18
- end
-
- test "returns 0 for :over_limit" do
- assert RESTCallLimits.get_api_remaining_calls(:over_limit) == 0
- end
-
- test "nil passes through" do
- assert RESTCallLimits.get_api_remaining_calls(nil) == 0
- end
- end
-
- describe "get_retry_after_header/1" do
- test "pulls out the value " do
- retry_after_header = {"Retry-After", "1.0"}
- response = %Response{headers: [retry_after_header, {"foo", "bar"}, {"bat", "biz"}]}
-
- assert RESTCallLimits.get_retry_after_header(response) == "1.0"
- end
-
- test "defaults to 2.0" do
- response = %Response{headers: [{"foo", "bar"}, {"bat", "biz"}]}
-
- assert RESTCallLimits.get_retry_after_header(response) == "2.0"
- end
- end
-
- describe "get_retry_after_milliseconds/1" do
- test "Parses the expected value" do
- assert RESTCallLimits.get_retry_after_milliseconds("2.0") == 2000
- end
-
- test "parses decimal value" do
- assert RESTCallLimits.get_retry_after_milliseconds("2.3") == 2300
- assert RESTCallLimits.get_retry_after_milliseconds("2.003") == 2003
- end
-
- test "handles zero leading values" do
- assert RESTCallLimits.get_retry_after_milliseconds("0.2") == 200
- end
- end
-end
diff --git a/test/shopify_api/rate_limiting/rest_tracker_test.exs b/test/shopify_api/rate_limiting/rest_tracker_test.exs
deleted file mode 100644
index 03e93074..00000000
--- a/test/shopify_api/rate_limiting/rest_tracker_test.exs
+++ /dev/null
@@ -1,69 +0,0 @@
-defmodule ShopifyAPI.RateLimiting.RESTTrackerTest do
- use ExUnit.Case
-
- alias HTTPoison.Response
- alias ShopifyAPI.AuthToken
- alias ShopifyAPI.RateLimiting.RESTTracker
-
- describe "api_hit_limit/2" do
- test "returns a 2000 ms delay" do
- call_limit_header = {"X-Shopify-Shop-Api-Call-Limit", "50/50"}
- retry_after_header = {"Retry-After", "2.0"}
-
- response = %Response{headers: [{"foo", "bar"}, call_limit_header, retry_after_header]}
- token = %AuthToken{app_name: "test", shop_name: "shop"}
-
- assert {0, 2000} == RESTTracker.api_hit_limit(token, response)
- end
- end
-
- describe "update_api_call_limit/2" do
- test "back off for 1000 ms when 0 is left" do
- call_limit_header = {"X-Shopify-Shop-Api-Call-Limit", "50/50"}
-
- response = %Response{headers: [{"foo", "bar"}, call_limit_header]}
- token = %AuthToken{app_name: "test", shop_name: "shop"}
-
- assert {0, 1000} == RESTTracker.update_api_call_limit(token, response)
- end
-
- test "does not back off if there is a limit left" do
- call_limit_header = {"X-Shopify-Shop-Api-Call-Limit", "40/50"}
-
- response = %Response{headers: [{"foo", "bar"}, call_limit_header]}
- token = %AuthToken{app_name: "test", shop_name: "shop"}
-
- assert {10, 0} == RESTTracker.update_api_call_limit(token, response)
- end
- end
-
- describe "get/1" do
- test "handles get without having set" do
- now = ~U[2020-01-01 12:00:00.000000Z]
- token = %AuthToken{app_name: "empty", shop_name: "empty"}
-
- assert {40, 0} == RESTTracker.get(token, now, 1)
- end
-
- test "returns with a sleep after hitting limit" do
- call_limit_header = {"X-Shopify-Shop-Api-Call-Limit", "50/50"}
- retry_after_header = {"Retry-After", "2.0"}
- response = %Response{headers: [{"foo", "bar"}, call_limit_header, retry_after_header]}
- token = %AuthToken{app_name: "hit_limit", shop_name: "hit_limit"}
-
- hit_time = ~U[2020-01-01 12:00:00.000000Z]
-
- assert {0, 2000} == RESTTracker.api_hit_limit(token, response, hit_time)
-
- assert {0, 2000} == RESTTracker.get(token, hit_time, 1)
-
- wait_a_second = ~U[2020-01-01 12:00:01.100000Z]
-
- assert {0, 900} == RESTTracker.get(token, wait_a_second, 1)
-
- wait_two_seconds = ~U[2020-01-01 12:00:02.100000Z]
-
- assert {0, 0} == RESTTracker.get(token, wait_two_seconds, 1)
- end
- end
-end
diff --git a/test/shopify_api/rest/product_test.exs b/test/shopify_api/rest/product_test.exs
deleted file mode 100644
index 40ee30d8..00000000
--- a/test/shopify_api/rest/product_test.exs
+++ /dev/null
@@ -1,32 +0,0 @@
-defmodule ShopifyAPI.REST.ProductTest do
- use ExUnit.Case
-
- alias Plug.Conn
- alias ShopifyAPI.{AuthToken, JSONSerializer, Shop}
- alias ShopifyAPI.REST.{Product, Request}
-
- setup _context do
- bypass = Bypass.open()
-
- token = %AuthToken{
- token: "token",
- shop_name: "localhost:#{bypass.port}"
- }
-
- shop = %Shop{domain: "localhost:#{bypass.port}"}
-
- {:ok, %{shop: shop, auth_token: token, bypass: bypass}}
- end
-
- test "", %{bypass: bypass, shop: _shop, auth_token: token} do
- product = %{"product_id" => "_", "title" => "Testing Create Product"}
-
- Bypass.expect_once(bypass, "GET", "/admin/api/#{Request.version()}/products.json", fn conn ->
- {:ok, body} = JSONSerializer.encode(%{products: [product]})
-
- Conn.resp(conn, 200, body)
- end)
-
- assert {:ok, [^product]} = Product.all(token)
- end
-end
diff --git a/test/shopify_api/rest/redirect_test.exs b/test/shopify_api/rest/redirect_test.exs
deleted file mode 100644
index 92e93253..00000000
--- a/test/shopify_api/rest/redirect_test.exs
+++ /dev/null
@@ -1,143 +0,0 @@
-defmodule ShopifyAPI.REST.RedirectTest do
- use ExUnit.Case
-
- alias Plug.Conn
- alias ShopifyAPI.{AuthToken, JSONSerializer, Shop}
- alias ShopifyAPI.REST.{Redirect, Request}
-
- setup _context do
- bypass = Bypass.open()
-
- token = %AuthToken{
- token: "token",
- shop_name: "localhost:#{bypass.port}"
- }
-
- shop = %Shop{domain: "localhost:#{bypass.port}"}
-
- redirect = %{
- "id" => 979_034_144,
- "path" => "/ipod",
- "target" => "/pages/itunes"
- }
-
- {:ok, %{shop: shop, auth_token: token, bypass: bypass, redirect: redirect}}
- end
-
- test "client can request all redirects", %{
- bypass: bypass,
- shop: _shop,
- auth_token: token,
- redirect: redirect
- } do
- Bypass.expect_once(bypass, "GET", "/admin/api/#{Request.version()}/redirects.json", fn conn ->
- {:ok, body} = JSONSerializer.encode(%{redirects: [redirect]})
-
- Conn.resp(conn, 200, body)
- end)
-
- assert {:ok, [redirect]} == Redirect.all(token)
- end
-
- test "client can request a single redirect", %{
- bypass: bypass,
- shop: _shop,
- auth_token: token,
- redirect: redirect
- } do
- Bypass.expect_once(
- bypass,
- "GET",
- "/admin/api/#{Request.version()}/redirects/#{redirect["id"]}.json",
- fn conn ->
- {:ok, body} = JSONSerializer.encode(%{redirect: redirect})
-
- Conn.resp(conn, 200, body)
- end
- )
-
- assert {:ok, redirect} == Redirect.get(token, redirect["id"])
- end
-
- test "client can request a redirect count", %{
- bypass: bypass,
- shop: _shop,
- auth_token: token,
- redirect: _redirect
- } do
- count = 1234
-
- Bypass.expect_once(
- bypass,
- "GET",
- "/admin/api/#{Request.version()}/redirects/count.json",
- fn conn ->
- {:ok, body} = JSONSerializer.encode(%{redirects: count})
-
- Conn.resp(conn, 200, body)
- end
- )
-
- assert {:ok, count} == Redirect.count(token)
- end
-
- test "client can request to create a redirect", %{
- bypass: bypass,
- shop: _shop,
- auth_token: token,
- redirect: redirect
- } do
- Bypass.expect_once(
- bypass,
- "POST",
- "/admin/api/#{Request.version()}/redirects.json",
- fn conn ->
- {:ok, body} = JSONSerializer.encode(%{redirect: redirect})
-
- Conn.resp(conn, 200, body)
- end
- )
-
- assert {:ok, redirect} == Redirect.create(token, %{redirect: redirect})
- end
-
- test "client can request to update an redirect", %{
- bypass: bypass,
- shop: _shop,
- auth_token: token,
- redirect: redirect
- } do
- Bypass.expect_once(
- bypass,
- "PUT",
- "/admin/api/#{Request.version()}/redirects/#{redirect["id"]}.json",
- fn conn ->
- {:ok, body} = JSONSerializer.encode(%{redirect: redirect})
-
- Conn.resp(conn, 200, body)
- end
- )
-
- assert {:ok, redirect} == Redirect.update(token, %{"redirect" => redirect})
- end
-
- test "client can request to delete an redirect", %{
- bypass: bypass,
- shop: _shop,
- auth_token: token,
- redirect: redirect
- } do
- Bypass.expect_once(
- bypass,
- "DELETE",
- "/admin/api/#{Request.version()}/redirects/#{redirect["id"]}.json",
- fn conn ->
- {:ok, body} = JSONSerializer.encode([])
-
- Conn.resp(conn, 200, body)
- end
- )
-
- assert {:ok, {:ok, []}} == Redirect.delete(token, redirect["id"])
- end
-end
diff --git a/test/shopify_api/rest_test.exs b/test/shopify_api/rest_test.exs
deleted file mode 100644
index 390679bb..00000000
--- a/test/shopify_api/rest_test.exs
+++ /dev/null
@@ -1,148 +0,0 @@
-defmodule ShopifyAPI.RESTTest do
- use ExUnit.Case
-
- import Bypass, only: [expect_once: 4]
-
- alias ShopifyAPI.AuthToken
- alias ShopifyAPI.REST
- alias ShopifyAPI.REST.Request
-
- defmodule MockAPIResponses do
- import Plug.Conn
-
- # Used to test that the Shopify auth header is set
- def assert_auth_header_set(%{req_headers: req_headers} = conn) do
- headers = Enum.into(req_headers, %{})
- assert headers["x-shopify-access-token"] == "token"
- resp(conn, 200, "{}")
- end
-
- def success(status \\ 200, body \\ "{}"),
- do: generate_response(status, body)
-
- def failure(status \\ 500, body \\ "{}"),
- do: generate_response(status, body)
-
- defp generate_response(status, body) when is_integer(status) and is_binary(body) do
- fn conn -> resp(conn, status, body) end
- end
- end
-
- setup do
- bypass = Bypass.open()
- token = %AuthToken{token: "token", shop_name: "localhost:#{bypass.port}"}
- {:ok, %{token: token, bypass: bypass}}
- end
-
- test "adds API auth header to outgoing requests", %{bypass: bypass, token: token} do
- expect_once(
- bypass,
- "GET",
- "/admin/api/#{Request.version()}/example",
- &MockAPIResponses.assert_auth_header_set/1
- )
-
- assert {:ok, _} = REST.get(token, "example")
- end
-
- describe "GET" do
- test "returns ok when returned status code is 200", %{bypass: bypass, token: token} do
- expect_once(
- bypass,
- "GET",
- "/admin/api/#{Request.version()}/example",
- MockAPIResponses.success()
- )
-
- assert {:ok, _} = REST.get(token, "example")
- end
-
- test "returns errors from API on non-200 responses", %{bypass: bypass, token: token} do
- expect_once(
- bypass,
- "GET",
- "/admin/api/#{Request.version()}/example",
- MockAPIResponses.failure()
- )
-
- assert {:error, %{status_code: 500}} = REST.get(token, "example")
- end
- end
-
- describe "POST" do
- test "returns ok when returned status code is 201", %{bypass: bypass, token: token} do
- expect_once(
- bypass,
- "POST",
- "/admin/api/#{Request.version()}/example",
- MockAPIResponses.success(201)
- )
-
- assert {:ok, _} = REST.post(token, "example", %{})
- end
-
- test "returns errors from API on non-200 responses", %{bypass: bypass, token: token} do
- expect_once(
- bypass,
- "POST",
- "/admin/api/#{Request.version()}/example",
- MockAPIResponses.failure(422)
- )
-
- assert {:error, %{status_code: 422}} = REST.post(token, "example", "")
- end
- end
-
- describe "DELETE" do
- test "is successful when API returns a 2XX status", %{bypass: bypass, token: token} do
- expect_once(
- bypass,
- "DELETE",
- "/admin/api/#{Request.version()}/example",
- MockAPIResponses.success(200)
- )
-
- assert {:ok, _} = REST.delete(token, "example")
- end
-
- test "returns errors from API on non-200 responses", %{bypass: bypass, token: token} do
- expect_once(
- bypass,
- "DELETE",
- "/admin/api/#{Request.version()}/example",
- MockAPIResponses.failure(404)
- )
-
- assert {:error, %{status_code: 404}} = REST.delete(token, "example")
- end
- end
-
- describe "extract_results_and_next_link" do
- test "returns next link if found" do
- headers = [{"Link", "; rel=\"next\""}]
- response = %HTTPoison.Response{body: "", headers: headers}
- {_, next_link} = Request.extract_results_and_next_link(response)
- assert next_link == "https://example.com?page=2"
- end
-
- test "returns nil if next link not found" do
- headers = [{"Link", "; rel=\"prev\""}]
- response = %HTTPoison.Response{body: "", headers: headers}
- {_, next_link} = Request.extract_results_and_next_link(response)
- assert next_link == nil
- end
-
- test "returns nil if headers are empty" do
- response = %HTTPoison.Response{body: "", headers: []}
- {_, next_link} = Request.extract_results_and_next_link(response)
- assert next_link == nil
- end
-
- test "returns nil if 'Link' header is missing" do
- headers = [{"Content-Type", "application/json"}]
- response = %HTTPoison.Response{body: "", headers: headers}
- {_, next_link} = Request.extract_results_and_next_link(response)
- assert next_link == nil
- end
- end
-end
diff --git a/test/shopify_api/throttled_test.exs b/test/shopify_api/throttled_test.exs
index 1bb3de60..f09ebe7c 100644
--- a/test/shopify_api/throttled_test.exs
+++ b/test/shopify_api/throttled_test.exs
@@ -1,16 +1,10 @@
defmodule Test.ShopifyAPI.ThrottledTest do
use ExUnit.Case
-
- alias ShopifyAPI.{AuthToken, RateLimiting, Throttled}
+ alias ShopifyAPI.AuthToken
+ alias ShopifyAPI.Throttled
@token %AuthToken{app_name: "test", shop_name: "throttled", plus: false}
- setup do
- RateLimiting.RESTTracker.set(@token, 10, 0)
-
- :ok
- end
-
def func, do: send(self(), :func_called)
def sleep_impl(_), do: send(self(), :sleep_called)
@@ -25,17 +19,6 @@ defmodule Test.ShopifyAPI.ThrottledTest do
end
describe "request/6" do
- test "recurses when func returns over limit status code" do
- func = fn ->
- send(self(), :func_called)
- {:ok, %{status_code: RateLimiting.REST.over_limit_status_code()}}
- end
-
- max_tries = 2
- Throttled.request(func, @token, max_tries, TrackerMock)
- for _ <- 1..max_tries, do: assert_received(:func_called)
- end
-
test "recurses when func returns graphql throttled response" do
func = fn ->
send(self(), :func_called)