shopify_api 13.2.0 → 13.3.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.github/CODEOWNERS +1 -1
- data/.github/workflows/build.yml +4 -0
- data/CHANGELOG.md +6 -0
- data/CONTRIBUTING.md +25 -0
- data/Gemfile.lock +4 -11
- data/ROADMAP.md +10 -0
- data/lib/shopify_api/auth/jwt_payload.rb +2 -2
- data/lib/shopify_api/auth/oauth.rb +15 -5
- data/lib/shopify_api/clients/http_client.rb +5 -1
- data/lib/shopify_api/context.rb +6 -2
- data/lib/shopify_api/version.rb +1 -1
- data/lib/shopify_api/webhooks/registry.rb +16 -0
- data/shopify_api.gemspec +0 -1
- metadata +4 -17
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 3242835d9dedea2805ab36b498f6fc5b1e778584b6edf05d07c894cf87bf1dec
|
4
|
+
data.tar.gz: 6953d7096849c3ee5b685ec708ef3d0191252f6c48adaa97c163487c73c52687
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: c407661dca2a62ba8815cc42371471eccc5a6cf4a1633aac95b9506ade343e89b5d4831376ff8a994093a7a721b2f4ac1708f736b1c4f8df7c17a978407188c0
|
7
|
+
data.tar.gz: c7eb834293eb3c5101b6fe17fb2ee4bc7771e8e9cf9f747c77f2cdb5ba123346cad392eef52b1c4cf323270ee9e26bdc60e475a38512d4d7b097f54744d93caa
|
data/.github/CODEOWNERS
CHANGED
@@ -1 +1 @@
|
|
1
|
-
* @
|
1
|
+
* @Shopify/client-libraries-app-templates
|
data/.github/workflows/build.yml
CHANGED
data/CHANGELOG.md
CHANGED
@@ -4,6 +4,12 @@ Note: For changes to the API, see https://shopify.dev/changelog?filter=api
|
|
4
4
|
|
5
5
|
## Unreleased
|
6
6
|
|
7
|
+
## 13.3.0
|
8
|
+
|
9
|
+
- [#1241](https://github.com/Shopify/shopify-api-ruby/pull/1241) Add `api_host` to `ShopifyAPI::Context.setup`, allowing the API host to be overridden in `ShopifyAPI::Clients::HttpClient`. This context option is intended for internal Shopify use only.
|
10
|
+
- [#1237](https://github.com/Shopify/shopify-api-ruby/pull/1237) Skip mandatory webhook topic registration/unregistrations
|
11
|
+
- [#1239](https://github.com/Shopify/shopify-api-ruby/pull/1239) Update `OAuth.validate_auth_callback` to use `ShopifyApi::Clients::HttpClient`.
|
12
|
+
|
7
13
|
## 13.2.0
|
8
14
|
|
9
15
|
- [#1183](https://github.com/Shopify/shopify-api-ruby/pull/1189) Added string array support for fields parameter in Webhook::Registry
|
data/CONTRIBUTING.md
CHANGED
@@ -1,9 +1,34 @@
|
|
1
1
|
|
2
2
|
Submitting Issues
|
3
3
|
-----------------
|
4
|
+
Submitting Issues
|
4
5
|
|
5
6
|
Please open an issue here if you encounter a specific bug with this API client library or if something is documented here https://shopify.dev/docs/apps but is missing from this package.
|
6
7
|
|
7
8
|
General questions about the Shopify API and usage of this package (not necessarily a bug) should be posted on the [Shopify forums](https://community.shopify.com/c/partners-and-developers/ct-p/appdev).
|
8
9
|
|
9
10
|
When in doubt, post on the forum first. You'll likely have your questions answered more quickly if you post there; more people monitor the forum than Github.
|
11
|
+
|
12
|
+
In order for us to best triage the issue, please include steps to reproduce the issue as well as the impacted feature.
|
13
|
+
|
14
|
+
## Roadmap
|
15
|
+
|
16
|
+
The focus of development efforts by maintainers of this project a roadmap will be proposed via PR and accessible at any point in the ROADMAP.md file.
|
17
|
+
|
18
|
+
Working with a pull request modify the [ROADMAP.md](https://github.com/Shopify/shopify-api-ruby/blob/aa0b7f9a5a9095ca11f3f93f9aecc72e8daa6bce/ROADMAP.md) allows us to invite community feedback on the direction while not adding another communication avenue. While there are certainly better tools for the job than a markdown file for this, we are aiming to keep a minimal toolset to help us better manage the communication channels that we have open.
|
19
|
+
|
20
|
+
If there are concerns with the direction and priorities of the maintainers, this roadmap PR is the appropriate place to share your concerns.
|
21
|
+
|
22
|
+
## Submitting Pull Requests
|
23
|
+
|
24
|
+
We welcome pull requests and help from the community! PRs fixing bugs will take priority to triaging proposed net new functionality. If you do want to add a feature, we recommend opening an issue first exploring the appetite of the community / maintainers to ensure there is alignment on direction before you spend time on the PR.
|
25
|
+
|
26
|
+
## Gem Architecture
|
27
|
+
Understanding how all the components of the Shopify App development stack work together will help best understand what level of abstraction a feature is meant to be applied. Please consider this architecture before introducing new functionally to ensure it is in the right place:
|
28
|
+
|
29
|
+
| Gem Name | Job |
|
30
|
+
|---|---|
|
31
|
+
| Shopify API (this gem) | Obtain a session, clients for APIs (REST, GraphQL), error handling, webhook management |
|
32
|
+
| REST Resources | Interfaces to the APIs. Response casting into defined objects with attributes/methods |
|
33
|
+
| Shopify App | Build Shopify app using Rails conventions. Oauth, webhook processing, persistence, etc |
|
34
|
+
| App Template | Template demonstrating how to use all these components in one starting boilerplate application |
|
data/Gemfile.lock
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
PATH
|
2
2
|
remote: .
|
3
3
|
specs:
|
4
|
-
shopify_api (13.
|
4
|
+
shopify_api (13.3.0)
|
5
5
|
activesupport
|
6
6
|
concurrent-ruby
|
7
7
|
hash_diff
|
@@ -40,7 +40,6 @@ GEM
|
|
40
40
|
concurrent-ruby (~> 1.0)
|
41
41
|
json (2.6.2)
|
42
42
|
jwt (2.7.1)
|
43
|
-
language_server-protocol (3.17.0.1)
|
44
43
|
method_source (1.0.0)
|
45
44
|
mini_mime (1.1.5)
|
46
45
|
minitest (5.15.0)
|
@@ -50,9 +49,9 @@ GEM
|
|
50
49
|
oj (3.16.0)
|
51
50
|
openssl (3.1.0)
|
52
51
|
parallel (1.22.1)
|
53
|
-
parser (3.
|
52
|
+
parser (3.2.2.4)
|
54
53
|
ast (~> 2.4.1)
|
55
|
-
|
54
|
+
racc
|
56
55
|
pry (0.14.1)
|
57
56
|
coderay (~> 1.1)
|
58
57
|
method_source (~> 1.0)
|
@@ -60,6 +59,7 @@ GEM
|
|
60
59
|
byebug (~> 11.0)
|
61
60
|
pry (>= 0.13, < 0.15)
|
62
61
|
public_suffix (4.0.6)
|
62
|
+
racc (1.7.1)
|
63
63
|
rainbow (3.1.1)
|
64
64
|
rake (13.0.6)
|
65
65
|
rbi (0.0.15)
|
@@ -85,10 +85,6 @@ GEM
|
|
85
85
|
rubocop (~> 1.35)
|
86
86
|
rubocop-sorbet (0.6.11)
|
87
87
|
rubocop (>= 0.90.0)
|
88
|
-
ruby-lsp (0.3.2)
|
89
|
-
language_server-protocol (~> 3.17.0)
|
90
|
-
sorbet-runtime
|
91
|
-
syntax_tree (>= 3.4)
|
92
88
|
ruby-progressbar (1.11.0)
|
93
89
|
securerandom (0.2.2)
|
94
90
|
sorbet (0.5.10438)
|
@@ -104,8 +100,6 @@ GEM
|
|
104
100
|
sorbet (>= 0.5.9204)
|
105
101
|
sorbet-runtime (>= 0.5.9204)
|
106
102
|
thor (>= 0.19.2)
|
107
|
-
syntax_tree (3.6.1)
|
108
|
-
prettier_print
|
109
103
|
tapioca (0.10.2)
|
110
104
|
bundler (>= 1.17.3)
|
111
105
|
netrc (>= 0.11.0)
|
@@ -149,7 +143,6 @@ DEPENDENCIES
|
|
149
143
|
rubocop
|
150
144
|
rubocop-shopify
|
151
145
|
rubocop-sorbet
|
152
|
-
ruby-lsp
|
153
146
|
shopify_api!
|
154
147
|
sorbet
|
155
148
|
tapioca
|
data/ROADMAP.md
ADDED
@@ -0,0 +1,10 @@
|
|
1
|
+
# Roadmap
|
2
|
+
|
3
|
+
|Priority|Description|Delivery Time frame|
|
4
|
+
|---|---|---|
|
5
|
+
|P0|Respond timely to open issues/Pull Requests|Ongoing|
|
6
|
+
|P1|Minor API release with support for 10-23 API version|Oct 6 - 13|
|
7
|
+
|P2|Restore dot notation access to GraphQL responses|Oct 26 - Dec 7|
|
8
|
+
|P2|Restrospection GQL queries to define types for GQL resources|October 26- Dec 7|
|
9
|
+
|P2|New token exchange authentication via optional feature flag|October 26- Dec 7|
|
10
|
+
|P3|[Extract REST resources into their own gem](https://github.com/Shopify/shopify-api-ruby/issues/1194)|Oct 26 - Dec 7|
|
@@ -75,8 +75,8 @@ module ShopifyAPI
|
|
75
75
|
def decode_token(token, api_secret_key)
|
76
76
|
JWT.decode(token, api_secret_key, true,
|
77
77
|
{ exp_leeway: JWT_EXPIRATION_LEEWAY, algorithm: "HS256" })[0]
|
78
|
-
rescue
|
79
|
-
raise ShopifyAPI::Errors::InvalidJwtTokenError, "
|
78
|
+
rescue JWT::DecodeError => err
|
79
|
+
raise ShopifyAPI::Errors::InvalidJwtTokenError, "Error decoding session token: #{err.message}"
|
80
80
|
end
|
81
81
|
end
|
82
82
|
end
|
@@ -70,15 +70,25 @@ module ShopifyAPI
|
|
70
70
|
raise Errors::InvalidOauthError,
|
71
71
|
"Invalid state in OAuth callback." unless state == auth_query.state
|
72
72
|
|
73
|
-
|
73
|
+
null_session = Auth::Session.new(shop: auth_query.shop)
|
74
74
|
body = { client_id: Context.api_key, client_secret: Context.api_secret_key, code: auth_query.code }
|
75
|
-
|
76
|
-
|
75
|
+
|
76
|
+
client = Clients::HttpClient.new(session: null_session, base_path: "/admin/oauth")
|
77
|
+
response = begin
|
78
|
+
client.request(
|
79
|
+
Clients::HttpRequest.new(
|
80
|
+
http_method: :post,
|
81
|
+
path: "access_token",
|
82
|
+
body: body,
|
83
|
+
body_type: "application/json",
|
84
|
+
),
|
85
|
+
)
|
86
|
+
rescue ShopifyAPI::Errors::HttpResponseError => e
|
77
87
|
raise Errors::RequestAccessTokenError,
|
78
|
-
"Cannot complete OAuth process. Received a #{
|
88
|
+
"Cannot complete OAuth process. Received a #{e.code} error while requesting access token."
|
79
89
|
end
|
80
|
-
session_params = response.to_h
|
81
90
|
|
91
|
+
session_params = T.cast(response.body, T::Hash[String, T.untyped]).to_h
|
82
92
|
session = create_new_session(session_params, auth_query.shop)
|
83
93
|
|
84
94
|
cookie = if Context.embedded?
|
@@ -13,7 +13,9 @@ module ShopifyAPI
|
|
13
13
|
session ||= Context.active_session
|
14
14
|
raise Errors::NoActiveSessionError, "No passed or active session" unless session
|
15
15
|
|
16
|
-
|
16
|
+
api_host = Context.api_host
|
17
|
+
|
18
|
+
@base_uri = T.let("https://#{api_host || session.shop}", String)
|
17
19
|
@base_uri_and_path = T.let("#{@base_uri}#{base_path}", String)
|
18
20
|
|
19
21
|
user_agent_prefix = Context.user_agent_prefix.nil? ? "" : "#{Context.user_agent_prefix} | "
|
@@ -23,6 +25,8 @@ module ShopifyAPI
|
|
23
25
|
"Accept": "application/json",
|
24
26
|
}, T::Hash[T.any(Symbol, String), T.untyped])
|
25
27
|
|
28
|
+
@headers["Host"] = session.shop unless api_host.nil?
|
29
|
+
|
26
30
|
unless session.access_token.nil? || T.must(session.access_token).empty?
|
27
31
|
@headers["X-Shopify-Access-Token"] = T.cast(session.access_token, String)
|
28
32
|
end
|
data/lib/shopify_api/context.rb
CHANGED
@@ -8,6 +8,7 @@ module ShopifyAPI
|
|
8
8
|
@api_key = T.let("", String)
|
9
9
|
@api_secret_key = T.let("", String)
|
10
10
|
@api_version = T.let(LATEST_SUPPORTED_ADMIN_VERSION, String)
|
11
|
+
@api_host = T.let(nil, T.nilable(String))
|
11
12
|
@scope = T.let(Auth::AuthScopes.new, Auth::AuthScopes)
|
12
13
|
@is_private = T.let(false, T::Boolean)
|
13
14
|
@private_shop = T.let(nil, T.nilable(String))
|
@@ -41,6 +42,7 @@ module ShopifyAPI
|
|
41
42
|
private_shop: T.nilable(String),
|
42
43
|
user_agent_prefix: T.nilable(String),
|
43
44
|
old_api_secret_key: T.nilable(String),
|
45
|
+
api_host: T.nilable(String),
|
44
46
|
).void
|
45
47
|
end
|
46
48
|
def setup(
|
@@ -56,7 +58,8 @@ module ShopifyAPI
|
|
56
58
|
host: ENV["HOST"] || "https://#{host_name}",
|
57
59
|
private_shop: nil,
|
58
60
|
user_agent_prefix: nil,
|
59
|
-
old_api_secret_key: nil
|
61
|
+
old_api_secret_key: nil,
|
62
|
+
api_host: nil
|
60
63
|
)
|
61
64
|
unless ShopifyAPI::AdminVersions::SUPPORTED_ADMIN_VERSIONS.include?(api_version)
|
62
65
|
raise Errors::UnsupportedVersionError,
|
@@ -66,6 +69,7 @@ module ShopifyAPI
|
|
66
69
|
@api_key = api_key
|
67
70
|
@api_secret_key = api_secret_key
|
68
71
|
@api_version = api_version
|
72
|
+
@api_host = api_host
|
69
73
|
@host = T.let(host, T.nilable(String))
|
70
74
|
@is_private = is_private
|
71
75
|
@scope = Auth::AuthScopes.new(scope)
|
@@ -130,7 +134,7 @@ module ShopifyAPI
|
|
130
134
|
end
|
131
135
|
|
132
136
|
sig { returns(T.nilable(String)) }
|
133
|
-
attr_reader :private_shop, :user_agent_prefix, :old_api_secret_key, :host
|
137
|
+
attr_reader :private_shop, :user_agent_prefix, :old_api_secret_key, :host, :api_host
|
134
138
|
|
135
139
|
sig { returns(T::Boolean) }
|
136
140
|
def embedded?
|
data/lib/shopify_api/version.rb
CHANGED
@@ -5,6 +5,11 @@ module ShopifyAPI
|
|
5
5
|
module Webhooks
|
6
6
|
class Registry
|
7
7
|
@registry = T.let({}, T::Hash[String, Registration])
|
8
|
+
MANDATORY_TOPICS = T.let([
|
9
|
+
"shop/redact",
|
10
|
+
"customers/redact",
|
11
|
+
"customers/data_request",
|
12
|
+
].freeze, T::Array[String])
|
8
13
|
|
9
14
|
class << self
|
10
15
|
extend T::Sig
|
@@ -17,6 +22,8 @@ module ShopifyAPI
|
|
17
22
|
metafield_namespaces: T.nilable(T::Array[String])).void
|
18
23
|
end
|
19
24
|
def add_registration(topic:, delivery_method:, path:, handler: nil, fields: nil, metafield_namespaces: nil)
|
25
|
+
return if mandatory_webhook_topic?(topic)
|
26
|
+
|
20
27
|
@registry[topic] = case delivery_method
|
21
28
|
when :pub_sub
|
22
29
|
Registrations::PubSub.new(topic: topic, path: path, fields: fields,
|
@@ -101,6 +108,8 @@ module ShopifyAPI
|
|
101
108
|
).returns(T::Hash[String, T.untyped])
|
102
109
|
end
|
103
110
|
def unregister(topic:, session:)
|
111
|
+
return { "response": nil } if mandatory_webhook_topic?(topic)
|
112
|
+
|
104
113
|
client = Clients::Graphql::Admin.new(session: session)
|
105
114
|
|
106
115
|
webhook_id = get_webhook_id(topic: topic, client: client)
|
@@ -213,6 +222,13 @@ module ShopifyAPI
|
|
213
222
|
def registration_sucessful?(body, mutation_name)
|
214
223
|
!body.dig("data", mutation_name, "webhookSubscription").nil?
|
215
224
|
end
|
225
|
+
|
226
|
+
# Mandatory webhooks are subscribed to via the partner dashboard not the API
|
227
|
+
# https://shopify.dev/docs/apps/webhooks/configuration/mandatory-webhooks
|
228
|
+
sig { params(topic: String).returns(T::Boolean) }
|
229
|
+
def mandatory_webhook_topic?(topic)
|
230
|
+
MANDATORY_TOPICS.include?(topic)
|
231
|
+
end
|
216
232
|
end
|
217
233
|
end
|
218
234
|
end
|
data/shopify_api.gemspec
CHANGED
@@ -48,7 +48,6 @@ Gem::Specification.new do |s|
|
|
48
48
|
s.add_development_dependency("rubocop")
|
49
49
|
s.add_development_dependency("rubocop-shopify")
|
50
50
|
s.add_development_dependency("rubocop-sorbet")
|
51
|
-
s.add_development_dependency("ruby-lsp")
|
52
51
|
s.add_development_dependency("sorbet")
|
53
52
|
s.add_development_dependency("tapioca")
|
54
53
|
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: shopify_api
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 13.
|
4
|
+
version: 13.3.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Shopify
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2023-
|
11
|
+
date: 2023-11-13 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: activesupport
|
@@ -220,20 +220,6 @@ dependencies:
|
|
220
220
|
- - ">="
|
221
221
|
- !ruby/object:Gem::Version
|
222
222
|
version: '0'
|
223
|
-
- !ruby/object:Gem::Dependency
|
224
|
-
name: ruby-lsp
|
225
|
-
requirement: !ruby/object:Gem::Requirement
|
226
|
-
requirements:
|
227
|
-
- - ">="
|
228
|
-
- !ruby/object:Gem::Version
|
229
|
-
version: '0'
|
230
|
-
type: :development
|
231
|
-
prerelease: false
|
232
|
-
version_requirements: !ruby/object:Gem::Requirement
|
233
|
-
requirements:
|
234
|
-
- - ">="
|
235
|
-
- !ruby/object:Gem::Version
|
236
|
-
version: '0'
|
237
223
|
- !ruby/object:Gem::Dependency
|
238
224
|
name: sorbet
|
239
225
|
requirement: !ruby/object:Gem::Requirement
|
@@ -296,6 +282,7 @@ files:
|
|
296
282
|
- LICENSE
|
297
283
|
- README.md
|
298
284
|
- RELEASING.md
|
285
|
+
- ROADMAP.md
|
299
286
|
- Rakefile
|
300
287
|
- SECURITY.md
|
301
288
|
- bin/tapioca
|
@@ -970,7 +957,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
970
957
|
- !ruby/object:Gem::Version
|
971
958
|
version: '0'
|
972
959
|
requirements: []
|
973
|
-
rubygems_version: 3.4.
|
960
|
+
rubygems_version: 3.4.21
|
974
961
|
signing_key:
|
975
962
|
specification_version: 4
|
976
963
|
summary: The gem for accessing the Shopify API
|