shopify_api_bruv 0.2.7 → 0.3.1

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 9135e1d7c6f0e40fa48c7cc13eec78b363385029f5b7724e6974557bf77e43c4
4
- data.tar.gz: af5f2e7906ed83e85cdddf93fa11f05e970cafbded61f3a50237f9fe23e98967
3
+ metadata.gz: 0c0d6c9a757b1c4164d65adcd704201932875e5451b7fc452206fce010847f16
4
+ data.tar.gz: 5139a1b215e2d4985857577edc2727e398edae28b068bc20744ec31b57052d81
5
5
  SHA512:
6
- metadata.gz: 974510b1bf78b10321f9a6a165737ec9103e40258defb03805b182c8425dfdef4d9f6c98625e5a8a3717dd7a111bb11f55ea308ffba6f54451b7d84ebc0bd18c
7
- data.tar.gz: bb739d8c212f13bb8baed21ea87b9c0a1391a3ed70c17e7ba4dff1edeacad61e619865a56edac14ab2191c8f5d20a70b5546aaed9789bb397c5c7cf1f0ceaadc
6
+ metadata.gz: 82222f2e7665f99ea63e8c17a7c0445a01e61504ed37ac4c69aaac93704a576e55a813be22e8f4b89e45d85e66e87eea40e7f141f7b8f205f5380bddc89f7dfd
7
+ data.tar.gz: 19f07ef9290a43606159963d7eef46fc135376f90b9a58aad4e51209aca20950aa37dcea68bdf2bf5e269bffaf251bb0be17450fd771a42556f6057701af440f
data/.env.template CHANGED
@@ -2,6 +2,3 @@ API_DOMAIN="{API_DOMAIN}"
2
2
  API_VERSION="{API_VERSION}"
3
3
  API_ACCESS_TOKEN="{API_ACCESS_TOKEN}"
4
4
  SHOPIFY_API_BRUV_LOGGER_ENABLED="true"
5
- SHOPIFY_API_BRUV_REQUEST_MAX_TRIES="3"
6
- SHOPIFY_API_BRUV_REQUEST_SLEEP_TIMER="4"
7
- SHOPIFY_API_BRUV_REQUEST_MINIMUM_CREDIT_LEFT="4"
data/CHANGELOG.md CHANGED
@@ -1,5 +1,14 @@
1
1
  ## [Unreleased]
2
2
 
3
+ ## [0.3.1] - 2023-12-10
4
+
5
+ - Adds error handling for http requests
6
+
7
+ ## [0.3.0] - 2023-12-10
8
+
9
+ - Refactors resource classes
10
+ - Updates docs
11
+
3
12
  ## [0.2.7] - 2023-12-09
4
13
 
5
14
  - Fixes variables not being passed on retry
data/Gemfile.lock CHANGED
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- shopify_api_bruv (0.2.7)
4
+ shopify_api_bruv (0.3.1)
5
5
  httparty
6
6
  logger
7
7
 
data/README.md CHANGED
@@ -17,7 +17,7 @@ If bundler is not being used to manage dependencies, install the gem by executin
17
17
 
18
18
  ## Usage
19
19
 
20
- See [/docs](docs/README.md)
20
+ Visit [/docs](docs/README.md)
21
21
 
22
22
  ## Development
23
23
 
data/docs/README.md CHANGED
@@ -1,101 +1,15 @@
1
- # Documentation
1
+ # Getting started
2
2
 
