graphql-extras 0.0.0.pre.2dcd696
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/.github/workflows/build.yml +25 -0
- data/.github/workflows/publish.yml +41 -0
- data/.gitignore +13 -0
- data/.rspec +3 -0
- data/Gemfile +4 -0
- data/README.md +174 -0
- data/Rakefile +6 -0
- data/bin/console +14 -0
- data/bin/setup +8 -0
- data/graphql-extras.gemspec +38 -0
- data/lib/graphql/extras.rb +9 -0
- data/lib/graphql/extras/batch.rb +47 -0
- data/lib/graphql/extras/controller.rb +54 -0
- data/lib/graphql/extras/rspec.rb +133 -0
- data/lib/graphql/extras/types.rb +69 -0
- data/lib/graphql/extras/version.rb +5 -0
- metadata +200 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: 6288183977267b694bbb2b74e36674b2df79736879d60e9b5d5abb5ce4c487d4
|
4
|
+
data.tar.gz: ae68c8cc32d0fe6407c9f21ff2a9b4ee3957d06cabfa25921f14423af3e99be3
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 467b82f5a0c596ab3828157da1b3728d01a6c8332ece4a20f617c31457e33ed4298b4ffa76aa9f47ed6e537ec12af651a2d859bdc57be4e6a60edb33e16f4a09
|
7
|
+
data.tar.gz: a219844d1c1ef0a1c519fd699d18b74ef7f015776fedf1788ff2a2257c67050f07c2dd23fb2acf25705af2e71fa65cb983e7969b9db260dd681b2ad7e029eb9a
|
@@ -0,0 +1,25 @@
|
|
1
|
+
name: Build
|
2
|
+
on: [push]
|
3
|
+
jobs:
|
4
|
+
build:
|
5
|
+
runs-on: ubuntu-latest
|
6
|
+
steps:
|
7
|
+
- name: Checkout
|
8
|
+
uses: actions/checkout@v2
|
9
|
+
|
10
|
+
- name: Setup Ruby
|
11
|
+
uses: actions/setup-ruby@v1
|
12
|
+
with:
|
13
|
+
ruby-version: 2.6.x
|
14
|
+
|
15
|
+
- name: Install packages
|
16
|
+
run: sudo apt-get install libsqlite3-dev
|
17
|
+
|
18
|
+
- name: Install bundler
|
19
|
+
run: gem install bundler
|
20
|
+
|
21
|
+
- name: Install dependencies
|
22
|
+
run: bundle install
|
23
|
+
|
24
|
+
- name: Test
|
25
|
+
run: bundle exec rspec
|
@@ -0,0 +1,41 @@
|
|
1
|
+
name: Publish
|
2
|
+
on:
|
3
|
+
release:
|
4
|
+
types: [published]
|
5
|
+
jobs:
|
6
|
+
publish:
|
7
|
+
runs-on: ubuntu-latest
|
8
|
+
steps:
|
9
|
+
- name: Checkout
|
10
|
+
uses: actions/checkout@v2
|
11
|
+
|
12
|
+
- name: Setup Ruby
|
13
|
+
uses: actions/setup-ruby@v1
|
14
|
+
with:
|
15
|
+
ruby-version: 2.6.x
|
16
|
+
|
17
|
+
- name: Install packages
|
18
|
+
run: sudo apt-get install libsqlite3-dev
|
19
|
+
|
20
|
+
- name: Install bundler
|
21
|
+
run: gem install bundler
|
22
|
+
|
23
|
+
- name: Install dependencies
|
24
|
+
run: bundle install
|
25
|
+
|
26
|
+
- name: Test
|
27
|
+
run: bundle exec rspec
|
28
|
+
|
29
|
+
- name: Set version
|
30
|
+
run: perl -pi -e "s/0\.0\.0/${GITHUB_REF:11}/" lib/graphql/extras/version.rb
|
31
|
+
|
32
|
+
- name: Publish
|
33
|
+
run: |
|
34
|
+
mkdir -p $HOME/.gem
|
35
|
+
touch $HOME/.gem/credentials
|
36
|
+
chmod 0600 $HOME/.gem/credentials
|
37
|
+
printf -- "---\n:rubygems_api_key: ${RUBYGEMS_TOKEN}\n" > $HOME/.gem/credentials
|
38
|
+
gem build *.gemspec
|
39
|
+
gem push *.gem
|
40
|
+
env:
|
41
|
+
RUBYGEMS_TOKEN: ${{ secrets.RUBYGEMS_TOKEN }}
|
data/.gitignore
ADDED
data/.rspec
ADDED
data/Gemfile
ADDED
data/README.md
ADDED
@@ -0,0 +1,174 @@
|
|
1
|
+
<h1 align="center">GraphQL::Extras</h1>
|
2
|
+
|
3
|
+
<div align="center">
|
4
|
+
|
5
|
+

