Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Allow api version overrides #1104

Merged
merged 6 commits into from
Jan 24, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
Note: For changes to the API, see https://shopify.dev/changelog?filter=api

## Unreleased
- [#1104](https://github.com/Shopify/shopify-api-ruby/pull/1104) Allow api version overrides.

## Version 12.4.0

Expand Down
6 changes: 6 additions & 0 deletions docs/usage/graphql.md
Original file line number Diff line number Diff line change
Expand Up @@ -88,6 +88,12 @@ response = client.query(query: query, variables: variables)
# do something with the reponse
```

By default, the client uses the API version configured in `ShopifyAPI`. To use a different API version, set the optional `api_version` parameter. To experiment with prerelease API features, use `"unstable"` for the API version.

```ruby
client = ShopifyAPI::Clients::Graphql::Admin.new(session: session, api_version: "unstable")
```

Want to make calls to the Storefront API? Click [here](graphql_storefront.md)

# Proxy a GraphQL Query
Expand Down
6 changes: 6 additions & 0 deletions docs/usage/graphql_storefront.md
Original file line number Diff line number Diff line change
Expand Up @@ -39,4 +39,10 @@ response = client.query(query: query)
# do something with the returned data
```

By default, the client uses the API version configured in `ShopifyAPI`. To use a different API version, set the optional `api_version` parameter. To experiment with prerelease API features, use `"unstable"` for the API version.

```ruby
client = ShopifyAPI::Clients::Graphql::Storefront.new(shop_url, storefront_access_token, api_version: "unstable")
```

Want to make calls to the Admin API? Click [here](graphql.md)
7 changes: 7 additions & 0 deletions docs/usage/rest.md
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,13 @@ client.post({

_for more information on the `products` endpoint, [check out our API reference guide](https://shopify.dev/api/admin-rest/unstable/resources/product)._

### Override the `api_version`:

```ruby
# To experiment with prerelease features, pass the api_version "unstable".
client = ShopifyAPI::Clients::Rest::Admin.new(session: session, api_version: "unstable")
```

## Pagination

This library also supports cursor-based pagination for REST Admin API requests. [Learn more about REST request pagination](https://shopify.dev/api/usage/pagination-rest).
Expand Down
6 changes: 3 additions & 3 deletions lib/shopify_api/clients/graphql/admin.rb
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,9 @@ module ShopifyAPI
module Clients
module Graphql
class Admin < Client
sig { params(session: T.nilable(Auth::Session)).void }
def initialize(session:)
super(session: session, base_path: "/admin/api")
sig { params(session: T.nilable(Auth::Session), api_version: T.nilable(String)).void }
def initialize(session:, api_version: nil)
super(session: session, base_path: "/admin/api", api_version: api_version)
end
end
end
Expand Down
16 changes: 13 additions & 3 deletions lib/shopify_api/clients/graphql/client.rb
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,19 @@ module Graphql
class Client
extend T::Sig

sig { params(session: T.nilable(Auth::Session), base_path: String).void }
def initialize(session:, base_path:)
sig { params(session: T.nilable(Auth::Session), base_path: String, api_version: T.nilable(String)).void }
def initialize(session:, base_path:, api_version: nil)
@http_client = T.let(HttpClient.new(session: session, base_path: base_path), HttpClient)
@api_version = T.let(api_version || Context.api_version, String)
ewalk153 marked this conversation as resolved.
Show resolved Hide resolved
if api_version
if api_version == Context.api_version
Context.logger.debug("Graphql client has a redundant API version override "\
"to the default #{Context.api_version}")
else
Context.logger.debug("Graphql client overriding default API version "\
"#{Context.api_version} with #{api_version}")
end
end
end

sig do
Expand All @@ -25,7 +35,7 @@ def query(query:, variables: nil, headers: nil, tries: 1)
@http_client.request(
HttpRequest.new(
http_method: :post,
path: "#{Context.api_version}/graphql.json",
path: "#{@api_version}/graphql.json",
body: body,
query: nil,
extra_headers: headers,
Expand Down
6 changes: 3 additions & 3 deletions lib/shopify_api/clients/graphql/storefront.rb
Original file line number Diff line number Diff line change
Expand Up @@ -5,15 +5,15 @@ module ShopifyAPI
module Clients
module Graphql
class Storefront < Client
sig { params(shop: String, storefront_access_token: String).void }
def initialize(shop, storefront_access_token)
sig { params(shop: String, storefront_access_token: String, api_version: T.nilable(String)).void }
def initialize(shop, storefront_access_token, api_version: nil)
session = Auth::Session.new(
id: shop,
shop: shop,
access_token: "",
is_online: false,
)
super(session: session, base_path: "/api")
super(session: session, base_path: "/api", api_version: api_version)
@storefront_access_token = storefront_access_token
end

Expand Down
17 changes: 14 additions & 3 deletions lib/shopify_api/clients/rest/admin.rb
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,20 @@ module Rest
class Admin < HttpClient
extend T::Sig

sig { params(session: T.nilable(Auth::Session)).void }
def initialize(session: nil)
super(session: session, base_path: "/admin/api/#{Context.api_version}")
sig { params(session: T.nilable(Auth::Session), api_version: T.nilable(String)).void }
def initialize(session: nil, api_version: nil)
@api_version = T.let(api_version || Context.api_version, String)
if api_version
if api_version == Context.api_version
Context.logger.debug("Rest client has a redundant API version override "\
"to the default #{Context.api_version}")
else
Context.logger.debug("Rest client overriding default API version "\
"#{Context.api_version} with #{api_version}")
end
end

super(session: session, base_path: "/admin/api/#{@api_version}")
end

sig do
Expand Down
10 changes: 9 additions & 1 deletion test/clients/graphql/admin_test.rb
Original file line number Diff line number Diff line change
Expand Up @@ -13,12 +13,20 @@ def setup
super
@session = ShopifyAPI::Auth::Session.new(shop: "test-shop.myshopify.com",
access_token: SecureRandom.alphanumeric(10))
@client = ShopifyAPI::Clients::Graphql::Admin.new(session: @session)
@client = build_client
@path = "admin/api"
@expected_headers = TestHelpers::Constants::DEFAULT_CLIENT_HEADERS.merge({
"X-Shopify-Access-Token": @session.access_token,
})
end

def build_client
if !defined?("@api_version")
ShopifyAPI::Clients::Graphql::Admin.new(session: @session)
else
ShopifyAPI::Clients::Graphql::Admin.new(session: @session, api_version: @api_version)
end
end
end
end
end
Expand Down
10 changes: 9 additions & 1 deletion test/clients/graphql/storefront_test.rb
Original file line number Diff line number Diff line change
Expand Up @@ -13,12 +13,20 @@ def setup
super
@shop = "test-shop.myshopify.com"
@storefront_access_token = SecureRandom.alphanumeric(10)
@client = ShopifyAPI::Clients::Graphql::Storefront.new(@shop, @storefront_access_token)
@client = build_client
@path = "api"
@expected_headers = TestHelpers::Constants::DEFAULT_CLIENT_HEADERS.merge({
"X-Shopify-Storefront-Access-Token": @storefront_access_token,
})
end

def build_client
if !defined?("@api_version")
ShopifyAPI::Clients::Graphql::Storefront.new(@shop, @storefront_access_token)
else
ShopifyAPI::Clients::Graphql::Storefront.new(@shop, @storefront_access_token, api_version: @api_version)
end
end
end
end
end
Expand Down
15 changes: 13 additions & 2 deletions test/clients/rest/admin_test.rb
Original file line number Diff line number Diff line change
Expand Up @@ -45,12 +45,21 @@ def test_path_starting_at_admin_overrides_default
assert_equal(response_headers.to_h { |k, v| [k, [v]] }, response.headers)
end

def test_api_version_can_be_overrriden
@api_version = "2022-07"
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Using an instance variable was expedient here. We can always rewrite this as an argument to run_test.

run_test(:post)
end

private

def run_test(http_method, path = "/some-path", expected_path = "some-path.json")
session = ShopifyAPI::Auth::Session.new(shop: "test-shop.myshopify.com",
access_token: SecureRandom.alphanumeric(10))
client = ShopifyAPI::Clients::Rest::Admin.new(session: session)
client = if defined?(@api_version)
ShopifyAPI::Clients::Rest::Admin.new(session: session, api_version: @api_version)
else
ShopifyAPI::Clients::Rest::Admin.new(session: session)
end

request = {
path: path,
Expand All @@ -66,9 +75,11 @@ def run_test(http_method, path = "/some-path", expected_path = "some-path.json")
success_body = { "success" => true }
response_headers = { "content-type" => "application/json" }

api_version = defined?(@api_version) ? @api_version : ShopifyAPI::Context.api_version

stub_request(
http_method,
"https://#{session.shop}/admin/api/#{ShopifyAPI::Context.api_version}/#{expected_path}",
"https://#{session.shop}/admin/api/#{api_version}/#{expected_path}",
)
.with(body: request[:body].to_json, query: request[:query], headers: expected_headers)
.to_return(body: success_body.to_json, headers: response_headers)
Expand Down
1 change: 1 addition & 0 deletions test/context_test.rb
Original file line number Diff line number Diff line change
Expand Up @@ -152,6 +152,7 @@ def test_send_a_warning_if_log_level_is_invalid
scope: [],
is_private: false,
is_embedded: true,
logger: ::Logger.new(T.let(StringIO.new, StringIO)),
Copy link
Member Author

@ewalk153 ewalk153 Jan 24, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Redirect logs to a StringIO to quiet the minitest output. In the future, we can assign the StringIO to an instance variable before passing it in, and check its output to verify logging messages.

session_storage: ShopifyAPI::Auth::FileSessionStorage.new,
user_agent_prefix: nil,
old_api_secret_key: nil,
Expand Down
1 change: 1 addition & 0 deletions test/test_helper.rb
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ def setup
scope: ["scope1", "scope2"],
is_private: false,
is_embedded: false,
logger: ::Logger.new(T.let(StringIO.new, StringIO)), # comment line to see logging on stdout
session_storage: TestHelpers::FakeSessionStorage.new,
user_agent_prefix: nil,
old_api_secret_key: nil,
Expand Down
30 changes: 30 additions & 0 deletions test/test_helpers/graphql_client.rb
Original file line number Diff line number Diff line change
Expand Up @@ -53,5 +53,35 @@ def test_can_make_query_with_variables

@client.query(query: query, variables: variables)
end

def test_can_override_api_version
@api_version = "2022-01"
query = <<~QUERY
query myTestQuery($first: Int) {
products (first: $first) {
edges {
node {
id
title
descriptionHtml
}
}
}
}
QUERY
variables = {
first: 10,
}
setup
body = { query: query, variables: variables }
success_body = { "success" => true }
response_headers = { "content-type" => "application/json" }

stub_request(:post, "https://test-shop.myshopify.com/#{@path}/#{@api_version}/graphql.json")
.with(body: body, headers: @expected_headers)
.to_return(body: success_body.to_json, headers: response_headers)

@client.query(query: query, variables: variables)
end
end
end