shopify_api-graphql-request 0.0.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 +7 -0
- data/.env.template +16 -0
- data/.rspec +3 -0
- data/LICENSE.txt +21 -0
- data/README.md +201 -0
- data/Rakefile +8 -0
- data/lib/shopify_api/graphql/request/version.rb +9 -0
- data/lib/shopify_api/graphql/request.rb +206 -0
- metadata +141 -0
checksums.yaml
ADDED
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
---
|
|
2
|
+
SHA256:
|
|
3
|
+
metadata.gz: 0ac24b90edcc2ac73f86627c06801e1ef9ae67a470cd466befaacc920009e9c3
|
|
4
|
+
data.tar.gz: 8f56fd88505e60ce25cd4287b7ac781e9874f8507cf76a83080277953bec152a
|
|
5
|
+
SHA512:
|
|
6
|
+
metadata.gz: 5cbb9adffc7ce34f8a46eee7698955153402ca5bd72232bf25653409d99be4c766b8cddf302ec7e42506c0db26d3e76e877c08b640750aec7306c1424c5781ea
|
|
7
|
+
data.tar.gz: 5aa3ddc3ba5dca7315e3a1a9e3af2f80389f3391cd09dae55986f8ba47d43319f70dd134808a34819105616ca4e38bc31054a2611294d58e76a15a57e1f7d39d
|
data/.env.template
ADDED
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
# To run tests:
|
|
2
|
+
#
|
|
3
|
+
# 1. Copy this file to .env
|
|
4
|
+
# 2. Fill-in the below variables with valid values.
|
|
5
|
+
# These values will be used by the tests. Data will be written to SHOPIFY_DOMAIN
|
|
6
|
+
#
|
|
7
|
+
|
|
8
|
+
# Must be full domain as it's used in test assertions
|
|
9
|
+
SHOPIFY_DOMAIN=
|
|
10
|
+
SHOPIFY_TOKEN=
|
|
11
|
+
|
|
12
|
+
# Will result in the creation of a metadafield on the customer. write_customers permission required
|
|
13
|
+
SHOPIFY_CUSTOMER_ID=
|
|
14
|
+
|
|
15
|
+
# Must have more than 1 variant values
|
|
16
|
+
SHOPIFY_PRODUCT_ID=
|
data/.rspec
ADDED
data/LICENSE.txt
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
The MIT License (MIT)
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 ScreenStaring
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in
|
|
13
|
+
all copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
|
21
|
+
THE SOFTWARE.
|
data/README.md
ADDED
|
@@ -0,0 +1,201 @@
|
|
|
1
|
+
# ShopifyAPI::GraphQL::Request
|
|
2
|
+
|
|
3
|
+
Small class to simplify the writing and handling of GraphQL queries and mutations for the Shopify Admin API.
|
|
4
|
+
Comes with built-in retry, pagination, error handling, and more!
|
|
5
|
+
|
|
6
|
+
## Usage
|
|
7
|
+
|
|
8
|
+
It's recommended to organize queries and mutations by subclassing `ShopifyAPI::GraphQL::Request`:
|
|
9
|
+
|
|
10
|
+
```rb
|
|
11
|
+
require "shopify_api/graphql/request"
|
|
12
|
+
|
|
13
|
+
class ShopifyProduct < ShopifyAPI::GraphQL::Request
|
|
14
|
+
# Define your queries/mutations
|
|
15
|
+
FIND =<<-GQL
|
|
16
|
+
query($id: ID!) {
|
|
17
|
+
product(id: $id) {
|
|
18
|
+
id
|
|
19
|
+
title
|
|
20
|
+
descriptionHtml
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
GQL
|
|
24
|
+
|
|
25
|
+
UPDATE =<<-GQL
|
|
26
|
+
mutation($product: ProductUpdateInput!) {
|
|
27
|
+
productUpdate(product: $product) {
|
|
28
|
+
product {
|
|
29
|
+
id
|
|
30
|
+
title
|
|
31
|
+
descriptionHtml
|
|
32
|
+
}
|
|
33
|
+
userErrors {
|
|
34
|
+
field
|
|
35
|
+
message
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
GQL
|
|
40
|
+
|
|
41
|
+
LIST <<-GQL
|
|
42
|
+
query($after: String) {
|
|
43
|
+
products(first: 25 after: $after) {
|
|
44
|
+
pageInfo {
|
|
45
|
+
hasNextPage
|
|
46
|
+
endCursor
|
|
47
|
+
}
|
|
48
|
+
edges {
|
|
49
|
+
node {
|
|
50
|
+
id
|
|
51
|
+
title
|
|
52
|
+
descriptionHtml
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
GQL
|
|
58
|
+
|
|
59
|
+
def find(id)
|
|
60
|
+
execute(FIND, :id => gid::Product(id)).dig(:data, :product)
|
|
61
|
+
end
|
|
62
|
+
|
|
63
|
+
def update(id, changes)
|
|
64
|
+
execute(UPDATE, :product => changes.merge(:id => gid::Product(id))).dig(:data, :product_update, :product)
|
|
65
|
+
end
|
|
66
|
+
|
|
67
|
+
def list
|
|
68
|
+
paginate(LIST) { |page| yield page.dig(:data, :products, :edges) }
|
|
69
|
+
end
|
|
70
|
+
end
|
|
71
|
+
```
|
|
72
|
+
|
|
73
|
+
Then use it:
|
|
74
|
+
|
|
75
|
+
```rb
|
|
76
|
+
shopify = ShopifyProduct.new("a-shop", token)
|
|
77
|
+
|
|
78
|
+
begin
|
|
79
|
+
product = shopify.find(123)
|
|
80
|
+
p product[:id]
|
|
81
|
+
p product[:description_html]
|
|
82
|
+
rescue ShopifyAPI::GraphQL::Request::NotFoundError => e
|
|
83
|
+
warn "Product not found: #{e}"
|
|
84
|
+
end
|
|
85
|
+
|
|
86
|
+
begin
|
|
87
|
+
product = shopify.update(123, :description_html => "Something amaaaazing!")
|
|
88
|
+
p product[:id]
|
|
89
|
+
p product[:description_html]
|
|
90
|
+
rescue ShopifyAPI::GraphQL::Request::UserError => e
|
|
91
|
+
warn "User errors:"
|
|
92
|
+
e.errors { |err| warn err["field"] }
|
|
93
|
+
end
|
|
94
|
+
|
|
95
|
+
begin
|
|
96
|
+
shopify.list(123) do |node|
|
|
97
|
+
product = node[:node]
|
|
98
|
+
p product[:id]
|
|
99
|
+
p product[:description_html]
|
|
100
|
+
end
|
|
101
|
+
rescue ShopifyAPI::GraphQL::Request::NotFoundError => e
|
|
102
|
+
warn "Request failed: #{e}"
|
|
103
|
+
end
|
|
104
|
+
```
|
|
105
|
+
|
|
106
|
+
Subclasses have access to the following methods:
|
|
107
|
+
|
|
108
|
+
- `#execute` - Execute a query or mutation with the provided arguments
|
|
109
|
+
- `#paginate` - Execute a query with pagination; without a block a lazy enumerator (`Enumerator::Lazy`) is returned
|
|
110
|
+
- `#gid` - Used for Global ID manipulation (an instance of [`TinyGID`](https://github.com/sshaw/tiny_gid/))
|
|
111
|
+
- `#gql` - The underlying GraphQL client (an instance of [`ShopifyAPI::GraphQL::Tiny`](https://github.com/ScreenStaring/shopify_api-graphql-tiny/))
|
|
112
|
+
|
|
113
|
+
`#execute` and `#paginate` also:
|
|
114
|
+
|
|
115
|
+
- Automatically retry failed or rate-limited requests
|
|
116
|
+
- Accept `snake_case` `Symbol` keys
|
|
117
|
+
- Return a `Hash` with `snake_case` `Symbol` keys
|
|
118
|
+
- Raise a `UserError` when a mutation's response contains `userErrors`
|
|
119
|
+
- Raise a `NotFoundError` when a query's result cannot be found
|
|
120
|
+
|
|
121
|
+
Both of these are small wrappers around the equivalent methods on `ShopifyAPI::GraphQL::Tiny`.
|
|
122
|
+
For more information see [its documentation on retries](https://github.com/ScreenStaring/shopify_api-graphql-tiny#automatically-retrying-failed-requests).
|
|
123
|
+
|
|
124
|
+
With the exception of retry, most defaults can be disabled per instance or per execution:
|
|
125
|
+
|
|
126
|
+
```rb
|
|
127
|
+
class ShopifyProduct < ShopifyAPI::GraphQL::Request
|
|
128
|
+
def initialize(shop, token)
|
|
129
|
+
super(shop, token, :raise_if_not_found => false, :raise_if_user_errors => false, :snake_case => false)
|
|
130
|
+
end
|
|
131
|
+
|
|
132
|
+
def find(gid)
|
|
133
|
+
execute(QUERY, :raise_if_not_found => true)
|
|
134
|
+
end
|
|
135
|
+
end
|
|
136
|
+
```
|
|
137
|
+
|
|
138
|
+
Disabling retry must be done per instance.
|
|
139
|
+
|
|
140
|
+
### Setting the GraphQL API Version
|
|
141
|
+
|
|
142
|
+
Pass the desired version to `Request`'s constructor:
|
|
143
|
+
|
|
144
|
+
```rb
|
|
145
|
+
class ShopifyProduct < ShopifyAPI::GraphQL::Request
|
|
146
|
+
def initialize(shop, token)
|
|
147
|
+
super(shop, token, :version => "2026-01")
|
|
148
|
+
end
|
|
149
|
+
end
|
|
150
|
+
```
|
|
151
|
+
|
|
152
|
+
### Making Requests Without Subclassing
|
|
153
|
+
|
|
154
|
+
Of course you can make requests directly on an instance of `ShopifyAPI::GraphQL::Request`:
|
|
155
|
+
|
|
156
|
+
```rb
|
|
157
|
+
require "shopify_api/graphql/request"
|
|
158
|
+
|
|
159
|
+
request = ShopifyAPI::GraphQL::Request.new("a-shop", token)
|
|
160
|
+
|
|
161
|
+
begin
|
|
162
|
+
product = request.execute(query, :id => "gid://shopify/Product/123").dig(:data, :product)
|
|
163
|
+
p product[:title]
|
|
164
|
+
p product[:description_html]
|
|
165
|
+
rescue ShopifyAPI::GraphQL::Request::NotFoundError => e
|
|
166
|
+
p e
|
|
167
|
+
end
|
|
168
|
+
```
|
|
169
|
+
|
|
170
|
+
And mutations:
|
|
171
|
+
|
|
172
|
+
```rb
|
|
173
|
+
begin
|
|
174
|
+
product = request.execute(mutation, :id => "gid://shopify/Product/123", :title => "Foo Hoo!").dig(:data, :product)
|
|
175
|
+
rescue ShopifyAPI::GraphQL::Request::UserError => e
|
|
176
|
+
p e
|
|
177
|
+
end
|
|
178
|
+
```
|
|
179
|
+
|
|
180
|
+
### More Info
|
|
181
|
+
|
|
182
|
+
For more information checkout [the API docs](https://rdoc.info/gems/shopify_api-graphql-request)
|
|
183
|
+
|
|
184
|
+
## Testing
|
|
185
|
+
|
|
186
|
+
`cp env.template .env` and fill-in `.env` with the missing values. This requires a Shopify store.
|
|
187
|
+
|
|
188
|
+
## See Also
|
|
189
|
+
|
|
190
|
+
- [Shopify Dev Tools](https://github.com/ScreenStaring/shopify-dev-tools/) - Command-line program to assist with the development and/or maintenance of Shopify apps and stores
|
|
191
|
+
- [Shopify ID Export](https://github.com/ScreenStaring/shopify_id_export/) - Dump Shopify product and variant IDs —along with other identifiers— to a CSV or JSON file
|
|
192
|
+
- [`ShopifyAPI::GraphQL::Tiny`](https://github.com/ScreenStaring/shopify_api-graphql-tiny/) - Lightweight, no-nonsense, Shopify GraphQL Admin API client with built-in pagination and retry
|
|
193
|
+
- [`TinyGID`](https://github.com/sshaw/tiny_gid/) - Build Global ID (`gid://`) URI strings from scalar values
|
|
194
|
+
|
|
195
|
+
## License
|
|
196
|
+
|
|
197
|
+
The gem is available as open source under the terms of the [MIT License](https://opensource.org/licenses/MIT).
|
|
198
|
+
|
|
199
|
+
---
|
|
200
|
+
|
|
201
|
+
Made by [ScreenStaring](http://screenstaring.com)
|
data/Rakefile
ADDED
|
@@ -0,0 +1,206 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require "strings/case"
|
|
4
|
+
require "tiny_gid"
|
|
5
|
+
|
|
6
|
+
require "shopify_api/graphql/tiny"
|
|
7
|
+
|
|
8
|
+
module ShopifyAPI
|
|
9
|
+
module GraphQL
|
|
10
|
+
#
|
|
11
|
+
# Small class to simplify the writing and handling of GraphQL queries and mutations for the Shopify Admin API.
|
|
12
|
+
# Comes with built-in retry, pagination, error handling, and more!
|
|
13
|
+
#
|
|
14
|
+
class Request
|
|
15
|
+
Error = Class.new(StandardError)
|
|
16
|
+
|
|
17
|
+
class UserError < Error
|
|
18
|
+
attr_reader :errors
|
|
19
|
+
|
|
20
|
+
def initialize(errors)
|
|
21
|
+
super error_message(errors)
|
|
22
|
+
@errors = errors
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
private
|
|
26
|
+
|
|
27
|
+
def error_message(errors)
|
|
28
|
+
errors.map do |error|
|
|
29
|
+
if error["field"]
|
|
30
|
+
sprintf("%s: %s", error["field"].join("."), error["message"])
|
|
31
|
+
else
|
|
32
|
+
error["message"]
|
|
33
|
+
end
|
|
34
|
+
end.join("\n")
|
|
35
|
+
end
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
class NotFoundError < Error
|
|
39
|
+
def initialize(queries, variables)
|
|
40
|
+
if queries.size > 1
|
|
41
|
+
super "No records found for queries #{queries.join(", ")} with #{variables}"
|
|
42
|
+
else
|
|
43
|
+
super "No record found for #{queries[0]} with #{variables}"
|
|
44
|
+
end
|
|
45
|
+
end
|
|
46
|
+
end
|
|
47
|
+
|
|
48
|
+
##
|
|
49
|
+
#
|
|
50
|
+
# Create a new GraphQL client to connect to +shop+
|
|
51
|
+
#
|
|
52
|
+
# === Arguments
|
|
53
|
+
#
|
|
54
|
+
# [shop (String)] Shopify domain to make requests against
|
|
55
|
+
# [token (String)] Shopify API token
|
|
56
|
+
# [options (Hash)] Client options. Optional.
|
|
57
|
+
#
|
|
58
|
+
# === Options
|
|
59
|
+
#
|
|
60
|
+
# [:raise_if_not_found (Boolean)] If +true+ raise a NotFoundError if the requested record is not found. Defaults to +true+.
|
|
61
|
+
# [:raise_if_user_errors (Boolean)] If +true+ raise a UserError if the mutation resulted in user errors. Defaults to +true+.
|
|
62
|
+
# [:snake_case (Boolean)] Convert response `Hash` keys to +snake_case+ symbols. Defaults to +true+.
|
|
63
|
+
#
|
|
64
|
+
# Additional options: those accepted by {ShopifyAPI::GraphQL::Tiny}[https://rdoc.info/gems/shopify_api-graphql-tiny]
|
|
65
|
+
#
|
|
66
|
+
def initialize(shop, token, options = nil)
|
|
67
|
+
@options = (options || {}).dup
|
|
68
|
+
|
|
69
|
+
[:snake_case, :raise_if_not_found, :raise_if_user_errors].each do |name|
|
|
70
|
+
@options[name] = true unless @options.include?(name)
|
|
71
|
+
end
|
|
72
|
+
|
|
73
|
+
@gql = ShopifyAPI::GraphQL::Tiny.new(shop, token, @options)
|
|
74
|
+
|
|
75
|
+
@gid = TinyGID.new("shopify")
|
|
76
|
+
end
|
|
77
|
+
|
|
78
|
+
##
|
|
79
|
+
#
|
|
80
|
+
# Executes a query or mutation
|
|
81
|
+
#
|
|
82
|
+
# === Arguments
|
|
83
|
+
#
|
|
84
|
+
# [query (String)] Query or mutation to execute
|
|
85
|
+
# [token (String)] Optional variables accepted by +query+
|
|
86
|
+
# [options (Hash)] Optional
|
|
87
|
+
#
|
|
88
|
+
# === Options
|
|
89
|
+
#
|
|
90
|
+
# These override the instance's defaults for a single query or mutation.
|
|
91
|
+
#
|
|
92
|
+
# [:raise_if_not_found (Boolean)]
|
|
93
|
+
# [:raise_if_user_errors (Boolean)]
|
|
94
|
+
# [:snake_case (Boolean)]
|
|
95
|
+
#
|
|
96
|
+
# === Returns
|
|
97
|
+
#
|
|
98
|
+
# The GraphQL response +Hash+
|
|
99
|
+
#
|
|
100
|
+
# === Errors
|
|
101
|
+
#
|
|
102
|
+
# * ArgumentError
|
|
103
|
+
# * ShopifyAPI::GraphQL::Request::UserError - the a mutation contains user errors
|
|
104
|
+
# * ShopifyAPI::GraphQL::Request::NotFoundError - if the query cannot be find the given object
|
|
105
|
+
# * ShopifyAPI::GraphQL::Tiny::ConnectionError
|
|
106
|
+
# * ShopifyAPI::GraphQL::Tiny::HTTPError
|
|
107
|
+
# * ShopifyAPI::GraphQL::Tiny::RateLimitError - if the retry attempts have been exceeded
|
|
108
|
+
# * ShopifyAPI::GraphQL::Tiny::GraphQLError
|
|
109
|
+
#
|
|
110
|
+
def execute(query, variables = nil, options = nil)
|
|
111
|
+
options = @options.merge(options || {})
|
|
112
|
+
|
|
113
|
+
variables = camelize_keys(variables) if options[:snake_case]
|
|
114
|
+
|
|
115
|
+
data = gql.execute(query, variables)
|
|
116
|
+
|
|
117
|
+
raise_if_not_found(data, variables) if options[:raise_if_not_found]
|
|
118
|
+
raise_if_user_errors(data) if options[:raise_if_user_errors]
|
|
119
|
+
|
|
120
|
+
data = snake_case_keys(data) if options[:snake_case]
|
|
121
|
+
|
|
122
|
+
data
|
|
123
|
+
end
|
|
124
|
+
|
|
125
|
+
##
|
|
126
|
+
#
|
|
127
|
+
# Executes a query using pagination.
|
|
128
|
+
#
|
|
129
|
+
# Using pagination requires you to include the
|
|
130
|
+
# {PageInfo}[https://shopify.dev/api/admin-graphql/2026-01/objects/PageInfo] in your query.
|
|
131
|
+
#
|
|
132
|
+
# === Arguments
|
|
133
|
+
#
|
|
134
|
+
# Same as #execute but also accepts a block that will be called with each page.
|
|
135
|
+
# If a block not given returns an instance of Enumerator::Lazy that will fetch the next
|
|
136
|
+
# page on each iteration
|
|
137
|
+
#
|
|
138
|
+
# === Errors
|
|
139
|
+
#
|
|
140
|
+
# See #execute
|
|
141
|
+
#
|
|
142
|
+
def paginate(query, variables = nil, options = nil)
|
|
143
|
+
options = @options.merge(options || {})
|
|
144
|
+
|
|
145
|
+
variables = camelize_keys(variables) if options[:snake_case]
|
|
146
|
+
|
|
147
|
+
pager = gql.paginate
|
|
148
|
+
# execute() returns a lazy enumerator so we're not loading everything now.
|
|
149
|
+
pages = pager.execute(query, variables).map do |page|
|
|
150
|
+
raise_if_not_found(page, variables) if options[:raise_if_not_found]
|
|
151
|
+
raise_if_user_errors(page) if options[:raise_if_user_errors]
|
|
152
|
+
|
|
153
|
+
page = snake_case_keys(page) if options[:snake_case]
|
|
154
|
+
page
|
|
155
|
+
end
|
|
156
|
+
|
|
157
|
+
return pages unless block_given?
|
|
158
|
+
|
|
159
|
+
pages.each { |page| yield page }
|
|
160
|
+
|
|
161
|
+
nil
|
|
162
|
+
end
|
|
163
|
+
|
|
164
|
+
protected
|
|
165
|
+
|
|
166
|
+
attr_reader :gql, :gid
|
|
167
|
+
|
|
168
|
+
def raise_if_not_found(data, variables)
|
|
169
|
+
not_found = data["data"].select { |key, value| value.nil? }
|
|
170
|
+
return unless not_found.any?
|
|
171
|
+
|
|
172
|
+
raise NotFoundError.new(not_found.keys, variables)
|
|
173
|
+
end
|
|
174
|
+
|
|
175
|
+
def raise_if_user_errors(data)
|
|
176
|
+
# FIXME: this does not account for multiple queries
|
|
177
|
+
# Structure is { "data" => QUERY => { "userErrors" => [] } }
|
|
178
|
+
data = data["data"].values[0]
|
|
179
|
+
return unless data && data["userErrors"] && data["userErrors"].any?
|
|
180
|
+
|
|
181
|
+
raise UserError, data["userErrors"]
|
|
182
|
+
end
|
|
183
|
+
|
|
184
|
+
def camelize_keys(object)
|
|
185
|
+
transform_keys(object) { |key| Strings::Case.camelcase(key.to_s) }
|
|
186
|
+
end
|
|
187
|
+
|
|
188
|
+
def snake_case_keys(object)
|
|
189
|
+
transform_keys(object) { |key| Strings::Case.snakecase(key).to_sym }
|
|
190
|
+
end
|
|
191
|
+
|
|
192
|
+
def transform_keys(object, &transformer)
|
|
193
|
+
case object
|
|
194
|
+
when Hash
|
|
195
|
+
object.each_with_object({}) do |(key, value), result|
|
|
196
|
+
result[transformer[key]] = transform_keys(value, &transformer)
|
|
197
|
+
end
|
|
198
|
+
when Array
|
|
199
|
+
object.map { |value| transform_keys(value, &transformer) }
|
|
200
|
+
else
|
|
201
|
+
object
|
|
202
|
+
end
|
|
203
|
+
end
|
|
204
|
+
end
|
|
205
|
+
end
|
|
206
|
+
end
|
metadata
ADDED
|
@@ -0,0 +1,141 @@
|
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
|
2
|
+
name: shopify_api-graphql-request
|
|
3
|
+
version: !ruby/object:Gem::Version
|
|
4
|
+
version: 0.0.1
|
|
5
|
+
platform: ruby
|
|
6
|
+
authors:
|
|
7
|
+
- Skye Shaw
|
|
8
|
+
bindir: exe
|
|
9
|
+
cert_chain: []
|
|
10
|
+
date: 2026-01-24 00:00:00.000000000 Z
|
|
11
|
+
dependencies:
|
|
12
|
+
- !ruby/object:Gem::Dependency
|
|
13
|
+
name: shopify_api-graphql-tiny
|
|
14
|
+
requirement: !ruby/object:Gem::Requirement
|
|
15
|
+
requirements:
|
|
16
|
+
- - ">="
|
|
17
|
+
- !ruby/object:Gem::Version
|
|
18
|
+
version: 1.0.1
|
|
19
|
+
- - "<"
|
|
20
|
+
- !ruby/object:Gem::Version
|
|
21
|
+
version: '2'
|
|
22
|
+
type: :runtime
|
|
23
|
+
prerelease: false
|
|
24
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
25
|
+
requirements:
|
|
26
|
+
- - ">="
|
|
27
|
+
- !ruby/object:Gem::Version
|
|
28
|
+
version: 1.0.1
|
|
29
|
+
- - "<"
|
|
30
|
+
- !ruby/object:Gem::Version
|
|
31
|
+
version: '2'
|
|
32
|
+
- !ruby/object:Gem::Dependency
|
|
33
|
+
name: tiny_gid
|
|
34
|
+
requirement: !ruby/object:Gem::Requirement
|
|
35
|
+
requirements:
|
|
36
|
+
- - ">="
|
|
37
|
+
- !ruby/object:Gem::Version
|
|
38
|
+
version: '0'
|
|
39
|
+
type: :runtime
|
|
40
|
+
prerelease: false
|
|
41
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
42
|
+
requirements:
|
|
43
|
+
- - ">="
|
|
44
|
+
- !ruby/object:Gem::Version
|
|
45
|
+
version: '0'
|
|
46
|
+
- !ruby/object:Gem::Dependency
|
|
47
|
+
name: strings-case
|
|
48
|
+
requirement: !ruby/object:Gem::Requirement
|
|
49
|
+
requirements:
|
|
50
|
+
- - ">="
|
|
51
|
+
- !ruby/object:Gem::Version
|
|
52
|
+
version: '0'
|
|
53
|
+
type: :runtime
|
|
54
|
+
prerelease: false
|
|
55
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
56
|
+
requirements:
|
|
57
|
+
- - ">="
|
|
58
|
+
- !ruby/object:Gem::Version
|
|
59
|
+
version: '0'
|
|
60
|
+
- !ruby/object:Gem::Dependency
|
|
61
|
+
name: bundler
|
|
62
|
+
requirement: !ruby/object:Gem::Requirement
|
|
63
|
+
requirements:
|
|
64
|
+
- - ">="
|
|
65
|
+
- !ruby/object:Gem::Version
|
|
66
|
+
version: '0'
|
|
67
|
+
type: :development
|
|
68
|
+
prerelease: false
|
|
69
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
70
|
+
requirements:
|
|
71
|
+
- - ">="
|
|
72
|
+
- !ruby/object:Gem::Version
|
|
73
|
+
version: '0'
|
|
74
|
+
- !ruby/object:Gem::Dependency
|
|
75
|
+
name: rake
|
|
76
|
+
requirement: !ruby/object:Gem::Requirement
|
|
77
|
+
requirements:
|
|
78
|
+
- - ">="
|
|
79
|
+
- !ruby/object:Gem::Version
|
|
80
|
+
version: '13.0'
|
|
81
|
+
type: :development
|
|
82
|
+
prerelease: false
|
|
83
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
84
|
+
requirements:
|
|
85
|
+
- - ">="
|
|
86
|
+
- !ruby/object:Gem::Version
|
|
87
|
+
version: '13.0'
|
|
88
|
+
- !ruby/object:Gem::Dependency
|
|
89
|
+
name: rspec
|
|
90
|
+
requirement: !ruby/object:Gem::Requirement
|
|
91
|
+
requirements:
|
|
92
|
+
- - "~>"
|
|
93
|
+
- !ruby/object:Gem::Version
|
|
94
|
+
version: '3.0'
|
|
95
|
+
type: :development
|
|
96
|
+
prerelease: false
|
|
97
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
98
|
+
requirements:
|
|
99
|
+
- - "~>"
|
|
100
|
+
- !ruby/object:Gem::Version
|
|
101
|
+
version: '3.0'
|
|
102
|
+
email:
|
|
103
|
+
- skye.shaw@gmail.com
|
|
104
|
+
executables: []
|
|
105
|
+
extensions: []
|
|
106
|
+
extra_rdoc_files: []
|
|
107
|
+
files:
|
|
108
|
+
- ".env.template"
|
|
109
|
+
- ".rspec"
|
|
110
|
+
- LICENSE.txt
|
|
111
|
+
- README.md
|
|
112
|
+
- Rakefile
|
|
113
|
+
- lib/shopify_api/graphql/request.rb
|
|
114
|
+
- lib/shopify_api/graphql/request/version.rb
|
|
115
|
+
licenses:
|
|
116
|
+
- MIT
|
|
117
|
+
metadata:
|
|
118
|
+
bug_tracker_uri: https://github.com/ScreenStaring/shopify_api-graphql-request/issues
|
|
119
|
+
changelog_uri: https://github.com/ScreenStaring/shopify_api-graphql-request/blob/master/Changes
|
|
120
|
+
documentation_uri: https://rubydoc.info/gems/shopify_api-graphql-request
|
|
121
|
+
source_code_uri: https://github.com/ScreenStaring/shopify_api-graphql-request
|
|
122
|
+
rdoc_options: []
|
|
123
|
+
require_paths:
|
|
124
|
+
- lib
|
|
125
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
|
126
|
+
requirements:
|
|
127
|
+
- - ">="
|
|
128
|
+
- !ruby/object:Gem::Version
|
|
129
|
+
version: 2.5.0
|
|
130
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
|
131
|
+
requirements:
|
|
132
|
+
- - ">="
|
|
133
|
+
- !ruby/object:Gem::Version
|
|
134
|
+
version: '0'
|
|
135
|
+
requirements: []
|
|
136
|
+
rubygems_version: 3.6.2
|
|
137
|
+
specification_version: 4
|
|
138
|
+
summary: Small class to simplify the writing and handling of GraphQL queries and mutations
|
|
139
|
+
for the Shopify Admin API. Comes with built-in retry, pagination, error handling,
|
|
140
|
+
and more!
|
|
141
|
+
test_files: []
|