shopify_graphql 0.2.0 → 0.4.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: 7081c7f634ac890bc428d5eb2e67d260cebf1dae0cb56ee514d375a39de76c2f
4
- data.tar.gz: 48e7c7b931e462502a93359e175ec13858988e5435be1f3e8dc114b75680103c
3
+ metadata.gz: '018b4cef704098a6424fda98cb9805a11e86c29fd3e5a391e5945687a7ddc621'
4
+ data.tar.gz: 1f4e1be2f4b3edbf319251023a6a9d596bf34fa1f877dc51269d0cd9bb5db6f7
5
5
  SHA512:
6
- metadata.gz: a9db31af58e597e5d0b91e66e388ae8d1a2b75afcc08fc0c75e9a3a84ac3ffd4f2b94466c3747ed5131750b19d88283ec274ae6c366ea377368f6d98303a72d4
7
- data.tar.gz: 4b8ad458b06267f51d35b9b1e56d85ec3f7ed4582928cba184567f047c8cd628e6d80d1d70199a004c9a0fbfeacd14bf624e80af4ed7f9b1f10e04ed1664fb12
6
+ metadata.gz: e2d0fdd479419a47c2647dffdc6cf65c1c09dfd6b66b35e2e13df9827b0844f0ee2191471d3a53ac42ddb60ecfec2f180457e61082fb209a385628e49c0a62af
7
+ data.tar.gz: cb05b2a483d83066fc233625938da8243905086baa31b0b29b1b6ff1af82f1b0afd5eb8534b4f3539b9f79fcc6c866a56295db1587a0a168fef33dbfe1242e3a
data/README.md CHANGED
@@ -10,8 +10,8 @@ Less painful way to work with [Shopify Graphql API](https://shopify.dev/api/admi
10
10
  - Graphql webhooks integration
11
11
  - Built-in error handling
12
12
  - No schema and no memory issues
13
+ - Buil-in retry on error
13
14
  - (Planned) Testing helpers
14
- - (Planned) Buil-in retry on error
15
15
  - (Planned) Pre-built calls for common Graphql operations
16
16
 
17
17
  ## Usage
@@ -0,0 +1,68 @@
1
+ module ShopifyGraphql
2
+ class AppSubscriptionFields
3
+ FRAGMENT = <<~GRAPHQL
4
+ fragment AppSubscriptionFields on AppSubscription {
5
+ id
6
+ name
7
+ status
8
+ createdAt
9
+ trialDays
10
+ currentPeriodEnd
11
+ test
12
+ lineItems {
13
+ id
14
+ plan {
15
+ pricingDetails {
16
+ __typename
17
+ ... on AppRecurringPricing {
18
+ price {
19
+ amount
20
+ }
21
+ interval
22
+ }
23
+ ... on AppUsagePricing {
24
+ balanceUsed {
25
+ amount
26
+ }
27
+ cappedAmount {
28
+ amount
29
+ }
30
+ interval
31
+ terms
32
+ }
33
+ }
34
+ }
35
+ }
36
+ }
37
+ GRAPHQL
38
+
39
+ def self.parse(data)
40
+ recurring_line_item = data.lineItems.find do |line_item|
41
+ line_item.plan.pricingDetails.__typename == "AppRecurringPricing"
42
+ end
43
+ recurring_pricing = recurring_line_item&.plan&.pricingDetails
44
+ usage_line_item = data.lineItems.find do |line_item|
45
+ line_item.plan.pricingDetails.__typename == "AppUsagePricing"
46
+ end
47
+ usage_pricing = usage_line_item&.plan&.pricingDetails
48
+
49
+ OpenStruct.new(
50
+ id: data.id,
51
+ name: data.name,
52
+ status: data.status,
53
+ created_at: data.createdAt && Time.parse(data.createdAt),
54
+ trial_days: data.trialDays,
55
+ current_period_end: data.currentPeriodEnd && Time.parse(data.currentPeriodEnd),
56
+ test: data.test,
57
+ recurring_line_item_id: recurring_line_item&.id,
58
+ recurring_price: recurring_pricing&.price&.amount&.to_d,
59
+ recurring_interval: recurring_pricing&.interval,
60
+ usage_line_item_id: usage_line_item&.id,
61
+ usage_balance: usage_pricing&.balanceUsed&.amount&.to_d,
62
+ usage_capped_amount: usage_pricing&.cappedAmount&.amount&.to_d,
63
+ usage_interval: usage_pricing&.interval,
64
+ usage_terms: usage_pricing&.terms
65
+ )
66
+ end
67
+ end
68
+ end
@@ -0,0 +1,34 @@
1
+ module ShopifyGraphql
2
+ class CancelSubscription
3
+ include Mutation
4
+
5
+ MUTATION = <<~GRAPHQL
6
+ mutation appSubscriptionCancel($id: ID!) {
7
+ appSubscriptionCancel(id: $id) {
8
+ appSubscription {
9
+ id
10
+ }
11
+ userErrors {
12
+ field
13
+ message
14
+ }
15
+ }
16
+ }
17
+ GRAPHQL
18
+
19
+ def call(id:)
20
+ response = execute(MUTATION, id: id)
21
+ response.data = response.data.appSubscriptionCancel
22
+ handle_user_errors(response.data)
23
+ response.data = parse_data(response.data)
24
+ response
25
+ end
26
+
27
+ private
28
+
29
+ def parse_data(data)
30
+ subscription = OpenStruct.new(id: data.appSubscription.id)
31
+ OpenStruct.new(subscription: subscription)
32
+ end
33
+ end
34
+ end
@@ -0,0 +1,64 @@
1
+ module ShopifyGraphql
2
+ class CreateRecurringSubscription
3
+ include Mutation
4
+
5
+ MUTATION = <<~GRAPHQL
6
+ #{AppSubscriptionFields::FRAGMENT}
7
+
8
+ mutation appSubscriptionCreate(
9
+ $name: String!,
10
+ $lineItems: [AppSubscriptionLineItemInput!]!,
11
+ $returnUrl: URL!,
12
+ $trialDays: Int,
13
+ $test: Boolean
14
+ ) {
15
+ appSubscriptionCreate(
16
+ name: $name,
17
+ lineItems: $lineItems,
18
+ returnUrl: $returnUrl,
19
+ trialDays: $trialDays,
20
+ test: $test
21
+ ) {
22
+ appSubscription {
23
+ ... AppSubscriptionFields
24
+ }
25
+ confirmationUrl
26
+ userErrors {
27
+ field
28
+ message
29
+ }
30
+ }
31
+ }
32
+ GRAPHQL
33
+
34
+ def call(name:, price:, return_url:, trial_days: nil, test: nil, interval: :monthly)
35
+ payload = {name: name, returnUrl: return_url}
36
+ plan_interval = interval == :monthly ? "EVERY_30_DAYS" : "ANNUAL"
37
+ payload[:lineItems] = [{
38
+ plan: {
39
+ appRecurringPricingDetails: {
40
+ price: {amount: price, currencyCode: "USD"},
41
+ interval: plan_interval
42
+ }
43
+ }
44
+ }]
45
+ payload[:trialDays] = trial_days if trial_days
46
+ payload[:test] = test if test
47
+
48
+ response = execute(MUTATION, **payload)
49
+ response.data = response.data.appSubscriptionCreate
50
+ handle_user_errors(response.data)
51
+ response.data = parse_data(response.data)
52
+ response
53
+ end
54
+
55
+ private
56
+
57
+ def parse_data(data)
58
+ OpenStruct.new(
59
+ subscription: AppSubscriptionFields.parse(data.appSubscription),
60
+ confirmation_url: data.confirmationUrl
61
+ )
62
+ end
63
+ end
64
+ end
@@ -0,0 +1,62 @@
1
+ module ShopifyGraphql
2
+ class CreateUsageSubscription
3
+ include Mutation
4
+
5
+ MUTATION = <<~GRAPHQL
6
+ #{AppSubscriptionFields::FRAGMENT}
7
+
8
+ mutation appSubscriptionCreate(
9
+ $name: String!,
10
+ $returnUrl: URL!,
11
+ $test: Boolean
12
+ $lineItems: [AppSubscriptionLineItemInput!]!,
13
+ ) {
14
+ appSubscriptionCreate(
15
+ name: $name,
16
+ returnUrl: $returnUrl,
17
+ test: $test
18
+ lineItems: $lineItems,
19
+ ) {
20
+ appSubscription {
21
+ ... AppSubscriptionFields
22
+ }
23
+ confirmationUrl
24
+ userErrors {
25
+ field
26
+ message
27
+ }
28
+ }
29
+ }
30
+ GRAPHQL
31
+
32
+ def call(name:, return_url:, terms:, capped_amount:, test: false)
33
+ response = execute(
34
+ MUTATION,
35
+ name: name,
36
+ returnUrl: return_url,
37
+ test: test,
38
+ lineItems: [{
39
+ plan: {
40
+ appUsagePricingDetails: {
41
+ terms: terms,
42
+ cappedAmount: {amount: capped_amount, currencyCode: "USD"}
43
+ }
44
+ }
45
+ }]
46
+ )
47
+ response.data = response.data.appSubscriptionCreate
48
+ handle_user_errors(response.data)
49
+ response.data = parse_data(response.data)
50
+ response
51
+ end
52
+
53
+ private
54
+
55
+ def parse_data(data)
56
+ OpenStruct.new(
57
+ subscription: AppSubscriptionFields.parse(data.appSubscription),
58
+ confirmation_url: data.confirmationUrl
59
+ )
60
+ end
61
+ end
62
+ end
@@ -0,0 +1,33 @@
1
+ module ShopifyGraphql
2
+ class GetAppSubscription
3
+ include Query
4
+
5
+ QUERY = <<~GRAPHQL
6
+ #{AppSubscriptionFields::FRAGMENT}
7
+
8
+ query($id: ID!) {
9
+ node(id: $id) {
10
+ ... AppSubscriptionFields
11
+ }
12
+ }
13
+ GRAPHQL
14
+
15
+ def call(id:)
16
+ response = execute(QUERY, id: id)
17
+ response.data = parse_data(response.data)
18
+ response
19
+ end
20
+
21
+ private
22
+
23
+ def parse_data(data)
24
+ unless data.node
25
+ raise ResourceNotFound.new(200, "Subscription not found")
26
+ end
27
+
28
+ OpenStruct.new(
29
+ subscription: AppSubscriptionFields.parse(data.node),
30
+ )
31
+ end
32
+ end
33
+ end
@@ -1,5 +1,16 @@
1
1
  module ShopifyGraphql
2
2
  class Client
3
+ RETRIABLE_EXCEPTIONS = [
4
+ Errno::ETIMEDOUT,
5
+ Errno::ECONNREFUSED,
6
+ Errno::EHOSTUNREACH,
7
+ 'Timeout::Error',
8
+ Faraday::TimeoutError,
9
+ Faraday::RetriableResponse,
10
+ Faraday::ParsingError,
11
+ Faraday::ConnectionFailed,
12
+ ].freeze
13
+
3
14
  def initialize(api_version = ShopifyAPI::Base.api_version)
4
15
  @api_version = api_version
5
16
  end
@@ -29,6 +40,7 @@ module ShopifyGraphql
29
40
  @connection ||= Faraday.new(url: api_url, headers: request_headers) do |conn|
30
41
  conn.request :json
31
42
  conn.response :json, parser_options: { object_class: OpenStruct }
43
+ conn.request :retry, max: 3, interval: 1, backoff_factor: 2, exceptions: RETRIABLE_EXCEPTIONS
32
44
  end
33
45
  end
34
46
 
@@ -17,7 +17,7 @@ module ShopifyGraphql
17
17
  engine_name 'shopify_graphql'
18
18
  isolate_namespace ShopifyGraphql
19
19
 
20
- initializer "shopify_app.redact_job_params" do
20
+ initializer "shopify_graphql.redact_job_params" do
21
21
  ActiveSupport.on_load(:active_job) do
22
22
  if ActiveJob::Base.respond_to?(:log_arguments?)
23
23
  CreateWebhooksJob.log_arguments = false
@@ -1,3 +1,3 @@
1
1
  module ShopifyGraphql
2
- VERSION = "0.2.0"
2
+ VERSION = "0.4.0"
3
3
  end
@@ -1,3 +1,4 @@
1
+ require 'shopify_api'
1
2
  require 'faraday'
2
3
  require 'faraday_middleware'
3
4
 
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: shopify_graphql
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.0
4
+ version: 0.4.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Kirill Platonov
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2021-12-29 00:00:00.000000000 Z
11
+ date: 2022-06-16 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rails
@@ -17,9 +17,6 @@ dependencies:
17
17
  - - ">="
18
18
  - !ruby/object:Gem::Version
19
19
  version: 5.2.0
20
- - - "<"
21
- - !ruby/object:Gem::Version
22
- version: 8.0.0
23
20
  type: :runtime
24
21
  prerelease: false
25
22
  version_requirements: !ruby/object:Gem::Requirement
@@ -27,9 +24,20 @@ dependencies:
27
24
  - - ">="
28
25
  - !ruby/object:Gem::Version
29
26
  version: 5.2.0
30
- - - "<"
27
+ - !ruby/object:Gem::Dependency
28
+ name: shopify_api
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - ">="
31
32
  - !ruby/object:Gem::Version
32
- version: 8.0.0
33
+ version: '0'
34
+ type: :runtime
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - ">="
39
+ - !ruby/object:Gem::Version
40
+ version: '0'
33
41
  - !ruby/object:Gem::Dependency
34
42
  name: shopify_app
35
43
  requirement: !ruby/object:Gem::Requirement
@@ -82,6 +90,11 @@ files:
82
90
  - LICENSE.txt
83
91
  - README.md
84
92
  - app/controllers/shopify_graphql/graphql_webhooks_controller.rb
93
+ - app/graphql/shopify_graphql/app_subscription_fields.rb
94
+ - app/graphql/shopify_graphql/cancel_subscription.rb
95
+ - app/graphql/shopify_graphql/create_recurring_subscription.rb
96
+ - app/graphql/shopify_graphql/create_usage_subscription.rb
97
+ - app/graphql/shopify_graphql/get_app_subscription.rb
85
98
  - config/routes.rb
86
99
  - lib/shopify_graphql.rb
87
100
  - lib/shopify_graphql/client.rb
@@ -122,7 +135,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
122
135
  - !ruby/object:Gem::Version
123
136
  version: '0'
124
137
  requirements: []
125
- rubygems_version: 3.2.22
138
+ rubygems_version: 3.2.33
126
139
  signing_key:
127
140
  specification_version: 4
128
141
  summary: Less painful way to work with Shopify Graphql API in Ruby.