jsonrpc2 0.1.1 → 0.2.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -8,11 +8,11 @@ module JSONRPC2
8
8
  return nil if @about.nil? or @about.empty?
9
9
  str = ""
10
10
 
11
- if @title
11
+ if @title
12
12
  str << "h1. #{@title}\n"
13
13
  else
14
14
  str << "h1. #{name}\n"
15
- end
15
+ end
16
16
 
17
17
  if @introduction
18
18
  str << "\nh2. Introduction\n\n#{@introduction}\n"
@@ -41,7 +41,7 @@ module JSONRPC2
41
41
  if section[:summary]
42
42
  str << "\n#{section[:summary]}\n"
43
43
  end
44
-
44
+
45
45
  str += to_textile_group(section).to_s
46
46
  end
47
47
 
@@ -70,7 +70,7 @@ module JSONRPC2
70
70
 
71
71
  if res = info[:returns]
72
72
  str << "\n\nh5. Result\n"
73
- str << "\n* @#{res[:type]}@"
73
+ str << "\n* @#{res[:type]}@"
74
74
  str << " - #{res[:desc]}" if res[:desc]
75
75
  str << "\n"
76
76
  else
@@ -128,7 +128,7 @@ module JSONRPC2
128
128
  return nil if list.empty?
129
129
 
130
130
  str = ''
131
-
131
+
132
132
  list.sort_by { |info| info[:index] }.each do |info|
133
133
  str << method_to_textile(info)
134
134
  end
@@ -16,6 +16,9 @@ module JSONRPC2
16
16
  # * Value (or Any or void) - Any value of any type
17
17
  # * CustomType - A defined custom object type
18
18
  module Types
19
+ class InvalidParamsError < ArgumentError; end
20
+ class InvalidResultError < RuntimeError; end
21
+
19
22
  module_function
20
23
  DateTimeRegex = %r"([0-9]{4})(-([0-9]{2})(-([0-9]{2})(T([0-9]{2}):([0-9]{2})(:([0-9]{2})(\.([0-9]+))?)?(Z|(([-+])([0-9]{2}):([0-9]{2})))?)?)?)?"
21
24
  DateRegex = %r'\A\d{4}-\d{2}-\d{2}\z'
@@ -76,7 +79,7 @@ module JSONRPC2
76
79
  end
77
80
 
78
81
  # Checks that param hash is valid for API call
79
- #
82
+ #
80
83
  # @param [Interface] interface API class
81
84
  # @param [String] method Method name
82
85
  # @param [Hash] data params hash to check
@@ -92,23 +95,23 @@ module JSONRPC2
92
95
  return true
93
96
  end
94
97
 
95
- raise "Params should not be nil" if data.nil?
98
+ raise InvalidParamsError, "Params should not be nil" if data.nil?
96
99
 
97
100
  extra_keys = data.keys - param_names
98
101
  unless extra_keys.empty?
99
- raise "Extra parameters #{extra_keys.inspect} for #{method}."
102
+ raise InvalidParamsError, "Extra parameters #{extra_keys.inspect} for #{method}."
100
103
  end
101
104
 
102
105
  params.each do |param|
103
106
  if data.has_key?(param[:name])
104
107
  value = data[param[:name].to_s]
105
108
  unless valid?(interface, param[:type], value)
106
- raise "'#{param[:name]}' should be of type #{param[:type]}, was #{value.class.name}"
109
+ raise InvalidParamsError, "'#{param[:name]}' should be of type #{param[:type]}, was #{value.class.name}"
107
110
  end
108
111
  elsif ! param[:required]
109
112
  next true
110
113
  else
111
- raise "Missing parameter: '#{param[:name]}' of type #{param[:type]} for #{method}"
114
+ raise InvalidParamsError, "Missing parameter: '#{param[:name]}' of type #{param[:type]} for #{method}"
112
115
  end
113
116
  end
114
117
  end
@@ -122,11 +125,12 @@ module JSONRPC2
122
125
  def valid_result?(interface, method, value)
123
126
  about = interface.about[method.to_s]
124
127
  return true if about.nil? # Undefined