3
- ## Environment variables
4
-
5
- ```bash
6
- SHOPIFY_API_BRUV_LOGGER_ENABLED="true" # Enables logger, remove or set to false to disable
7
- SHOPIFY_API_BRUV_REQUEST_MAX_TRIES="3" # Max tries for resource class based requests
8
- SHOPIFY_API_BRUV_REQUEST_SLEEP_TIMER="4" # Sleep timer for resource class based requests
9
- SHOPIFY_API_BRUV_REQUEST_MINIMUM_CREDIT_LEFT="4" # Sleeps if credit left reaches this amount
10
- ```
11
-
12
- ## Auth
13
- ```ruby
14
- # Initialize a config
15
- config = ShopifyApiBruv::Auth::Config.new(
16
- api_domain: "shop.myshopify.com",
17
- api_version: "2023-10",
18
- api_access_token: "ACCESS_TOKEN"
19
- )
20
- ```
21
-
22
- ## Usage (GraphQL)
23
-
24
- ### Simple request
25
-
26
- ```ruby
27
- # Initialize a graphql client and provide the config
28
- client = ShopifyApiBruv::Clients::Graphql::Client.new(config:)
29
-
30
- # Define a query
31
- query = <<~GRAPHQL
32
- query {
33
- products(first: 250) {
34
- edges {
35
- node {
36
- id
37
- title
38
- handle
39
- }
40
- }
41
- }
42
- }
43
- GRAPHQL
44
-
45
- # Make the request
46
- client.request(query:)
47
- ```
48
-
49
- ### Using the resource class
3
+ - [Auth](./usage/auth/README.md)
4
+ - [Clients](./usage/clients/README.md)
5
+ - [Resources](./usage/resources/README.md)
50
6
 
