Skip to content

Commit e5fdb9d

Browse files
authored
Merge branch 'main' into centralize_ruby_version
2 parents 52643d9 + a3e67f0 commit e5fdb9d

File tree

152 files changed

+35790
-11
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

152 files changed

+35790
-11
lines changed

CHANGELOG.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,9 @@ Note: For changes to the API, see https://shopify.dev/changelog?filter=api
77
- [#1071](https://github.com/Shopify/shopify-api-ruby/issues/1071) Fix FulfillmentEvent class types
88
- Fix: InventoryItem class `harmonized_system_code` attribute type which can be either integer, string or nil
99
- Fix: Variant class `inventory_quantity` attribute type which can be either integer, string or nil
10+
- [1293](https://github.com/Shopify/shopify-api-ruby/issues/1293) Add support for using Storefront private access tokens.
11+
- Deprecated passing the public Storefront access token as a positional parameter to the Storefront GraphQL client in favor of using the named parameter. (You probably want to use the private access token for this client anyway.)
12+
- [1305](https://github.com/Shopify/shopify-api-ruby/pull/1305/) Adds support for the `2024-04` API version.
1013

1114
## 14.0.1
1215
- [#1288](https://github.com/Shopify/shopify-api-ruby/pull/1288) Fix FeatureDeprecatedError being raised without a message.

Gemfile.lock

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -141,6 +141,7 @@ GEM
141141

142142
PLATFORMS
143143
arm64-darwin-21
144+
arm64-darwin-23
144145
universal-darwin-22
145146
x86_64-linux
146147

docs/usage/graphql_storefront.md

Lines changed: 13 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,21 @@
11
# Make a Storefront API call
22

3-
The library also allows you to send GraphQL requests to the [Shopify Storefront API](https://shopify.dev/docs/api/storefront). To do that, you can use `ShopifyAPI::Clients::Graphql::Storefront` with the current session and a `storefrontAccessToken`.
3+
The library also allows you to send GraphQL requests to the [Shopify Storefront API](https://shopify.dev/docs/api/storefront). To do that, you can use `ShopifyAPI::Clients::Graphql::Storefront` with either a [private or public Storefront access token](https://shopify.dev/docs/api/usage/authentication#access-tokens-for-the-storefront-api).
44

55
You can obtain Storefront API access tokens for both private apps and sales channels. Please read [our documentation](https://shopify.dev/docs/custom-storefronts/building-with-the-storefront-api/getting-started) to learn more about Storefront Access Tokens.
66

77
Below is an example of how you may query the Storefront API:
88

99
```ruby
1010
# Load the access token as per instructions above
11-
storefront_access_token = ''
11+
storefront_private_access_token = ''
1212
# your shop domain
1313
shop_url = 'shop.myshopify.com'
1414

15-
# initialize the client with session and storefront access token
16-
client = ShopifyAPI::Clients::Graphql::Storefront.new(shop_url, storefront_access_token)
15+
# initialize the client with session and a private Storefront access token
16+
client = ShopifyAPI::Clients::Graphql::Storefront.new(shop_url, private_token: storefront_private_access_token)
17+
# or, alternatively with a public Storefront access token:
18+
# client = ShopifyAPI::Clients::Graphql::Storefront.new(shop_url, public_token: storefront_public_access_token)
1719

1820
query = <<~QUERY
1921
{
@@ -35,14 +37,19 @@ query = <<~QUERY
3537
}
3638
QUERY
3739

38-
response = client.query(query: query)
40+
# You may not need the "Shopify-Storefront-Buyer-IP" header, see its documentation:
41+
# https://shopify.dev/docs/api/usage/authentication#making-server-side-requests
42+
response = client.query(query: query, headers: { "Shopify-Storefront-Buyer-IP": request.ip })
3943
# do something with the returned data
4044
```
4145

4246
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.
4347

4448
```ruby
45-
client = ShopifyAPI::Clients::Graphql::Storefront.new(shop_url, storefront_access_token, api_version: "unstable")
49+
client = ShopifyAPI::Clients::Graphql::Storefront.new(shop_url,
50+
private_token: storefront_private_access_token,
51+
api_version: "unstable"
52+
)
4653
```
4754

4855
Want to make calls to the Admin API? Click [here](graphql.md)

lib/shopify_api/admin_versions.rb

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ module ShopifyAPI
55
module AdminVersions
66
SUPPORTED_ADMIN_VERSIONS = T.let([
77
"unstable",
8+
"2024-04",
89
"2024-01",
910
"2023-10",
1011
"2023-07",
@@ -16,7 +17,7 @@ module AdminVersions
1617
"2022-01",
1718
], T::Array[String])
1819

19-
LATEST_SUPPORTED_ADMIN_VERSION = T.let("2024-01", String)
20+
LATEST_SUPPORTED_ADMIN_VERSION = T.let("2024-04", String)
2021
end
2122

2223
SUPPORTED_ADMIN_VERSIONS = ShopifyAPI::AdminVersions::SUPPORTED_ADMIN_VERSIONS

lib/shopify_api/clients/graphql/storefront.rb

Lines changed: 26 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -5,16 +5,38 @@ module ShopifyAPI
55
module Clients
66
module Graphql
77
class Storefront < Client
8-
sig { params(shop: String, storefront_access_token: String, api_version: T.nilable(String)).void }
9-
def initialize(shop, storefront_access_token, api_version: nil)
8+
sig do
9+
params(
10+
shop: String,
11+
storefront_access_token: T.nilable(String),
12+
private_token: T.nilable(String),
13+
public_token: T.nilable(String),
14+
api_version: T.nilable(String),
15+
).void
16+
end
17+
def initialize(shop, storefront_access_token = nil, private_token: nil, public_token: nil, api_version: nil)
18+
unless storefront_access_token.nil?
19+
warning = <<~WARNING
20+
DEPRECATED: Use the named parameters for the Storefront token instead of passing
21+
the public token as the second argument. Also, you may want to look into using
22+
the Storefront private access token instead:
23+
https://shopify.dev/docs/api/usage/authentication#getting-started-with-private-access
24+
WARNING
25+
ShopifyAPI::Logger.deprecated(warning, "15.0.0")
26+
end
27+
1028
session = Auth::Session.new(
1129
id: shop,
1230
shop: shop,
1331
access_token: "",
1432
is_online: false,
1533
)
1634
super(session: session, base_path: "/api", api_version: api_version)
17-
@storefront_access_token = storefront_access_token
35+
@storefront_access_token = T.let(T.must(private_token || public_token || storefront_access_token), String)
36+
@storefront_auth_header = T.let(
37+
private_token.nil? ? "X-Shopify-Storefront-Access-Token" : "Shopify-Storefront-Private-Token",
38+
String,
39+
)
1840
end
1941

2042
sig do
@@ -26,7 +48,7 @@ def initialize(shop, storefront_access_token, api_version: nil)
2648
).returns(HttpResponse)
2749
end
2850
def query(query:, variables: nil, headers: {}, tries: 1)
29-
T.must(headers).merge!({ "X-Shopify-Storefront-Access-Token": @storefront_access_token })
51+
T.must(headers).merge!({ @storefront_auth_header => @storefront_access_token })
3052
super(query: query, variables: variables, headers: headers, tries: tries)
3153
end
3254
end
Lines changed: 194 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,194 @@
1+
# typed: false
2+
# frozen_string_literal: true
3+
4+
########################################################################################################################
5+
# This file is auto-generated. If you have an issue, please create a GitHub issue. #
6+
########################################################################################################################
7+
8+
module ShopifyAPI
9+
class AbandonedCheckout < ShopifyAPI::Rest::Base
10+
extend T::Sig
11+
12+
@prev_page_info = T.let(Concurrent::ThreadLocalVar.new { nil }, Concurrent::ThreadLocalVar)
13+
@next_page_info = T.let(Concurrent::ThreadLocalVar.new { nil }, Concurrent::ThreadLocalVar)
14+
15+
@api_call_limit = T.let(Concurrent::ThreadLocalVar.new { nil }, Concurrent::ThreadLocalVar)
16+
@retry_request_after = T.let(Concurrent::ThreadLocalVar.new { nil }, Concurrent::ThreadLocalVar)
17+
18+
sig { params(session: T.nilable(ShopifyAPI::Auth::Session), from_hash: T.nilable(T::Hash[T.untyped, T.untyped])).void }
19+
def initialize(session: ShopifyAPI::Context.active_session, from_hash: nil)
20+
21+
@abandoned_checkout_url = T.let(nil, T.nilable(String))
22+
@billing_address = T.let(nil, T.nilable(T::Hash[T.untyped, T.untyped]))
23+
@buyer_accepts_marketing = T.let(nil, T.nilable(T::Boolean))
24+
@buyer_accepts_sms_marketing = T.let(nil, T.nilable(T::Boolean))
25+
@cart_token = T.let(nil, T.nilable(String))
26+
@closed_at = T.let(nil, T.nilable(String))
27+
@completed_at = T.let(nil, T.nilable(String))
28+
@created_at = T.let(nil, T.nilable(String))
29+
@currency = T.let(nil, T.nilable(Currency))
30+
@customer = T.let(nil, T.nilable(Customer))
31+
@customer_locale = T.let(nil, T.nilable(String))
32+
@device_id = T.let(nil, T.nilable(Integer))
33+
@discount_codes = T.let(nil, T.nilable(T::Array[T.untyped]))
34+
@email = T.let(nil, T.nilable(String))
35+
@gateway = T.let(nil, T.nilable(String))
36+
@id = T.let(nil, T.nilable(Integer))
37+
@landing_site = T.let(nil, T.nilable(String))
38+
@line_items = T.let(nil, T.nilable(T::Hash[T.untyped, T.untyped]))
39+
@location_id = T.let(nil, T.nilable(Integer))
40+
@note = T.let(nil, T.nilable(String))
41+
@phone = T.let(nil, T.nilable(String))
42+
@presentment_currency = T.let(nil, T.nilable(String))
43+
@referring_site = T.let(nil, T.nilable(String))
44+
@shipping_address = T.let(nil, T.nilable(T::Hash[T.untyped, T.untyped]))
45+
@shipping_lines = T.let(nil, T.nilable(T::Hash[T.untyped, T.untyped]))
46+
@sms_marketing_phone = T.let(nil, T.nilable(String))
47+
@source_name = T.let(nil, T.nilable(String))
48+
@subtotal_price = T.let(nil, T.nilable(String))
49+
@tax_lines = T.let(nil, T.nilable(T::Hash[T.untyped, T.untyped]))
50+
@taxes_included = T.let(nil, T.nilable(T::Boolean))
51+
@token = T.let(nil, T.nilable(String))
52+
@total_discounts = T.let(nil, T.nilable(String))
53+
@total_duties = T.let(nil, T.nilable(String))
54+
@total_line_items_price = T.let(nil, T.nilable(String))
55+
@total_price = T.let(nil, T.nilable(String))
56+
@total_tax = T.let(nil, T.nilable(String))
57+
@total_weight = T.let(nil, T.nilable(Integer))
58+
@updated_at = T.let(nil, T.nilable(String))
59+
@user_id = T.let(nil, T.nilable(Integer))
60+
61+
super(session: session, from_hash: from_hash)
62+
end
63+
64+
@has_one = T.let({
65+
currency: Currency,
66+
customer: Customer
67+
}, T::Hash[Symbol, Class])
68+
@has_many = T.let({
69+
discount_codes: DiscountCode
70+
}, T::Hash[Symbol, Class])
71+
@paths = T.let([
72+
{http_method: :get, operation: :checkouts, ids: [], path: "checkouts.json"},
73+
{http_method: :get, operation: :checkouts, ids: [], path: "checkouts.json"}
74+
], T::Array[T::Hash[String, T.any(T::Array[Symbol], String, Symbol)]])
75+
76+
sig { returns(T.nilable(String)) }
77+
attr_reader :abandoned_checkout_url
78+
sig { returns(T.nilable(T::Hash[T.untyped, T.untyped])) }
79+
attr_reader :billing_address
80+
sig { returns(T.nilable(T::Boolean)) }
81+
attr_reader :buyer_accepts_marketing
82+
sig { returns(T.nilable(T::Boolean)) }
83+
attr_reader :buyer_accepts_sms_marketing
84+
sig { returns(T.nilable(String)) }
85+
attr_reader :cart_token
86+
sig { returns(T.nilable(String)) }
87+
attr_reader :closed_at
88+
sig { returns(T.nilable(String)) }
89+
attr_reader :completed_at
90+
sig { returns(T.nilable(String)) }
91+
attr_reader :created_at
92+
sig { returns(T.nilable(Currency)) }
93+
attr_reader :currency
94+
sig { returns(T.nilable(Customer)) }
95+
attr_reader :customer
96+
sig { returns(T.nilable(String)) }
97+
attr_reader :customer_locale
98+
sig { returns(T.nilable(Integer)) }
99+
attr_reader :device_id
100+
sig { returns(T.nilable(T::Array[DiscountCode])) }
101+
attr_reader :discount_codes
102+
sig { returns(T.nilable(String)) }
103+
attr_reader :email
104+
sig { returns(T.nilable(String)) }
105+
attr_reader :gateway
106+
sig { returns(T.nilable(Integer)) }
107+
attr_reader :id
108+
sig { returns(T.nilable(String)) }
109+
attr_reader :landing_site
110+
sig { returns(T.nilable(T::Hash[T.untyped, T.untyped])) }
111+
attr_reader :line_items
112+
sig { returns(T.nilable(Integer)) }
113+
attr_reader :location_id
114+
sig { returns(T.nilable(String)) }
115+
attr_reader :note
116+
sig { returns(T.nilable(String)) }
117+
attr_reader :phone
118+
sig { returns(T.nilable(String)) }
119+
attr_reader :presentment_currency
120+
sig { returns(T.nilable(String)) }
121+
attr_reader :referring_site
122+
sig { returns(T.nilable(T::Hash[T.untyped, T.untyped])) }
123+
attr_reader :shipping_address
124+
sig { returns(T.nilable(T::Hash[T.untyped, T.untyped])) }
125+
attr_reader :shipping_lines
126+
sig { returns(T.nilable(String)) }
127+
attr_reader :sms_marketing_phone
128+
sig { returns(T.nilable(String)) }
129+
attr_reader :source_name
130+
sig { returns(T.nilable(String)) }
131+
attr_reader :subtotal_price
132+
sig { returns(T.nilable(T::Hash[T.untyped, T.untyped])) }
133+
attr_reader :tax_lines
134+
sig { returns(T.nilable(T::Boolean)) }
135+
attr_reader :taxes_included
136+
sig { returns(T.nilable(String)) }
137+
attr_reader :token
138+
sig { returns(T.nilable(String)) }
139+
attr_reader :total_discounts
140+
sig { returns(T.nilable(String)) }
141+
attr_reader :total_duties
142+
sig { returns(T.nilable(String)) }
143+
attr_reader :total_line_items_price
144+
sig { returns(T.nilable(String)) }
145+
attr_reader :total_price
146+
sig { returns(T.nilable(String)) }
147+
attr_reader :total_tax
148+
sig { returns(T.nilable(Integer)) }
149+
attr_reader :total_weight
150+
sig { returns(T.nilable(String)) }
151+
attr_reader :updated_at
152+
sig { returns(T.nilable(Integer)) }
153+
attr_reader :user_id
154+
155+
class << self
156+
sig do
157+
params(
158+
since_id: T.untyped,
159+
created_at_min: T.untyped,
160+
created_at_max: T.untyped,
161+
updated_at_min: T.untyped,
162+
updated_at_max: T.untyped,
163+
status: T.untyped,
164+
limit: T.untyped,
165+
session: Auth::Session,
166+
kwargs: T.untyped
167+
).returns(T.untyped)
168+
end
169+
def checkouts(
170+
since_id: nil,
171+
created_at_min: nil,
172+
created_at_max: nil,
173+
updated_at_min: nil,
174+
updated_at_max: nil,
175+
status: nil,
176+
limit: nil,
177+
session: ShopifyAPI::Context.active_session,
178+
**kwargs
179+
)
180+
request(
181+
http_method: :get,
182+
operation: :checkouts,
183+
session: session,
184+
ids: {},
185+
params: {since_id: since_id, created_at_min: created_at_min, created_at_max: created_at_max, updated_at_min: updated_at_min, updated_at_max: updated_at_max, status: status, limit: limit}.merge(kwargs).compact,
186+
body: {},
187+
entity: nil,
188+
)
189+
end
190+
191+
end
192+
193+
end
194+
end
Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
# typed: false
2+
# frozen_string_literal: true
3+
4+
########################################################################################################################
5+
# This file is auto-generated. If you have an issue, please create a GitHub issue. #
6+
########################################################################################################################
7+
8+
module ShopifyAPI
9+
class AccessScope < ShopifyAPI::Rest::Base
10+
extend T::Sig
11+
12+
@prev_page_info = T.let(Concurrent::ThreadLocalVar.new { nil }, Concurrent::ThreadLocalVar)
13+
@next_page_info = T.let(Concurrent::ThreadLocalVar.new { nil }, Concurrent::ThreadLocalVar)
14+
15+
@api_call_limit = T.let(Concurrent::ThreadLocalVar.new { nil }, Concurrent::ThreadLocalVar)
16+
@retry_request_after = T.let(Concurrent::ThreadLocalVar.new { nil }, Concurrent::ThreadLocalVar)
17+
18+
sig { params(session: T.nilable(ShopifyAPI::Auth::Session), from_hash: T.nilable(T::Hash[T.untyped, T.untyped])).void }
19+
def initialize(session: ShopifyAPI::Context.active_session, from_hash: nil)
20+
21+
@handle = T.let(nil, T.nilable(String))
22+
@access_scopes = T.let(nil, T.nilable(T::Array[T.untyped]))
23+
24+
super(session: session, from_hash: from_hash)
25+
end
26+
27+
@has_one = T.let({}, T::Hash[Symbol, Class])
28+
@has_many = T.let({}, T::Hash[Symbol, Class])
29+
@custom_prefix = T.let("/admin/oauth", T.nilable(String))
30+
@paths = T.let([
31+
{http_method: :get, operation: :get, ids: [], path: "access_scopes.json"}
32+
], T::Array[T::Hash[String, T.any(T::Array[Symbol], String, Symbol)]])
33+
34+
sig { returns(T.nilable(String)) }
35+
attr_reader :handle
36+
sig { returns(T.nilable(T::Array[T::Hash[T.untyped, T.untyped]])) }
37+
attr_reader :access_scopes
38+
39+
class << self
40+
sig do
41+
params(
42+
session: Auth::Session,
43+
kwargs: T.untyped
44+
).returns(T::Array[AccessScope])
45+
end
46+
def all(
47+
session: ShopifyAPI::Context.active_session,
48+
**kwargs
49+
)
50+
response = base_find(
51+
session: session,
52+
ids: {},
53+
params: {}.merge(kwargs).compact,
54+
)
55+
56+
T.cast(response, T::Array[AccessScope])
57+
end
58+
59+
end
60+
61+
end
62+
end

0 commit comments

Comments
 (0)