125
- if about[:returns].nil?
126
- return value.nil?
127
- end
128
- valid?(interface, about[:returns][:type], value) or
129
- raise "Invalid return type: should have been #{about[:returns][:type]}, was #{value.class.name}"
128
+ return value.nil? if about[:returns].nil?
129
+ return true if valid?(interface, about[:returns][:type], value)
130
+
131
+ raise InvalidResultError, <<~MSG.chomp
132
+ Invalid return type: should have been #{about[:returns][:type]}, was #{value.class.name}
133
+ MSG
130
134
  end
131
135
  end
132
136
 
@@ -1,5 +1,5 @@
1
1
  # JSONRPC2 namespace module
2
2
  module JSONRPC2
3
3
  # Version
4
- VERSION = "0.1.1"
4
+ VERSION = "0.2.0"
5
5
  end
@@ -0,0 +1,162 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'json'
4
+ require 'base64'
5
+ require 'logger'
6
+ require 'jsonrpc2/interface'
7
+ require 'jsonrpc2/auth'
8
+
9
+ RSpec.describe JSONRPC2::Interface do
10
+ let(:instance) { rpc_api_class.new(initialization_params) }
11
+ let(:basic_auth_credentials) { 'user:valid_password' }
12
+ let(:initialization_params) { { 'HTTP_AUTHORIZATION' => "Basic #{Base64.encode64(basic_auth_credentials)}" } }
13
+ let(:rpc_api_class) do
14
+ Class.new(described_class) do
15
+ auth_with JSONRPC2::BasicAuth.new('user' => 'valid_password')
16
+
17
+ param 'name', 'String', 'name'
18
+ result 'String', 'A tailored greeting'
19
+ def hello
20
+ raise 'He-Must-Not-Be-Named' if params['name'] == 'Voldemort'
21
+ return 42 if params['name'] == 'Marvin'
22
+
23
+ "Hello, #{params['name']}!"
24
+ end
25
+ end
26
+ end
27
+
28
+ describe '#rack_dispatch' do
29
+ subject(:dispatch_result) { instance.rack_dispatch(rpc_request_data) }
30
+
31
+ let(:rpc_request_data) { { 'id' => 123, 'method' => 'hello', 'jsonrpc' => '2.0' } }
32
+ let(:response_status) { dispatch_result[0] }
33
+ let(:response_body) { dispatch_result[2][0] }
34
+ let(:parsed_response_body) { JSON.parse(response_body, symbolize_names: true) }
35
+
36
+ context 'with empty input' do
37
+ let(:rpc_request_data) { {} }
38
+
39
+ it 'returns the "Invalid request" error' do
40
+ expect(parsed_response_body[:error]).to eq(
41
+ code: -32600,
42
+ message: 'Invalid request',
43
+ data: nil
44
+ )
45
+ end
46
+ end
47
+
48
+ context 'with invalid credentials' do
49
+ let(:basic_auth_credentials) { 'user:invalid_password' }
50
+ it 'returns the authorization error' do
51
+ expect(response_status).to eq(401)
52
+ expect(response_body).to include('Authentication Required')
53
+ end
54
+ end
55
+
56
+ context 'with no params' do
57
+ it 'returns the "Params should not be nil" error' do
58
+ expect(parsed_response_body[:error]).to eq(
59
+ code: -32602,
60
+ message: 'Invalid params - Params should not be nil',
61
+ data: {}
62
+ )
63
+ end
64
+ end
65
+
66
+ context 'with a missing param' do
67
+ let(:rpc_request_data) { super().merge('params' => {}) }
68
+
69
+ it 'returns a helpful param error' do
70
+ expect(parsed_response_body[:error]).to eq(
71
+ code: -32602,
72
+ message: 'Invalid params - Missing parameter: \'name\' of type String for hello',
73
+ data: {}
74
+ )
75
+ end
76
+ end
77
+
78
+ context 'with a mismatched type of param' do
79
+ let(:rpc_request_data) { super().merge('params' => { 'name' => true }) }
80
+
81
+ it 'returns the helpful param error' do
82
+ expect(parsed_response_body[:error]).to eq(
83
+ code: -32602,
84
+ message: 'Invalid params - \'name\' should be of type String, was TrueClass',
85
+ data: {}
86
+ )
87
+ end
88
+ end
89
+
90
+ context 'with a valid param' do
91
+ let(:rpc_request_data) { super().merge('params' => params) }
92
+ let(:params) { { 'name' => 'Geoff' } }
93
+
94
+ it 'returns the valid response' do
95
+ expect(parsed_response_body[:result]).to eq('Hello, Geoff!')
96
+ end
97
+
98
+ context 'with an extra param' do
99
+ let(:params) { super().merge('extra' => 'I should not be here') }
100
+
101
+ it 'returns the helpful param error' do
102
+ expect(parsed_response_body[:error]).to eq(
103
+ code: -32602,
104
+ message: 'Invalid params - Extra parameters ["extra"] for hello.',
105
+ data: {}
106
+ )
107
+ end
108
+ end
109
+
110
+ context 'with an invalid result type' do
111
+ let(:params) { { 'name' => 'Marvin' } }
112
+
113
+ it 'informs about the server error' do
114
+ expect(parsed_response_body[:error]).to match(
115
+ code: -32000,
116
+ message: 'An error occurred. Check logs for details',
117
+ data: {}
118
+ )
119
+ end
120
+ end
121
+ end
122
+
123
+ context 'with an unhandled server error' do
124
+ let(:rpc_request_data) { super().merge('params' => { 'name' => 'Voldemort' }) }
125
+
126
+ it 'informs about the server error' do
127
+ expect(parsed_response_body[:error]).to match(
128
+ code: -32000,
129
+ message: 'An error occurred. Check logs for details',
130
+ data: {}
131
+ )
132
+ end
133
+
134
+ context 'with error hook raising an error' do
135
+ let(:initialization_params) { super().merge('rack.logger' => rack_logger) }
136
+ let(:rack_logger) { instance_double(::Logger, :rack_logger, info: nil, error: nil) }
137
+
138
+ before do
139
+ rpc_api_class.class_eval do
140
+ def on_server_error(request_id:, error:)
141
+ raise "Whoops, my bad!"
142
+ end
143
+ end
144
+ end
145
+
146
+ it 'informs about the server error' do
147
+ expect(parsed_response_body[:error]).to match(
148
+ code: -32000,
149
+ message: 'An error occurred. Check logs for details',
150
+ data: {}
151
+ )
152
+ end
153
+
154
+ it 'logs the error' do
155
+ expect(rack_logger).to receive(:error).with(/Whoops, my bad!/)
156
+
157
+ dispatch_result
158
+ end
159
+ end
160
+ end
161
+ end
162
+ end
@@ -0,0 +1,94 @@
1
+ # This file was generated by the `rspec --init` command. Conventionally, all
2
+ # specs live under a `spec` directory, which RSpec adds to the `$LOAD_PATH`.
3
+ # The generated `.rspec` file contains `--require spec_helper` which will cause
4
+ # this file to always be loaded, without a need to explicitly require it in any
5
+ # files.
6
+ #
7
+ # Given that it is always loaded, you are encouraged to keep this file as
8
+ # light-weight as possible. Requiring heavyweight dependencies from this file
9
+ # will add to the boot time of your test suite on EVERY test run, even for an
10
+ # individual file that may not need all of that loaded. Instead, consider making
11
+ # a separate helper file that requires the additional dependencies and performs
12
+ # the additional setup, and require it from the spec files that actually need
13
+ # it.
14
+ #
15
+ # See https://rubydoc.info/gems/rspec-core/RSpec/Core/Configuration
16
+ RSpec.configure do |config|
17
+ # rspec-expectations config goes here. You can use an alternate
18
+ # assertion/expectation library such as wrong or the stdlib/minitest
19
+ # assertions if you prefer.
20
+ config.expect_with :rspec do |expectations|
21
+ # This option will default to `true` in RSpec 4. It makes the `description`
22
+ # and `failure_message` of custom matchers include text for helper methods
23
+ # defined using `chain`, e.g.:
24
+ # be_bigger_than(2).and_smaller_than(4).description
25
+ # # => "be bigger than 2 and smaller than 4"
26
+ # ...rather than:
27
+ # # => "be bigger than 2"
28
+ expectations.include_chain_clauses_in_custom_matcher_descriptions = true
29
+ end
30
+
31
+ # rspec-mocks config goes here. You can use an alternate test double
32
+ # library (such as bogus or mocha) by changing the `mock_with` option here.
33
+ config.mock_with :rspec do |mocks|
34
+ # Prevents you from mocking or stubbing a method that does not exist on
35
+ # a real object. This is generally recommended, and will default to
36
+ # `true` in RSpec 4.
37
+ mocks.verify_partial_doubles = true
38
+ end
39
+
40
+ # This option will default to `:apply_to_host_groups` in RSpec 4 (and will
41
+ # have no way to turn it off -- the option exists only for backwards
42
+ # compatibility in RSpec 3). It causes shared context metadata to be
43
+ # inherited by the metadata hash of host groups and examples, rather than
44
+ # triggering implicit auto-inclusion in groups with matching metadata.
45
+ config.shared_context_metadata_behavior = :apply_to_host_groups
46
+
47
+ # This allows you to limit a spec run to individual examples or groups
48
+ # you care about by tagging them with `:focus` metadata. When nothing
49
+ # is tagged with `:focus`, all examples get run. RSpec also provides
50
+ # aliases for `it`, `describe`, and `context` that include `:focus`
51
+ # metadata: `fit`, `fdescribe` and `fcontext`, respectively.
52
+ config.filter_run_when_matching :focus
53
+
54
+ # Allows RSpec to persist some state between runs in order to support
55
+ # the `--only-failures` and `--next-failure` CLI options. We recommend
56
+ # you configure your source control system to ignore this file.
57
+ config.example_status_persistence_file_path = "spec/examples.txt"
58
+
59
+ # Limits the available syntax to the non-monkey patched syntax that is
60
+ # recommended. For more details, see:
61
+ # https://relishapp.com/rspec/rspec-core/docs/configuration/zero-monkey-patching-mode
62
+ config.disable_monkey_patching!
63
+
64
+ # This setting enables warnings. It's recommended, but in some cases may
65
+ # be too noisy due to issues in dependencies.
66
+ config.warnings = true
67
+
68
+ # Many RSpec users commonly either run the entire suite or an individual
69
+ # file, and it's useful to allow more verbose output when running an
70
+ # individual spec file.
71
+ if config.files_to_run.one?
72
+ # Use the documentation formatter for detailed output,
73
+ # unless a formatter has already been configured
74
+ # (e.g. via a command-line flag).
75
+ config.default_formatter = "doc"
76
+ end
77
+
78
+ # Print the 10 slowest examples and example groups at the
79
+ # end of the spec run, to help surface which specs are running
80
+ # particularly slow.
81
+ # config.profile_examples = 10
82
+
83
+ # Run specs in random order to surface order dependencies. If you find an
84
+ # order dependency and want to debug it, you can fix the order by providing
85
+ # the seed, which is printed after each run.
86
+ # --seed 1234
87
+ config.order = :random
88
+
89
+ # Seed global randomization in this process using the `--seed` CLI option.
90
+ # Setting this allows you to use `--seed` to deterministically reproduce
91
+ # test failures related to randomization by passing the same `--seed` value
92
+ # as the one that triggered the failure.
93
+ Kernel.srand config.seed
94
+ end
metadata CHANGED
@@ -1,85 +1,164 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: jsonrpc2
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.1
4
+ version: 0.2.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Geoff Youngs
8
- autorequire:
9
- bindir: bin
8
+ autorequire:
9
+ bindir: exe
10
10
  cert_chain: []