51
- ```ruby
52
- class GetProducts < ShopifyApiBruv::Resources::Graphql::Resource
53
- def query
54
- <<~GRAPHQL
55
- query {
56
- products(first: 250) {
57
- edges {
58
- node {
59
- id
60
- title
61
- handle
62
- }
63
- }
64
- }
65
- }
66
- GRAPHQL
67
- end
68
- end
69
-
70
- # Usage
71
- GetProducts.request(config:)
72
- ```
73
-
74
- ## Usage (Rest)
75
-
76
- ### Simple request
77
-
78
- ```ruby
79
- # Initialize a graphql client and provide the config
80
- client = ShopifyApiBruv::Clients::Rest::Client.new(config:)
81
-
82
- # Make the request
83
- client.get(path: '/products')
84
- ```
85
-
86
- ### Using the resource class
87
-
88
- ```ruby
89
- class GetProducts < ShopifyApiBruv::Resources::Rest::Resource
90
- def initialize(config:)
91
- super(
92
- config:,
93
- method: :get,
94
- path: '/products'
95
- )
96
- end
97
- end
7
+ ## Environment variables
98
8
 
99
- # Usage
100
- GetProducts.request(config:)
101
- ```
9
+ | Key | Default value | Type | Required |
10
+ | ------------------------------------------------------ | ------------- | ------- | -------- |
11
+ | `SHOPIFY_API_BRUV_LOGGER_ENABLED` | `false` | Boolean | No |
12
+ | `SHOPIFY_API_BRUV_RESOURCE_GRAPHQL_MAX_TRIES` | `3` | Integer | No |
13
+ | `SHOPIFY_API_BRUV_RESOURCE_GRAPHQL_SLEEP_TIMER` | `4` | Integer | No |
14
+ | `SHOPIFY_API_BRUV_RESOURCE_REST_SLEEP_TIMER` | `4` | Integer | No |
15
+ | `SHOPIFY_API_BRUV_RESOURCE_REST_CREDIT_LEFT_THRESHOLD` | `8` | Integer | No |
@@ -0,0 +1,11 @@
1
+ # Auth
2
+
3
+ This gem requires following configuration to authenticate:
4
+
5
+ ```ruby
6
+ ShopifyApiBruv::Auth::Config.new(
7
+ api_domain: "<api_domain>",
8
+ api_version: "2023-10",
9
+ api_access_token: "<api_access_token>"
10
+ )
11
+ ```
@@ -0,0 +1,4 @@
1
+ # Clients
2
+
3
+ - [GraphQL](./graphql/README.md)
4
+ - [Rest](./rest/README.md)
@@ -0,0 +1,24 @@
1
+ # GraphQL
2
+
3
+ ```ruby
4
+ # Initialize a graphql client
5
+ client = ShopifyApiBruv::Clients::Graphql::Client.new(config:)
6
+
7
+ # Define your query
8
+ query = <<~GRAPHQL
9
+ query {
10
+ products(first: 10) {
11
+ edges {
12
+ node {
13
+ id
14
+ title
15
+ handle
16
+ }
17
+ }
18
+ }
19
+ }
20
+ GRAPHQL
21
+
22
+ # Make the request
23
+ client.request(query:)
24
+ ```
@@ -0,0 +1,9 @@
1
+ # Rest
2
+
3
+ ```ruby
4
+ # Initialize a rest client
5
+ client = ShopifyApiBruv::Clients::Rest::Client.new(config:)
6
+
7
+ # Make the request
8
+ client.get(path: '/products', query: { limit: 10 })
9
+ ```
@@ -0,0 +1,4 @@
1
+ # Resources
2
+
3
+ - [GraphQL](./graphql/README.md)
4
+ - [Rest](./rest/README.md)
@@ -0,0 +1,84 @@
1
+ # GraphQL
2
+
3
+ You can either use the resource class directly:
4
+
5
+ ```ruby
6
+ resource = ShopifyApiBruv::Resources::Graphql::Resource.new(config:)
7
+ resource.query = <<~GRAPHQL
8
+ mutation productCreate($input: ProductInput!) {
9
+ productCreate(input: $input) {
10
+ product {
11
+ title
12
+ }
13
+ userErrors {
14
+ field
15
+ message
16
+ }
17
+ }
18
+ }
19
+ GRAPHQL
20
+ resource.variables = { input: { title: "Test Product" } }
21
+ resource.call
22
+ ```
23
+
24
+
25
+ Or define it as a class inheriting from `ShopifyApiBruv::Resources::Graphql::Resource`
26
+
27
+ ## Query
28
+
29
+ ```ruby
30
+ # frozen_string_literal: true
31
+
32
+ module Shopify
33
+ module Graphql
34
+ class GetProduct < ShopifyApiBruv::Resources::Graphql::Resource
35
+ QUERY = <<~GRAPHQL
36
+ query ($id: ID!) {
37
+ product(id: $id) {
38
+ id
39
+ title
40
+ }
41
+ }
42
+ GRAPHQL
43
+ end
44
+ end
45
+ end
46
+ ```
47
+
48
+ Usage:
49
+
50
+ ```ruby
51
+ Shopify::Graphql::GetProduct.call(config:, variables: { id: "gid://shopify/Product/1234567890" })
52
+ ```
53
+
54
+ ## Mutation
55
+
56
+ ```ruby
57
+ # frozen_string_literal: true
58
+
59
+ module Shopify
60
+ module Graphql
61
+ class CreateProduct < ShopifyApiBruv::Resources::Graphql::Resource
62
+ QUERY = <<~GRAPHQL
63
+ mutation productCreate($input: ProductInput!) {
64
+ productCreate(input: $input) {
65
+ product {
66
+ title
67
+ }
68
+ userErrors {
69
+ field
70
+ message
71
+ }
72
+ }
73
+ }
74
+ GRAPHQL
75
+ end
76
+ end
77
+ end
78
+ ```
79
+
80
+ Usage:
81
+
82
+ ```ruby
83
+ Shopify::Graphql::CreateProduct.call(config:, variables: { input: { title: "Test Product" } })
84
+ ```
@@ -0,0 +1,74 @@
1
+ # Rest
2
+
3
+ You can either use the resource class directly:
4
+
5
+ ```ruby
6
+ resource = ShopifyApiBruv::Resources::Rest::Resource.new(
7
+ config:,
8
+ method: :get,
9
+ path: '/products',
10
+ query: { limit: 10 }
11
+ )
12
+ response = resource.call
13
+
14
+ # Built in pagination example
15
+ loop do
16
+ break if resource.pagination.nil? && !resource.pagination.next_page?
17
+ response = resource.pagination.fetch_next_page
18
+ end
19
+ ```
20
+
21
+ Or define it as a class inheriting from `ShopifyApiBruv::Resources::Rest::Resource`
22
+
23
+ ## Receive data
24
+
25
+ ```ruby
26
+ # frozen_string_literal: true
27
+
28
+ module Shopify
29
+ module Rest
30
+ class GetProduct < ShopifyApiBruv::Resources::Rest::Resource
31
+ def initialize(config:, id:)
32
+ super(
33
+ config:,
34
+ method: :get,
35
+ path: "/products/#{id}"
36
+ )
37
+ end
38
+ end
39
+ end
40
+ end
41
+ ```
42
+
43
+ Usage:
44
+
45
+ ```ruby
46
+ Shopify::Rest::GetProduct.call(config:, id: "1234567890")
47
+ ```
48
+
49
+ ## Populate data
50
+
51
+ ```ruby
52
+ # frozen_string_literal: true
53
+
54
+ module Shopify
55
+ module Rest
56
+ class CreateProduct < ShopifyApiBruv::Resources::Rest::Resource
57
+ def initialize(config:, body:)
58
+ super(
59
+ config:,
60
+ method: :post,
61
+ path: '/products',
62
+ body:
63
+ )
64
+ end
65
+ end
66
+ end
67
+ end
68
+ ```
69
+
70
+ Usage:
71
+
72
+ ```ruby
73
+ Shopify::Rest::CreateProduct.call(config:, body: { product: { title: "Test Product" } })
74
+ ```
@@ -5,6 +5,13 @@ module ShopifyApiBruv
5
5
  class HttpRequest
