shopify_api_bruv 0.2.7 → 0.3.1

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: 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