11
- date: 2014-01-04 00:00:00.000000000 Z
11
+ date: 2022-04-14 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: httpclient
15
15
  requirement: !ruby/object:Gem::Requirement
16
16
  requirements:
17
- - - '>='
17
+ - - ">="
18
18
  - !ruby/object:Gem::Version
19
19
  version: '0'
20
20
  type: :runtime
21
21
  prerelease: false
22
22
  version_requirements: !ruby/object:Gem::Requirement
23
23
  requirements:
24
- - - '>='
24
+ - - ">="
25
25
  - !ruby/object:Gem::Version
26
26
  version: '0'
27
27
  - !ruby/object:Gem::Dependency
28
28
  name: json
29
29
  requirement: !ruby/object:Gem::Requirement
30
30
  requirements:
31
- - - '>='
31
+ - - ">="
32
32
  - !ruby/object:Gem::Version
33
33
  version: '0'
34
34
  type: :runtime
35
35
  prerelease: false
36
36
  version_requirements: !ruby/object:Gem::Requirement
37
37
  requirements:
38
- - - '>='
38
+ - - ">="
39
39
  - !ruby/object:Gem::Version
40
40
  version: '0'
41
41
  - !ruby/object:Gem::Dependency
42
42
  name: RedCloth
43
43
  requirement: !ruby/object:Gem::Requirement