6
6
  attr_reader :api, :method, :path, :body, :content_type, :query, :headers
7
7
 
8
+ VALID_METHODS = [
9
+ :get,
10
+ :delete,
11
+ :put,
12
+ :post
13
+ ].freeze
14
+
8
15
  def initialize(api:, method:, path:, body:, content_type:, query: nil, headers:)
9
16
  @api = api
10
17
  @method = method
@@ -14,11 +21,27 @@ module ShopifyApiBruv
14
21
  @query = query
15
22
  @headers = headers
16
23
 
24
+ validate
25
+
17
26
  ShopifyApiBruv.logger(
18
27
  method: :info,
19
28
  message: "Shopify API Request (Method: #{method}):\nPath:\n#{path}\n\nBody:\n#{body}"
20
29
  )
21
30
  end
31
+
32
+ private
33
+
34
+ def validate
35
+ raise Errors::HttpRequestError,
36
+ "Invalid method #{method}, valid methods are: #{VALID_METHODS}" unless VALID_METHODS.include?(method)
37
+
38
+ raise Errors::HttpRequestError,
39
+ 'Content-Type missing' if !body.nil? && content_type.nil?
40
+
41
+ return unless [:put, :post].include?(method)
42
+
43
+ raise Errors::HttpRequestError, "Body is required for method #{method}" if body.nil?
44
+ end
22
45
  end
23
46
  end
24
47
  end
@@ -10,12 +10,12 @@ module ShopifyApiBruv
10
10
  @headers = headers
11
11
  @body = body
12
12
 
13
+ validate
14
+
13
15
  ShopifyApiBruv.logger(
14
16
  method: :info,
15
17
  message: "Shopify API Response (Code: #{code}):\nHeaders:\n#{headers}\n\nBody:\n#{body}"
16
18
  )
17
-
18
- validate
19
19
  end
20
20
 
21
21
  private
@@ -0,0 +1,8 @@
1
+ # frozen_string_literal: true
2
+
3
+ module ShopifyApiBruv
4
+ module Errors
5
+ class HttpRequestError < StandardError
6
+ end
7
+ end
8
+ end
@@ -3,8 +3,8 @@
3
3
  module ShopifyApiBruv
4
4
  module Resources
5
5
  class Base
