diff --git a/CHANGELOG.md b/CHANGELOG.md index 0196b41d4..662dfc5bd 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -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 diff --git a/docs/usage/graphql.md b/docs/usage/graphql.md index ccd3188ca..4493f5f5c 100644 --- a/docs/usage/graphql.md +++ b/docs/usage/graphql.md @@ -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 diff --git a/docs/usage/graphql_storefront.md b/docs/usage/graphql_storefront.md index 1bc9631f6..42830734a 100644 --- a/docs/usage/graphql_storefront.md +++ b/docs/usage/graphql_storefront.md @@ -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) diff --git a/docs/usage/rest.md b/docs/usage/rest.md index 7a98877d8..6a1b823f5 100644 --- a/docs/usage/rest.md +++ b/docs/usage/rest.md @@ -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). diff --git a/lib/shopify_api/clients/graphql/admin.rb b/lib/shopify_api/clients/graphql/admin.rb index 24da6af4c..8ee35991c 100644 --- a/lib/shopify_api/clients/graphql/admin.rb +++ b/lib/shopify_api/clients/graphql/admin.rb @@ -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 diff --git a/lib/shopify_api/clients/graphql/client.rb b/lib/shopify_api/clients/graphql/client.rb index 4c85691c9..958cc2166 100644 --- a/lib/shopify_api/clients/graphql/client.rb +++ b/lib/shopify_api/clients/graphql/client.rb @@ -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) + 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 @@ -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, diff --git a/lib/shopify_api/clients/graphql/storefront.rb b/lib/shopify_api/clients/graphql/storefront.rb index 92edd8643..399ba1677 100644 --- a/lib/shopify_api/clients/graphql/storefront.rb +++ b/lib/shopify_api/clients/graphql/storefront.rb @@ -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 diff --git a/lib/shopify_api/clients/rest/admin.rb b/lib/shopify_api/clients/rest/admin.rb index 1af5e9948..04622795e 100644 --- a/lib/shopify_api/clients/rest/admin.rb +++ b/lib/shopify_api/clients/rest/admin.rb @@ -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 diff --git a/test/clients/graphql/admin_test.rb b/test/clients/graphql/admin_test.rb index 5d3cab8e2..d04d92504 100644 --- a/test/clients/graphql/admin_test.rb +++ b/test/clients/graphql/admin_test.rb @@ -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 diff --git a/test/clients/graphql/storefront_test.rb b/test/clients/graphql/storefront_test.rb index 862e3c566..f30f78725 100644 --- a/test/clients/graphql/storefront_test.rb +++ b/test/clients/graphql/storefront_test.rb @@ -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 diff --git a/test/clients/rest/admin_test.rb b/test/clients/rest/admin_test.rb index a4907df19..626883d9e 100644 --- a/test/clients/rest/admin_test.rb +++ b/test/clients/rest/admin_test.rb @@ -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" + 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, @@ -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) diff --git a/test/context_test.rb b/test/context_test.rb index 517e97824..79a6c9450 100644 --- a/test/context_test.rb +++ b/test/context_test.rb @@ -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)), session_storage: ShopifyAPI::Auth::FileSessionStorage.new, user_agent_prefix: nil, old_api_secret_key: nil, diff --git a/test/test_helper.rb b/test/test_helper.rb index 6bf2915c0..6e21c2cda 100644 --- a/test/test_helper.rb +++ b/test/test_helper.rb @@ -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, diff --git a/test/test_helpers/graphql_client.rb b/test/test_helpers/graphql_client.rb index aa16730b6..289ac4508 100644 --- a/test/test_helpers/graphql_client.rb +++ b/test/test_helpers/graphql_client.rb @@ -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