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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: b83eabed3d0c78f619d6061eb4bb92c389e1d15afca55225c243c0200a73f1f9
4
- data.tar.gz: 2d6858dda679bb4a65f2eddbbc3d746f6177eda1808109a1ebcce943ae5cb9b9
3
+ metadata.gz: 3242835d9dedea2805ab36b498f6fc5b1e778584b6edf05d07c894cf87bf1dec
4
+ data.tar.gz: 6953d7096849c3ee5b685ec708ef3d0191252f6c48adaa97c163487c73c52687
5
5
  SHA512:
6
- metadata.gz: fb175ef43080cec7459eff1a7a40c3d0c48aabc8b69bd8fe10fba1bdcfb3c3ca9a9d4e5e5bd6184421a0639f06b18097efa151c912439198f28838a6f60b5b67
7
- data.tar.gz: 121a72ef9cc5b608b96d5be67a9404f739598708e9649fd720b21fa7614f2d53f162d2e12872441bf4419318d5cb7f13721606239ce21f9bbfa3868e1c4153f8
6
+ metadata.gz: c407661dca2a62ba8815cc42371471eccc5a6cf4a1633aac95b9506ade343e89b5d4831376ff8a994093a7a721b2f4ac1708f736b1c4f8df7c17a978407188c0
7
+ data.tar.gz: c7eb834293eb3c5101b6fe17fb2ee4bc7771e8e9cf9f747c77f2cdb5ba123346cad392eef52b1c4cf323270ee9e26bdc60e475a38512d4d7b097f54744d93caa
data/.github/CODEOWNERS CHANGED
@@ -1 +1 @@
1
- * @shopify/learn-libs-superteam
1
+ * @Shopify/client-libraries-app-templates
@@ -20,6 +20,10 @@ jobs:
20
20
  uses: ruby/setup-ruby@v1
21
21
  with:
22
22
  ruby-version: ${{ matrix.version }}
23
+ - name: Install OpenSSL
24
+ run: |
25
+ sudo apt-get update
26
+ sudo apt-get install -y libssl-dev
23
27
  - name: Run Bundle Commands
24
28
  run: |
25
29
  bundle config set --with docs
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.2.0)
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.1.2.1)
52
+ parser (3.2.2.4)
54
53
  ast (~> 2.4.1)
55
- prettier_print (0.1.0)
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, "Failed to parse session token '#{token}'"
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
- # TODO: replace this call with the HTTP client once it is built
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
- response = HTTParty.post("https://#{auth_query.shop}/admin/oauth/access_token", body: body)
76
- unless response.ok?
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 #{response.code} error while requesting access token."
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
- @base_uri = T.let("https://#{session.shop}", String)
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
@@ -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?
@@ -2,5 +2,5 @@
2
2
  # frozen_string_literal: true
3
3
 
4
4
  module ShopifyAPI
5
- VERSION = "13.2.0"
5
+ VERSION = "13.3.0"
6
6
  end
@@ -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.2.0
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-10-10 00:00:00.000000000 Z
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.20
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