44
44
  requirements:
45
- - - '>='
45
+ - - ">="
46
46
  - !ruby/object:Gem::Version
47
47
  version: '0'
48
48
  type: :runtime
49
49
  prerelease: false
50
50
  version_requirements: !ruby/object:Gem::Requirement
51
51
  requirements:
52
- - - '>='
52
+ - - ">="
53
53
  - !ruby/object:Gem::Version
54
54
  version: '0'
55
55
  - !ruby/object:Gem::Dependency
56
56
  name: thor
57
57
  requirement: !ruby/object:Gem::Requirement
58
58
  requirements:
59
- - - '>='
59
+ - - ">="
60
60
  - !ruby/object:Gem::Version
61
61
  version: '0'
62
62
  type: :runtime
63
63
  prerelease: false
64
64
  version_requirements: !ruby/object:Gem::Requirement
65
65
  requirements:
66
- - - '>='
67
- - !ruby/object:Gem::Version
68
- version: '0'
69
- description: "== Description\n\nA Rack compatible JSON-RPC2 server domain specific
70
- language (DSL) - allows JSONRPC APIs to be \ndefined as mountable Rack applications
71
- with inline documentation, authentication and type checking.\n\ne.g.\n\n class
72
- Calculator < JSONRPC2::Interface\n title \"JSON-RPC2 Calculator\"\n introduction
73
- \"This interface allows basic maths calculations via JSON-RPC2\"\n auth_with
74
- JSONRPC2::BasicAuth.new({'user' => 'secretword'})\n\n section 'Simple Ops' do\n
75
- \ desc 'Multiply two numbers'\n param 'a', 'Number', 'a'\n param
76
- 'b', 'Number', 'b'\n result 'Number', 'a * b'\n def mul args\n args['a']
77
- * args['b']\n end\n\n desc 'Add numbers'\n example \"Calculate
78
- 1 + 1 = 2\", :params => { 'a' => 1, 'b' => 1}, :result => 2\n\n param 'a',
79
- 'Number', 'First number'\n param 'b', 'Number', 'Second number'\n optional
80
- 'c', 'Number', 'Third number'\n result 'Number', 'a + b + c'\n def
81
- sum args\n val = args['a'] + args['b']\n val += args['c'] if args['c']\n
82
- \ val\n end\n end\n end\n\n"
66
+ - - ">="
67
+ - !ruby/object:Gem::Version
68
+ version: '0'
69
+ - !ruby/object:Gem::Dependency
70
+ name: rack
71
+ requirement: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - ">="
74
+ - !ruby/object:Gem::Version
75
+ version: '0'
76
+ type: :development
77
+ prerelease: false
78
+ version_requirements: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - ">="
81
+ - !ruby/object:Gem::Version
82
+ version: '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: '0'
90
+ type: :development
91
+ prerelease: false
92
+ version_requirements: !ruby/object:Gem::Requirement
93
+ requirements:
94
+ - - ">="
95
+ - !ruby/object:Gem::Version
96
+ version: '0'
97
+ - !ruby/object:Gem::Dependency
98
+ name: puma
99
+ requirement: !ruby/object:Gem::Requirement
100
+ requirements:
101
+ - - ">="
102
+ - !ruby/object:Gem::Version
103
+ version: '0'
104
+ type: :development
105
+ prerelease: false
106
+ version_requirements: !ruby/object:Gem::Requirement
107
+ requirements:
108
+ - - ">="
109
+ - !ruby/object:Gem::Version
110
+ version: '0'
111
+ - !ruby/object:Gem::Dependency
112
+ name: pry-byebug
113
+ requirement: !ruby/object:Gem::Requirement
114
+ requirements:
115
+ - - ">="
116
+ - !ruby/object:Gem::Version
117
+ version: '0'
118
+ type: :development
119
+ prerelease: false
120
+ version_requirements: !ruby/object:Gem::Requirement
121
+ requirements:
122
+ - - ">="
123
+ - !ruby/object:Gem::Version
124
+ version: '0'
125
+ description: |+
126
+ == Description
127
+
128
+ A Rack compatible JSON-RPC2 server domain specific language (DSL) - allows JSONRPC APIs to be
129
+ defined as mountable Rack applications with inline documentation, authentication and type checking.
130
+
131
+ e.g.
132
+
133
+ class Calculator < JSONRPC2::Interface
134
+ title "JSON-RPC2 Calculator"
135
+ introduction "This interface allows basic maths calculations via JSON-RPC2"
136
+ auth_with JSONRPC2::BasicAuth.new({'user' => 'secretword'})
137
+
138
+ section 'Simple Ops' do
139
+ desc 'Multiply two numbers'
140
+ param 'a', 'Number', 'a'
141
+ param 'b', 'Number', 'b'
142
+ result 'Number', 'a * b'
143
+ def mul args
144
+ args['a'] * args['b']
145
+ end
146
+
147
+ desc 'Add numbers'
148
+ example "Calculate 1 + 1 = 2", :params => { 'a' => 1, 'b' => 1}, :result => 2
149
+
150
+ param 'a', 'Number', 'First number'
151
+ param 'b', 'Number', 'Second number'
152
+ optional 'c', 'Number', 'Third number'
153
+ result 'Number', 'a + b + c'
154
+ def sum args
155
+ val = args['a'] + args['b']
156
+ val += args['c'] if args['c']
157
+ val
158
+ end
159
+ end
160
+ end
161
+
83
162
  email:
