shopify_api 13.2.0 → 13.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- 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
|