6
- def self.request(...)
7
- new(...).request
6
+ def self.call(...)
7
+ new(...).call
8
8
  end
9
9
  end
10
10
  end
@@ -5,25 +5,29 @@ module ShopifyApiBruv
5
5
  module Graphql
6
6
  class Resource < Base
7
7
  attr_reader :client
8
- attr_accessor :query
8
+ attr_accessor :variables, :query
9
9
 
10
- MAX_TRIES = ENV.fetch('SHOPIFY_API_BRUV_REQUEST_MAX_TRIES', 3).to_i
11
- SLEEP_TIMER = ENV.fetch('SHOPIFY_API_BRUV_REQUEST_SLEEP_TIMER', 4).to_i
12
- MUTATION_OBJECT_NAME_PATTERN = /mutation\s+(\w+)\s*\(.*/
10
+ QUERY = nil
11
+ MAX_TRIES = ENV.fetch('SHOPIFY_API_BRUV_RESOURCE_GRAPHQL_MAX_TRIES', 3).to_i
12
+ SLEEP_TIMER = ENV.fetch('SHOPIFY_API_BRUV_RESOURCE_GRAPHQL_SLEEP_TIMER', 4).to_i
13
13
 
14
- def initialize(config:)
14
+ def initialize(config:, variables: nil)
15
15
  @client = Clients::Graphql::Client.new(config:)
16
+ @variables = variables
17
+ @query = self.class::QUERY unless self.class::QUERY.nil?
16
18
  end
17
19
 
18
- def request(variables: nil, tries: 0)
19
- raise NotImplementedError, 'Please set a query in the derived class' if query.nil?
20
+ def call(tries: 0)
21
+ if query.nil?
22
+ raise Errors::ResourceError, "Please set attribute 'query' or define constant 'QUERY' in derived class"
23
+ end
20
24
 
21
25
  response = client.request(query:, variables:)
22
26
  body = response.body
23
27
 
24
28
  handle_response_errors(body:, query:, variables:, tries:)
25
29
 
26
- mutation_object_name = query.match(MUTATION_OBJECT_NAME_PATTERN)&.captures&.first
30
+ mutation_object_name = query.match(/mutation\s+(\w+)\s*\(.*/)&.captures&.first
27
31
  mutation_object_name.nil? ? body['data'] : body.dig('data', mutation_object_name)
28
32
  end
29
33
 
@@ -37,7 +41,7 @@ module ShopifyApiBruv
37
41
  if errors&.any? { |error| error['message'] == 'Throttled' }
38
42
  sleep(SLEEP_TIMER)
39
43
 
40
- request(variables:, tries: + 1)
44
+ call(tries: + 1)
41
45
  end
42
46
 
43
47
  raise Errors::ResourceError, errors unless errors.nil?
@@ -3,7 +3,7 @@
3
3
  module ShopifyApiBruv
4
4
  module Resources
5
5
  module Rest
6
- class PaginationResource
6
+ class Pagination
7
7
  attr_reader :resource, :page_info
8
8
 
9
9
  def initialize(resource:, page_info:)
@@ -27,14 +27,14 @@ module ShopifyApiBruv
27
27
  raise Errors::ResourceError, 'Next page cursor not found' unless next_page?
28
28
 
29
29
  resource.query[:page_info] = page_info[:next]
30
- resource.request
30
+ resource.call
31
31
  end
32
32
 
33
33
  def fetch_previous_page
34
34
  raise Errors::ResourceError, 'Previous page cursor not found' unless previous_page?
35
35
 
36
36
  resource.query[:page_info] = page_info[:previous]
37
- resource.request
37
+ resource.call
38
38
  end
39
39
  end
40
40
  end
@@ -5,10 +5,10 @@ module ShopifyApiBruv
5
5
  module Rest
6
6
  class Resource < Base
7
7
  attr_reader :client, :method, :path, :body
8
- attr_accessor :query, :pagination_resource
8
+ attr_accessor :query, :pagination
9
9
 
10
- SLEEP_TIMER = ENV.fetch('SHOPIFY_API_BRUV_REQUEST_SLEEP_TIMER', 4).to_i
11
- MINIMUM_CREDIT_LEFT = ENV.fetch('SHOPIFY_API_BRUV_REQUEST_MINIMUM_CREDIT_LEFT', 4).to_i
10
+ SLEEP_TIMER = ENV.fetch('SHOPIFY_API_BRUV_RESOURCE_REST_SLEEP_TIMER', 4).to_i
11
+ CREDIT_LEFT_THRESHOLD = ENV.fetch('SHOPIFY_API_BRUV_RESOURCE_REST_CREDIT_LEFT_THRESHOLD', 8).to_i
12
12
 
13
13
  def initialize(config:, method:, path:, body: nil, query: nil)
14
14
  @client = Clients::Rest::Client.new(config:)
@@ -20,13 +20,13 @@ module ShopifyApiBruv
20
20
  validate_arguments
21
21
  end
22
22
 
23
- def request
23
+ def call
24
24
  response = client.public_send(method, path:, body:, query:)
25
25
 
26
26
  handle_response_api_limits(headers: response.headers)
27
27
 
28
- pagination_resource = PaginationResource.new(resource: self, page_info: response.page_info)
29
- @pagination_resource = pagination_resource if pagination_resource.purpose?
28
+ pagination = Pagination.new(resource: self, page_info: response.page_info)
29
+ @pagination = pagination if pagination.purpose?
30
30
 
31
31
  response.body
32
32
  end
@@ -45,7 +45,7 @@ module ShopifyApiBruv
45
45
  limit = api_call_limit_header.pop.to_i - 1
46
46
  used = api_call_limit_header.shift.to_i
47
47
 
48
- if (limit - used) <= MINIMUM_CREDIT_LEFT
48
+ if (limit - used) <= CREDIT_LEFT_THRESHOLD
49
49
  sleep(SLEEP_TIMER)
50
50
  end
51
51
  end
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module ShopifyApiBruv
4
- VERSION = '0.2.7'
4
+ VERSION = '0.3.1'
5
5
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: shopify_api_bruv
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.7
4
+ version: 0.3.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Idjent
@@ -111,6 +111,13 @@ files:
111
111
  - README.md
112
112
  - Rakefile
113
113
  - docs/README.md
114
+ - docs/usage/auth/README.md
115
+ - docs/usage/clients/README.md
116
+ - docs/usage/clients/graphql/README.md
117
+ - docs/usage/clients/rest/README.md
118
+ - docs/usage/resources/README.md
119
+ - docs/usage/resources/graphql/README.md
120
+ - docs/usage/resources/rest/README.md
114
121
  - lib/shopify_api_bruv.rb
115
122
  - lib/shopify_api_bruv/auth/config.rb
116
123
  - lib/shopify_api_bruv/clients/graphql/client.rb
@@ -120,12 +127,13 @@ files:
120
127
  - lib/shopify_api_bruv/clients/rest/client.rb
121
128
  - lib/shopify_api_bruv/clients/rest/http_response.rb
122
129
  - lib/shopify_api_bruv/errors/http_client_error.rb
130
+ - lib/shopify_api_bruv/errors/http_request_error.rb
123
131
  - lib/shopify_api_bruv/errors/http_response_error.rb
124
132
  - lib/shopify_api_bruv/errors/resource_error.rb
125
133
  - lib/shopify_api_bruv/logger.rb
126
134
  - lib/shopify_api_bruv/resources/base.rb
127
135
  - lib/shopify_api_bruv/resources/graphql/resource.rb
128
- - lib/shopify_api_bruv/resources/rest/pagination_resource.rb
136
+ - lib/shopify_api_bruv/resources/rest/pagination.rb
129
137
  - lib/shopify_api_bruv/resources/rest/resource.rb
130
138
  - lib/shopify_api_bruv/version.rb
131
139
  - sig/shopify_api_bruv.rbs