84
163
  - git@intersect-uk.co.uk
85
164
  executables:
@@ -87,12 +166,19 @@ executables:
87
166
  extensions: []
88
167
  extra_rdoc_files: []
89
168
  files:
90
- - .gitignore
169
+ - ".github/workflows/test.yml"
170
+ - ".gitignore"
171
+ - ".rspec"
172
+ - CHANGELOG.md
173
+ - Dockerfile
91
174
  - Gemfile
92
175
  - README.markdown
93
176
  - Rakefile
94
- - bin/jsonrpc2
177
+ - bin/run-example
178
+ - bin/setup
179
+ - bin/test
95
180
  - example/config.ru
181
+ - exe/jsonrpc2
96
182
  - jsonrpc2.gemspec
97
183
  - lib/assets/css/bootstrap.css
98
184
  - lib/assets/css/bootstrap.min.css
@@ -110,28 +196,36 @@ files:
110
196
  - lib/jsonrpc2/textile.rb
111
197
  - lib/jsonrpc2/types.rb
112
198
  - lib/jsonrpc2/version.rb
199
+ - spec/lib/interface_spec.rb
200
+ - spec/spec_helper.rb
113
201
  - test/test_types.rb
114
- homepage: http://github.com/geoffyoungs/jsonrpc2
202
+ homepage: http://github.com/livelink/jsonrpc2
115
203
  licenses: []