|
6
|
+

|
7
|
+
|
8
|
+
</div>
|
9
|
+
|
10
|
+
A collection of utilities for building GraphQL APIs.
|
11
|
+
|
12
|
+
## Installation
|
13
|
+
|
14
|
+
Add this line to your application's Gemfile:
|
15
|
+
|
16
|
+
```ruby
|
17
|
+
gem 'graphql-extras'
|
18
|
+
```
|
19
|
+
|
20
|
+
And then execute:
|
21
|
+
|
22
|
+
$ bundle
|
23
|
+
|
24
|
+
## Usage
|
25
|
+
|
26
|
+
### GraphQL::Extras::Controller
|
27
|
+
|
28
|
+
The [`graphql` gem](https://github.com/rmosolgo/graphql-ruby) will generate a controller for you with a bunch of boilerplate. This module will encapsulate that boilerplate:
|
29
|
+
|
30
|
+
```ruby
|
31
|
+
class GraphqlController < ApplicationController
|
32
|
+
include GraphQL::Extras::Controller
|
33
|
+
|
34
|
+
def execute
|
35
|
+
graphql(schema: MySchema, context: { current_user: current_user })
|
36
|
+
end
|
37
|
+
end
|
38
|
+
```
|
39
|
+
|
40
|
+
### GraphQL::Extras::Batch::AssociationLoader
|
41
|
+
|
42
|
+
This is a subclass of [`GraphQL::Batch::Loader`](https://github.com/Shopify/graphql-batch) that performs eager loading of Active Record associations.
|
43
|
+
|
44
|
+
```ruby
|
45
|
+
loader = GraphQL::Extras::Batch::AssociationLoader.for(:blog)
|
46
|
+
loader.load(Post.first)
|
47
|
+
loader.load_many(Post.all)
|
48
|
+
```
|
49
|
+
|
50
|
+
### GraphQL::Extras::Batch::Resolvers
|
51
|
+
|
52
|
+
This includes a set of convenience methods for query batching.
|
53
|
+
|
54
|
+
```ruby
|
55
|
+
class Post < GraphQL::Schema::Object
|
56
|
+
include GraphQL::Extras::Batch::Resolver
|
57
|
+
|
58
|
+
field :blog, BlogType, resolve: association(:blog), null: false
|
59
|
+
field :comments, [CommentType], resolve: association(:comments, preload: { comments: :user }), null: false
|
60
|
+
field :blog_title, String, null: false
|
61
|
+
|
62
|
+
def blog_title
|
63
|
+
association(object, :blog).then(&:title)
|
64
|
+
end
|
65
|
+
end
|
66
|
+
```
|
67
|
+
|
68
|
+
### GraphQL::Extras::Types
|
69
|
+
|
70
|
+
In your base classes, you should include the `GraphQL::Extras::Types`.
|
71
|
+
|
72
|
+
```ruby
|
73
|
+
class BaseObject < GraphQL::Schema::Object
|
74
|
+
include GraphQL::Extras::Types
|
75
|
+
end
|
76
|
+
|
77
|
+
class BaseInputObject < GraphQL::Schema::InputObject
|
78
|
+
include GraphQL::Extras::Types
|
79
|
+
end
|
80
|
+
```
|
81
|
+
|
82
|
+
#### Date
|
83
|
+
|
84
|
+
This scalar takes a `Date` and transmits it as a string, using ISO 8601 format.
|
85
|
+
|
86
|
+
```ruby
|
87
|
+
field :birthday, Date, required: true
|
88
|
+
```
|
89
|
+
|
90
|
+
#### DateTime
|
91
|
+
|
92
|
+
This scalar takes a `DateTime` and transmits it as a string, using ISO 8601 format.
|
93
|
+
|
94
|
+
```ruby
|
95
|
+
field :created_at, DateTime, required: true
|
96
|
+
```
|
97
|
+
|
98
|
+
*Note: This is just an alias for the `ISO8601DateTime` type that is included in the `graphql` gem.*
|
99
|
+
|
100
|
+
#### Decimal
|
101
|
+
|
102
|
+
This scalar takes a `BigDecimal` and transmits it as a string.
|
103
|
+
|
104
|
+
```ruby
|
105
|
+
field :weight, BigDecimal, required: true
|
106
|
+
```
|
107
|
+
|
108
|
+
#### Upload
|
109
|
+
|
110
|
+
This scalar is used for accepting file uploads.
|
111
|
+
|
112
|
+
```ruby
|
113
|
+
field :image, Upload, required: true
|
114
|
+
```
|
115
|
+
|
116
|
+
It achieves this by passing in all file upload parameters through context. This will work out of the box if you're using `GraphQL::Extras::Controller`.
|
117
|
+
|
118
|
+
Here's an example using CURL:
|
119
|
+
|
120
|
+
$ curl -X POST \
|
121
|
+
-F query='mutation { uploadFile(image: "image") }' \
|
122
|
+
-F image=@cats.png \
|
123
|
+
localhost:3000/graphql
|
124
|
+
|
125
|
+
Take note of the correspondence between the value `"image"` and the additional HTTP parameter called `-F image=@cats.png`.
|
126
|
+
|
127
|
+
See [apollo-link-upload](https://github.com/rzane/apollo-link-upload) for the client-side implementation.
|
128
|
+
|
129
|
+
### RSpec integration
|
130
|
+
|
131
|
+
Add the following to your `rails_helper.rb` (or `spec_helper.rb`).
|
132
|
+
|
133
|
+
```ruby
|
134
|
+
require "graphql/extras/rspec"
|
135
|
+
```
|
136
|
+
|
137
|
+
Now, you can run tests like so:
|
138
|
+
|
139
|
+
```ruby
|
140
|
+
RSpec.describe "hello" do
|
141
|
+
let(:context) { { name: "Ray" } }
|
142
|
+
let(:schema) { use_schema(Schema, context: context) }
|
143
|
+
let(:queries) { graphql_fixture("hello.graphql") }
|
144
|
+
|
145
|
+
it "allows easily executing queries" do
|
146
|
+
result = schema.execute(queries.hello)
|
147
|
+
|
148
|
+
expect(result).to be_successful_query
|
149
|
+
expect(result['data']['hello']).to eq("world")
|
150
|
+
end
|
151
|
+
end
|
152
|
+
```
|
153
|
+
|
154
|
+
The `graphql_fixture` method assumes that your queries live in `spec/fixtures/graphql`. You can change this assumption with the following configuration:
|
155
|
+
|
156
|
+
```ruby
|
157
|
+
RSpec.configure do |config|
|
158
|
+
config.graphql_fixture_path = '/path/to/queries'
|
159
|
+
end
|
160
|
+
```
|
161
|
+
|
162
|
+
## Development
|
163
|
+
|
164
|
+
To install dependencies:
|
165
|
+
|
166
|
+
$ bundle install
|
167
|
+
|
168
|
+
To run the test suite:
|
169
|
+
|
170
|
+
$ bundle exec rspec
|
171
|
+
|
172
|
+
## Contributing
|
173
|
+
|
174
|
+
Bug reports and pull requests are welcome on GitHub at https://github.com/rzane/graphql-extras.
|
data/Rakefile
ADDED
data/bin/console
ADDED
@@ -0,0 +1,14 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
require "bundler/setup"
|
4
|
+
require "graphql/extras"
|
5
|
+
|
6
|
+
# You can add fixtures and/or initialization code here to make experimenting
|
7
|
+
# with your gem easier. You can also use a different console, if you like.
|
8
|
+
|
9
|
+
# (If you use this, don't forget to add pry to your Gemfile!)
|
10
|
+
# require "pry"
|
11
|
+
# Pry.start
|
12
|
+
|
13
|
+
require "irb"
|
14
|
+
IRB.start(__FILE__)
|
data/bin/setup
ADDED
@@ -0,0 +1,38 @@
|
|
1
|
+
lib = File.expand_path("lib", __dir__)
|
2
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
3
|
+
require "graphql/extras/version"
|
4
|
+
|
5
|
+
Gem::Specification.new do |spec|
|
6
|
+
spec.name = "graphql-extras"
|
7
|
+
spec.version = GraphQL::Extras::VERSION
|
8
|
+
spec.authors = ["Ray Zane"]
|
9
|
+
spec.email = ["raymondzane@gmail.com"]
|
10
|
+
|
11
|
+
spec.summary = %q{Utiltities for building GraphQL APIs.}
|
12
|
+
spec.description = %q{A set of modules and types for buildign GraphQL APIs.}
|
13
|
+
spec.homepage = "https://github.com/promptworks/graphql-extras"
|
14
|
+
|
15
|
+
spec.metadata["homepage_uri"] = spec.homepage
|
16
|
+
spec.metadata["source_code_uri"] = "https://github.com/promptworks/graphql-extras"
|
17
|
+
|
18
|
+
# Specify which files should be added to the gem when it is released.
|
19
|
+
# The `git ls-files -z` loads the files in the RubyGem that have been added into git.
|
20
|
+
spec.files = Dir.chdir(File.expand_path('..', __FILE__)) do
|
21
|
+
`git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
|
22
|
+
end
|
23
|
+
spec.bindir = "exe"
|
24
|
+
spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
|
25
|
+
spec.require_paths = ["lib"]
|
26
|
+
|
27
|
+
spec.add_dependency "activesupport", ">= 5.2"
|
28
|
+
spec.add_dependency "graphql", "~> 1.9"
|
29
|
+
spec.add_dependency "graphql-batch", "~> 0.4"
|
30
|
+
|
31
|
+
spec.add_development_dependency "bundler", "~> 2.0"
|
32
|
+
spec.add_development_dependency "rake", "~> 10.0"
|
33
|
+
spec.add_development_dependency "rspec", "~> 3.0"
|
34
|
+
spec.add_development_dependency "rspec-rails", "~> 3.8"
|
35
|
+
spec.add_development_dependency "actionpack", ">= 5.2"
|
36
|
+
spec.add_development_dependency "activerecord", ">= 5.2"
|
37
|
+
spec.add_development_dependency "sqlite3", "~> 1.4"
|
38
|
+
end
|
@@ -0,0 +1,47 @@
|
|
1
|
+
require "graphql/batch"
|
2
|
+
|
3
|
+
module GraphQL
|
4
|
+
module Extras
|
5
|
+
module Batch
|
6
|
+
class AssociationLoader < GraphQL::Batch::Loader
|
7
|
+
def initialize(name, preload: name)
|
8
|
+
@name = name
|
9
|
+
@preload = preload
|
10
|
+
end
|
11
|
+
|
12
|
+
def cache_key(record)
|
13
|
+
record.object_id
|
14
|
+
end
|
15
|
+
|
16
|
+
def perform(records)
|
17
|
+
preloader = ActiveRecord::Associations::Preloader.new
|
18
|
+
preloader.preload(records, @preload)
|
19
|
+
|
20
|
+
records.each do |record|
|
21
|
+
fulfill(record, record.public_send(@name))
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
module Resolvers
|
27
|
+
def self.included(base)
|
28
|
+
base.extend ClassMethods
|
29
|
+
end
|
30
|
+
|
31
|
+
module ClassMethods
|
32
|
+
def association(name)
|
33
|
+
lambda do |record, _args, _ctx|
|
34
|
+
loader = AssociationLoader.for(name)
|
35
|
+
loader.load(record)
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
def association(record, name)
|
41
|
+
loader = AssociationLoader.for(name)
|
42
|
+
loader.load(record)
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
@@ -0,0 +1,54 @@
|
|
1
|
+
module GraphQL
|
2
|
+
module Extras
|
3
|
+
module Controller
|
4
|
+
def graphql(schema:, context: {}, debug: Rails.env.development?)
|
5
|
+
query = params[:query]
|
6
|
+
operation = params[:operationName]
|
7
|
+
variables = cast_graphql_params(params[:variables])
|
8
|
+
|
9
|
+
uploads = params.to_unsafe_h.select do |_, value|
|
10
|
+
value.is_a?(ActionDispatch::Http::UploadedFile)
|
11
|
+
end
|
12
|
+
|
13
|
+
result = schema.execute(
|
14
|
+
query,
|
15
|
+
operation_name: operation,
|
16
|
+
variables: variables,
|
17
|
+
context: context.merge(uploads: uploads)
|
18
|
+
)
|
19
|
+
|
20
|
+
render(status: 200, json: result)
|
21
|
+
rescue => error
|
22
|
+
raise error unless debug
|
23
|
+
|
24
|
+
logger.error(error.message)
|
25
|
+
logger.error(error.backtrace.join("\n"))
|
26
|
+
|
27
|
+
render(
|
28
|
+
status: 500,
|
29
|
+
json: {
|
30
|
+
data: {},
|
31
|
+
error: {
|
32
|
+
message: error.message,
|
33
|
+
backtrace: error.backtrace
|
34
|
+
}
|
35
|
+
}
|
36
|
+
)
|
37
|
+
end
|
38
|
+
|
39
|
+
private def cast_graphql_params(param)
|
40
|
+
case param
|
41
|
+
when String
|
42
|
+
return {} if param.blank?
|
43
|
+
cast_graphql_params(JSON.parse(param))
|
44
|
+
when Hash, ActionController::Parameters
|
45
|
+
param
|
46
|
+
when nil
|
47
|
+
{}
|
48
|
+
else
|
49
|
+
raise ArgumentError, "Unexpected parameter: #{param}"
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|
54
|
+
end
|
@@ -0,0 +1,133 @@
|
|
1
|
+
require "yaml"
|
2
|
+
require "active_support/inflector"
|
3
|
+
require "active_support/core_ext/hash"
|
4
|
+
|
5
|
+
module GraphQL
|
6
|
+
module Extras
|
7
|
+
module RSpec
|
8
|
+
class Queries
|
9
|
+
def add(key, value)
|
10
|
+
define_singleton_method(key) { value }
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
14
|
+
class Schema
|
15
|
+
def initialize(schema, context: {})
|
16
|
+
@schema = schema
|
17
|
+
@context = context
|
18
|
+
end
|
19
|
+
|
20
|
+
def execute(query, variables = {})
|
21
|
+
variables = deep_camelize_keys(variables)
|
22
|
+
variables, uploads = extract_uploads(variables)
|
23
|
+
context = @context.merge(uploads: uploads)
|
24
|
+
|
25
|
+
result = @schema.execute(query, variables: variables, context: context)
|
26
|
+
result.to_h
|
27
|
+
end
|
28
|
+
|
29
|
+
private
|
30
|
+
|
31
|
+
def extract_uploads(variables)
|
32
|
+
uploads = {}
|
33
|
+
variables = deep_transform_values(variables) { |value|
|
34
|
+
if upload?(value)
|
35
|
+
SecureRandom.hex.tap { |key| uploads.merge!(key => value) }
|
36
|
+
else
|
37
|
+
value
|
38
|
+
end
|
39
|
+
}
|
40
|
+
|
41
|
+
[variables, uploads]
|
42
|
+
end
|
43
|
+
|
44
|
+
def deep_camelize_keys(variables)
|
45
|
+
variables.deep_transform_keys { |key| key.to_s.camelize(:lower) }
|
46
|
+
end
|
47
|
+
|
48
|
+
def deep_transform_values(data, &block)
|
49
|
+
case data
|
50
|
+
when Array
|
51
|
+
data.map { |v| deep_transform_values(v, &block) }
|
52
|
+
when Hash
|
53
|
+
data.transform_values { |v| deep_transform_values(v, &block) }
|
54
|
+
else
|
55
|
+
yield data
|
56
|
+
end
|
57
|
+
end
|
58
|
+
|
59
|
+
def upload?(value)
|
60
|
+
value.respond_to?(:tempfile) && value.respond_to?(:original_filename)
|
61
|
+
end
|
62
|
+
end
|
63
|
+
|
64
|
+
class Parser
|
65
|
+
include ::GraphQL::Language
|
66
|
+
|
67
|
+
def initialize(document)
|
68
|
+
@operations = document.definitions
|
69
|
+
.grep(Nodes::OperationDefinition)
|
70
|
+
|
71
|
+
@fragments = document.definitions
|
72
|
+
.grep(Nodes::FragmentDefinition)
|
73
|
+
.reduce({}) { |acc, f| acc.merge(f.name => f) }
|
74
|
+
end
|
75
|
+
|
76
|
+
def parse
|
77
|
+
queries = Queries.new
|
78
|
+
printer = Printer.new
|
79
|
+
|
80
|
+
@operations.each do |op|
|
81
|
+
nodes = [op, *find_fragments(op)]
|
82
|
+
nodes = nodes.map { |node| printer.print(node) }
|
83
|
+
queries.add op.name.underscore, nodes.join
|
84
|
+
end
|
85
|
+
|
86
|
+
queries
|
87
|
+
end
|
88
|
+
|
89
|
+
private
|
90
|
+
|
91
|
+
def find_fragments(node)
|
92
|
+
node.selections.flat_map do |field|
|
93
|
+
if field.is_a? Nodes::FragmentSpread
|
94
|
+
fragment = @fragments.fetch(field.name)
|
95
|
+
[fragment, *find_fragments(fragment)]
|
96
|
+
else
|
97
|
+
find_fragments(field)
|
98
|
+
end
|
99
|
+
end
|
100
|
+
end
|
101
|
+
end
|
102
|
+
|
103
|
+
def graphql_fixture(filename)
|
104
|
+
root = ::RSpec.configuration.graphql_fixture_path
|
105
|
+
file = File.join(root, filename)
|
106
|
+
document = ::GraphQL.parse_file(file)
|
107
|
+
parser = Parser.new(document)
|
108
|
+
parser.parse
|
109
|
+
end
|
110
|
+
|
111
|
+
def use_schema(*args)
|
112
|
+
Schema.new(*args)
|
113
|
+
end
|
114
|
+
end
|
115
|
+
end
|
116
|
+
end
|
117
|
+
|
118
|
+
RSpec::Matchers.define :be_successful_query do
|
119
|
+
match do |result|
|
120
|
+
result['errors'].nil?
|
121
|
+
end
|
122
|
+
|
123
|
+
failure_message do |result|
|
124
|
+
errors = result['errors'].map(&:deep_stringify_keys)
|
125
|
+
message = "expected query to be successful, but encountered errors:\n"
|
126
|
+
message + errors.to_yaml.lines.drop(1).join.indent(2)
|
127
|
+
end
|
128
|
+
end
|
129
|
+
|
130
|
+
RSpec.configure do |config|
|
131
|
+
config.add_setting :graphql_fixture_path, default: "spec/fixtures/graphql"
|
132
|
+
config.include GraphQL::Extras::RSpec, type: :graphql
|
133
|
+
end
|
@@ -0,0 +1,69 @@
|
|
1
|
+
require "date"
|
2
|
+
require "bigdecimal"
|
3
|
+
require "graphql"
|
4
|
+
|
5
|
+
module GraphQL
|
6
|
+
module Extras
|
7
|
+
module Types
|
8
|
+
class DateTime < GraphQL::Types::ISO8601DateTime
|
9
|
+
description <<~DESC
|
10
|
+
The `DateTime` scalar type represents a date and time in the UTC
|
11
|
+
timezone. The DateTime appears in a JSON response as an ISO8601 formatted
|
12
|
+
string, including UTC timezone ("Z"). The parsed date and time string will
|
13
|
+
be converted to UTC and any UTC offset other than 0 will be rejected.
|
14
|
+
DESC
|
15
|
+
end
|
16
|
+
|
17
|
+
class Date < GraphQL::Schema::Scalar
|
18
|
+
description <<~DESC
|
19
|
+
The `Date` scalar type represents a date. The Date appears in a JSON
|
20
|
+
response as an ISO8601 formatted string.
|
21
|
+
DESC
|
22
|
+
|
23
|
+
def self.coerce_input(value, _context)
|
24
|
+
::Date.iso8601(value)
|
25
|
+
rescue ArgumentError
|
26
|
+
nil
|
27
|
+
end
|
28
|
+
|
29
|
+
def self.coerce_result(value, _context)
|
30
|
+
value.iso8601
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
class Decimal < GraphQL::Schema::Scalar
|
35
|
+
description <<~DESC
|
36
|
+
The `Decimal` scalar type represents signed double-precision fractional
|
37
|
+
values parsed by the `Decimal` library. The Decimal appears in a JSON
|
38
|
+
response as a string to preserve precision.
|
39
|
+
DESC
|
40
|
+
|
41
|
+
def self.coerce_input(value, _context)
|
42
|
+
BigDecimal(value.to_s)
|
43
|
+
rescue ArgumentError
|
44
|
+
nil
|
45
|
+
end
|
46
|
+
|
47
|
+
def self.coerce_result(value, _context)
|
48
|
+
value.to_s("F")
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
class Upload < GraphQL::Schema::Scalar
|
53
|
+
description "Represents an uploaded file."
|
54
|
+
|
55
|
+
def self.coerce_input(value, context)
|
56
|
+
return nil if value.nil?
|
57
|
+
|
58
|
+
uploads = context.fetch(:uploads) {
|
59
|
+
raise "Expected context to include a hash of uploads."
|
60
|
+
}
|
61
|
+
|
62
|
+
uploads.fetch(value) do
|
63
|
+
raise GraphQL::CoercionError, "No upload named `#{value}` provided."
|
64
|
+
end
|
65
|
+
end
|
66
|
+
end
|
67
|
+
end
|
68
|
+
end
|
69
|
+
end
|
metadata
ADDED
@@ -0,0 +1,200 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: graphql-extras
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.0.0.pre.2dcd696
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Ray Zane
|
8
|
+
autorequire:
|
9
|
+
bindir: exe
|
10
|
+
cert_chain: []
|
11
|
+
date: 2020-05-10 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: activesupport
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - ">="
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '5.2'
|
20
|
+
type: :runtime
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - ">="
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '5.2'
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: graphql
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - "~>"
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: '1.9'
|
34
|
+
type: :runtime
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - "~>"
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: '1.9'
|
41
|
+
- !ruby/object:Gem::Dependency
|
42
|
+
name: graphql-batch
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
44
|
+
requirements:
|
45
|
+
- - "~>"
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: '0.4'
|
48
|
+
type: :runtime
|
49
|
+
prerelease: false
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - "~>"
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: '0.4'
|
55
|
+
- !ruby/object:Gem::Dependency
|
56
|
+
name: bundler
|
57
|
+
requirement: !ruby/object:Gem::Requirement
|
58
|
+
requirements:
|
59
|
+
- - "~>"
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: '2.0'
|
62
|
+
type: :development
|
63
|
+
prerelease: false
|
64
|
+
version_requirements: !ruby/object:Gem::Requirement
|
65
|
+
requirements:
|
66
|
+
- - "~>"
|
67
|
+
- !ruby/object:Gem::Version
|
68
|
+
version: '2.0'
|
69
|
+
- !ruby/object:Gem::Dependency
|
70
|
+
name: rake
|
71
|
+
requirement: !ruby/object:Gem::Requirement
|
72
|
+
requirements:
|
73
|
+
- - "~>"
|
74
|
+
- !ruby/object:Gem::Version
|
75
|
+
version: '10.0'
|
76
|
+
type: :development
|
77
|
+
prerelease: false
|
78
|
+
version_requirements: !ruby/object:Gem::Requirement
|
79
|
+
requirements:
|
80
|
+
- - "~>"
|
81
|
+
- !ruby/object:Gem::Version
|
82
|
+
version: '10.0'
|
83
|
+
- !ruby/object:Gem::Dependency
|
84
|
+
name: rspec
|
85
|
+
requirement: !ruby/object:Gem::Requirement
|
86
|
+
requirements:
|
87
|
+
- - "~>"
|
88
|
+
- !ruby/object:Gem::Version
|
89
|
+
version: '3.0'
|
90
|
+
type: :development
|
91
|
+
prerelease: false
|
92
|
+
version_requirements: !ruby/object:Gem::Requirement
|
93
|
+
requirements:
|
94
|
+
- - "~>"
|
95
|
+
- !ruby/object:Gem::Version
|
96
|
+
version: '3.0'
|
97
|
+
- !ruby/object:Gem::Dependency
|
98
|
+
name: rspec-rails
|
99
|
+
requirement: !ruby/object:Gem::Requirement
|
100
|
+
requirements:
|
101
|
+
- - "~>"
|
102
|
+
- !ruby/object:Gem::Version
|
103
|
+
version: '3.8'
|
104
|
+
type: :development
|
105
|
+
prerelease: false
|
106
|
+
version_requirements: !ruby/object:Gem::Requirement
|
107
|
+
requirements:
|
108
|
+
- - "~>"
|
109
|
+
- !ruby/object:Gem::Version
|
110
|
+
version: '3.8'
|
111
|
+
- !ruby/object:Gem::Dependency
|
112
|
+
name: actionpack
|
113
|
+
requirement: !ruby/object:Gem::Requirement
|
114
|
+
requirements:
|
115
|
+
- - ">="
|
116
|
+
- !ruby/object:Gem::Version
|
117
|
+
version: '5.2'
|
118
|
+
type: :development
|
119
|
+
prerelease: false
|
120
|
+
version_requirements: !ruby/object:Gem::Requirement
|
121
|
+
requirements:
|
122
|
+
- - ">="
|
123
|
+
- !ruby/object:Gem::Version
|
124
|
+
version: '5.2'
|
125
|
+
- !ruby/object:Gem::Dependency
|
126
|
+
name: activerecord
|
127
|
+
requirement: !ruby/object:Gem::Requirement
|
128
|
+
requirements:
|
129
|
+
- - ">="
|
130
|
+
- !ruby/object:Gem::Version
|
131
|
+
version: '5.2'
|
132
|
+
type: :development
|
133
|
+
prerelease: false
|
134
|
+
version_requirements: !ruby/object:Gem::Requirement
|
135
|
+
requirements:
|
136
|
+
- - ">="
|
137
|
+
- !ruby/object:Gem::Version
|
138
|
+
version: '5.2'
|
139
|
+
- !ruby/object:Gem::Dependency
|
140
|
+
name: sqlite3
|
141
|
+
requirement: !ruby/object:Gem::Requirement
|
142
|
+
requirements:
|
143
|
+
- - "~>"
|
144
|
+
- !ruby/object:Gem::Version
|
145
|
+
version: '1.4'
|
146
|
+
type: :development
|
147
|
+
prerelease: false
|
148
|
+
version_requirements: !ruby/object:Gem::Requirement
|
149
|
+
requirements:
|
150
|
+
- - "~>"
|
151
|
+
- !ruby/object:Gem::Version
|
152
|
+
version: '1.4'
|
153
|
+
description: A set of modules and types for buildign GraphQL APIs.
|
154
|
+
email:
|
155
|
+
- raymondzane@gmail.com
|
156
|
+
executables: []
|
157
|
+
extensions: []
|
158
|
+
extra_rdoc_files: []
|
159
|
+
files:
|
160
|
+
- ".github/workflows/build.yml"
|
161
|
+
- ".github/workflows/publish.yml"
|
162
|
+
- ".gitignore"
|
163
|
+
- ".rspec"
|
164
|
+
- Gemfile
|
165
|
+
- README.md
|
166
|
+
- Rakefile
|
167
|
+
- bin/console
|
168
|
+
- bin/setup
|
169
|
+
- graphql-extras.gemspec
|
170
|
+
- lib/graphql/extras.rb
|
171
|
+
- lib/graphql/extras/batch.rb
|
172
|
+
- lib/graphql/extras/controller.rb
|
173
|
+
- lib/graphql/extras/rspec.rb
|
174
|
+
- lib/graphql/extras/types.rb
|
175
|
+
- lib/graphql/extras/version.rb
|
176
|
+
homepage: https://github.com/promptworks/graphql-extras
|
177
|
+
licenses: []
|
178
|
+
metadata:
|
179
|
+
homepage_uri: https://github.com/promptworks/graphql-extras
|
180
|
+
source_code_uri: https://github.com/promptworks/graphql-extras
|
181
|
+
post_install_message:
|
182
|
+
rdoc_options: []
|
183
|
+
require_paths:
|
184
|
+
- lib
|
185
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
186
|
+
requirements:
|
187
|
+
- - ">="
|
188
|
+
- !ruby/object:Gem::Version
|
189
|
+
version: '0'
|
190
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
191
|
+
requirements:
|
192
|
+
- - ">"
|
193
|
+
- !ruby/object:Gem::Version
|
194
|
+
version: 1.3.1
|
195
|
+
requirements: []
|
196
|
+
rubygems_version: 3.0.3
|
197
|
+
signing_key:
|
198
|
+
specification_version: 4
|
199
|
+
summary: Utiltities for building GraphQL APIs.
|
200
|
+
test_files: []
|