116
- metadata: {}
117
- post_install_message:
204
+ metadata:
205
+ bug_tracker_uri: https://github.com/livelink/jsonrpc2/issues
206
+ changelog_uri: https://github.com/livelink/jsonrpc2/blob/master/CHANGELOG.md
207
+ documentation_uri: https://github.com/livelink/jsonrpc2#inline-documentation
208
+ post_install_message:
118
209
  rdoc_options: []
119
210
  require_paths:
120
211
  - lib
121
212
  required_ruby_version: !ruby/object:Gem::Requirement
122
213
  requirements:
123
- - - '>='
214
+ - - ">="
124
215
  - !ruby/object:Gem::Version
125
216
  version: '0'
126
217
  required_rubygems_version: !ruby/object:Gem::Requirement
127
218
  requirements:
128
- - - '>='
219
+ - - ">="
129
220
  - !ruby/object:Gem::Version
130
221
  version: '0'
131
222
  requirements: []
132
- rubyforge_project:
133
- rubygems_version: 2.0.3
134
- signing_key:
223
+ rubygems_version: 3.1.4
224
+ signing_key:
135
225
  specification_version: 4
136
226
  summary: JSON-RPC2 server DSL
137
- test_files: []
227
+ test_files:
228
+ - spec/lib/interface_spec.rb
229
+ - spec/spec_helper.rb
230
+ - test/test_types.rb
231
+ ...