jsonrpc-middleware 0.4.0 → 0.6.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.
@@ -8,6 +8,13 @@ module JSONRPC
8
8
  app.middleware.use JSONRPC::Middleware
9
9
  end
10
10
 
11
+ # Register the JSON-RPC routes DSL extension
12
+ initializer 'jsonrpc.routes_dsl' do
13
+ ActiveSupport.on_load(:action_controller) do
14
+ ActionDispatch::Routing::Mapper.include(JSONRPC::MapperExtension)
15
+ end
16
+ end
17
+
11
18
  initializer 'jsonrpc.renderer' do
12
19
  ActiveSupport.on_load(:action_controller) do
13
20
  Mime::Type.register 'application/json', :jsonrpc
@@ -28,7 +35,7 @@ module JSONRPC
28
35
  self.response_body = ''
29
36
  ''
30
37
  else
31
- result_data.to_json
38
+ MultiJson.dump(result_data)
32
39
  end
33
40
  elsif jsonrpc_notification?
34
41
  # Notification - no response body
@@ -37,7 +44,7 @@ module JSONRPC
37
44
  ''
38
45
  else
39
46
  # Fallback - treat as regular JSON-RPC response
40
- result_data.to_json
47
+ MultiJson.dump(result_data)
41
48
  end
42
49
  end
43
50
  end
@@ -13,7 +13,7 @@ module JSONRPC
13
13
  # @example Create a request with named parameters
14
14
  # request = JSONRPC::Request.new(method: "subtract", params: { minuend: 42, subtrahend: 23 }, id: 3)
15
15
  #
16
- class Request
16
+ class Request < Dry::Struct
17
17
  # JSON-RPC protocol version
18
18
  #
19
19
  # @api public
@@ -23,7 +23,7 @@ module JSONRPC
23
23
  #
24
24
  # @return [String]
25
25
  #
26
- attr_reader :jsonrpc
26
+ attribute :jsonrpc, Types::String.default('2.0')
27
27
 
28
28
  # The method name to invoke
29
29
  #
@@ -34,7 +34,7 @@ module JSONRPC
34
34
  #
35
35
  # @return [String]
36
36
  #
37
- attr_reader :method
37
+ attribute :method, Types::String.constrained(format: /\A(?!rpc\.)/)
38
38
 
39
39
  # Parameters to pass to the method
40
40
  #
@@ -45,7 +45,7 @@ module JSONRPC
45
45
  #
46
46
  # @return [Hash, Array, nil]
47
47
  #
48
- attr_reader :params
48
+ attribute? :params, (Types::Hash | Types::Array).optional
49
49
 
50
50
  # The request identifier
51
51
  #
@@ -56,36 +56,7 @@ module JSONRPC
56
56
  #
57
57
  # @return [String, Integer, nil]
58
58
  #
59
- attr_reader :id
60
-
61
- # Creates a new JSON-RPC 2.0 Request object
62
- #
63
- # @api public
64
- #
65
- # @example Create a request with positional parameters
66
- # JSONRPC::Request.new(method: "subtract", params: [42, 23], id: 1)
67
- #
68
- # @param method [String] the name of the method to be invoked
69
- # @param params [Hash, Array, nil] the parameters to be used during method invocation
70
- # @param id [String, Integer, nil] the request identifier
71
- #
72
- # @raise [ArgumentError] if method is not a String or is reserved
73
- #
74
- # @raise [ArgumentError] if params is not a Hash, Array, or nil
75
- #
76
- # @raise [ArgumentError] if id is not a String, Integer, or nil
77
- #
78
- def initialize(method:, id:, params: nil)
79
- @jsonrpc = '2.0'
80
-
81
- validate_method(method)
82
- validate_params(params)
83
- validate_id(id)
84
-
85
- @method = method
86
- @params = params
87
- @id = id
88
- end
59
+ attribute? :id, Types::String | Types::Integer | Types::Nil
89
60
 
90
61
  # Converts the request to a JSON-compatible Hash
91
62
  #
@@ -119,61 +90,18 @@ module JSONRPC
119
90
  # @return [String] the request as a JSON string
120
91
  #
121
92
  def to_json(*)
122
- to_h.to_json(*)
93
+ MultiJson.dump(to_h, *)
123
94
  end
124
95
 
125
- private
126
-
127
- # Validates that the method name meets JSON-RPC 2.0 requirements
128
- #
129
- # @api private
130
- #
131
- # @param method [String] the method name
132
- #
133
- # @raise [ArgumentError] if method is not a String or is reserved
134
- #
135
- # @return [void]
136
- #
137
- def validate_method(method)
138
- raise ArgumentError, 'Method must be a String' unless method.is_a?(String)
139
-
140
- return unless method.start_with?('rpc.')
141
-
142
- raise ArgumentError, "Method names starting with 'rpc.' are reserved"
143
- end
144
-
145
- # Validates that the params is a valid structure according to JSON-RPC 2.0
146
- #
147
- # @api private
148
- #
149
- # @param params [Hash, Array, nil] the parameters
150
- #
151
- # @raise [ArgumentError] if params is not a Hash, Array, or nil
152
- #
153
- # @return [void]
154
- #
155
- def validate_params(params)
156
- return if params.nil?
157
-
158
- return if params.is_a?(Hash) || params.is_a?(Array)
159
-
160
- raise ArgumentError, 'Params must be an Object, Array, or omitted'
161
- end
162
-
163
- # Validates that the id meets JSON-RPC 2.0 requirements
164
- #
165
- # @api private
96
+ # The method name to invoke
166
97
  #
167
- # @param id [String, Integer, nil] the request identifier
98
+ # @api public
168
99
  #
169
- # @raise [ArgumentError] if id is not a String, Integer, or nil
100
+ # @example
101
+ # request.method # => "subtract"
170
102
  #
171
- # @return [void]
103
+ # @return [String]
172
104
  #
173
- def validate_id(id)
174
- return if id.nil?
175
-
176
- raise ArgumentError, 'ID must be a String, Integer, or nil' unless id.is_a?(String) || id.is_a?(Integer)
177
- end
105
+ def method = attributes[:method]
178
106
  end
179
107
  end
@@ -19,7 +19,9 @@ module JSONRPC
19
19
  # error = JSONRPC::Error.new(code: -32601, message: "Method not found")
20
20
  # response = JSONRPC::Response.new(error: error, id: 1)
21
21
  #
22
- class Response
22
+ class Response < Dry::Struct
23
+ transform_keys(&:to_sym)
24
+
23
25
  # JSON-RPC protocol version
24
26
  #
25
27
  # @api public
@@ -29,7 +31,7 @@ module JSONRPC
29
31
  #
30
32
  # @return [String]
31
33
  #
32
- attr_reader :jsonrpc
34
+ attribute :jsonrpc, Types::String.default('2.0')
33
35
 
34
36
  # The result of the method invocation (for success)
35
37
  #
@@ -40,7 +42,7 @@ module JSONRPC
40
42
  #
41
43
  # @return [Object, nil]
42
44
  #
43
- attr_reader :result
45
+ attribute? :result, Types::Any
44
46
 
45
47
  # The error object (for failure)
46
48
  #
@@ -51,7 +53,7 @@ module JSONRPC
51
53
  #
52
54
  # @return [JSONRPC::Error, nil]
53
55
  #
54
- attr_reader :error
56
+ attribute? :error, Types.Instance(JSONRPC::Error).optional
55
57
 
56
58
  # The request identifier
57
59
  #
@@ -62,7 +64,7 @@ module JSONRPC
62
64
  #
63
65
  # @return [String, Integer, nil]
64
66
  #
65
- attr_reader :id
67
+ attribute? :id, Types::String | Types::Integer | Types::Nil
66
68
 
67
69
  # Creates a new JSON-RPC 2.0 Response object
68
70
  #
@@ -85,16 +87,6 @@ module JSONRPC
85
87
  #
86
88
  # @raise [ArgumentError] if id is not a String, Integer, or nil
87
89
  #
88
- def initialize(id:, result: nil, error: nil)
89
- @jsonrpc = '2.0'
90
-
91
- validate_result_and_error(result, error)
92
- validate_id(id)
93
-
94
- @result = result
95
- @error = error
96
- @id = id
97
- end
98
90
 
99
91
  # Checks if the response is successful
100
92
  #
@@ -106,7 +98,7 @@ module JSONRPC
106
98
  # @return [Boolean] true if the response contains a result, false if it contains an error
107
99
  #
108
100
  def success?
109
- !@result.nil?
101
+ !result.nil?
110
102
  end
111
103
 
112
104
  # Checks if the response is an error
@@ -119,7 +111,7 @@ module JSONRPC
119
111
  # @return [Boolean] true if the response contains an error, false if it contains a result
120
112
  #
121
113
  def error?
122
- !@error.nil?
114
+ !error.nil?
123
115
  end
124
116
 
125
117
  # Converts the response to a JSON-compatible Hash
@@ -156,48 +148,7 @@ module JSONRPC
156
148
  # @return [String] the response as a JSON string
157
149
  #
158
150
  def to_json(*)
159
- to_h.to_json(*)
160
- end
161
-
162
- private
163
-
164
- # Validates that exactly one of result or error is present
165
- #
166
- # @api private
167
- #
168
- # @param result [Object, nil] the result
169
- # @param error [JSONRPC::Error, nil] the error
170
- #
171
- # @raise [ArgumentError] if both result and error are present or both are nil
172
- #
173
- # @raise [ArgumentError] if error is present but not a JSONRPC::Error
174
- #
175
- # @return [void]
176
- #
177
- def validate_result_and_error(result, error)
178
- raise ArgumentError, 'Either result or error must be present' if result.nil? && error.nil?
179
-
180
- raise ArgumentError, 'Response cannot contain both result and error' if !result.nil? && !error.nil?
181
-
182
- return unless !error.nil? && !error.is_a?(Error)
183
-
184
- raise ArgumentError, 'Error must be a JSONRPC::Error'
185
- end
186
-
187
- # Validates that the id meets JSON-RPC 2.0 requirements
188
- #
189
- # @api private
190
- #
191
- # @param id [String, Integer, nil] the request identifier
192
- #
193
- # @raise [ArgumentError] if id is not a String, Integer, or nil
194
- #
195
- # @return [void]
196
- #
197
- def validate_id(id)
198
- return if id.nil?
199
-
200
- raise ArgumentError, 'ID must be a String, Integer, or nil' unless id.is_a?(String) || id.is_a?(Integer)
151
+ MultiJson.dump(to_h, *)
201
152
  end
202
153
  end
203
154
  end
@@ -0,0 +1,13 @@
1
+ # frozen_string_literal: true
2
+
3
+ module JSONRPC
4
+ # Container for dry-types
5
+ #
6
+ # @api private
7
+ #
8
+ # @see https://dry-rb.org/gems/dry-types/ Dry::Types documentation
9
+ #
10
+ module Types
11
+ include Dry.Types()
12
+ end
13
+ end
@@ -11,5 +11,5 @@ module JSONRPC
11
11
  #
12
12
  # @return [String] The current version number
13
13
  #
14
- VERSION = '0.4.0'
14
+ VERSION = '0.6.0'
15
15
  end
data/lib/jsonrpc.rb CHANGED
@@ -1,7 +1,9 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  require 'zeitwerk'
4
+ require 'dry-struct'
4
5
  require 'dry-validation'
6
+ require 'multi_json'
5
7
 
6
8
  Dry::Validation.load_extensions(:predicates_as_macros)
7
9
 
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: jsonrpc-middleware
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.4.0
4
+ version: 0.6.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Wilson Silva
@@ -9,6 +9,20 @@ bindir: exe
9
9
  cert_chain: []
10
10
  date: 1980-01-02 00:00:00.000000000 Z
11
11
  dependencies:
12
+ - !ruby/object:Gem::Dependency
13
+ name: dry-struct
14
+ requirement: !ruby/object:Gem::Requirement
15
+ requirements:
16
+ - - "~>"
17
+ - !ruby/object:Gem::Version
18
+ version: '1.8'
19
+ type: :runtime
20
+ prerelease: false
21
+ version_requirements: !ruby/object:Gem::Requirement
22
+ requirements:
23
+ - - "~>"
24
+ - !ruby/object:Gem::Version
25
+ version: '1.8'
12
26
  - !ruby/object:Gem::Dependency
13
27
  name: dry-validation
14
28
  requirement: !ruby/object:Gem::Requirement
@@ -23,6 +37,20 @@ dependencies:
23
37
  - - "~>"
24
38
  - !ruby/object:Gem::Version
25
39
  version: '1.11'
40
+ - !ruby/object:Gem::Dependency
41
+ name: multi_json
42
+ requirement: !ruby/object:Gem::Requirement
43
+ requirements:
44
+ - - "~>"
45
+ - !ruby/object:Gem::Version
46
+ version: '1.17'
47
+ type: :runtime
48
+ prerelease: false
49
+ version_requirements: !ruby/object:Gem::Requirement
50
+ requirements:
51
+ - - "~>"
52
+ - !ruby/object:Gem::Version
53
+ version: '1.17'
26
54
  - !ruby/object:Gem::Dependency
27
55
  name: zeitwerk
28
56
  requirement: !ruby/object:Gem::Requirement
@@ -45,8 +73,9 @@ executables: []
45
73
  extensions: []
46
74
  extra_rdoc_files: []
47
75
  files:
48
- - ".aiexclude"
76
+ - ".aiignore"
49
77
  - ".claude/commands/document.md"
78
+ - ".claude/commands/gemfile/update.md"
50
79
  - ".claude/commands/test.md"
51
80
  - ".claude/docs/yard.md"
52
81
  - ".claude/settings.local.json"
@@ -80,6 +109,8 @@ files:
80
109
  - examples/rack/README.md
81
110
  - examples/rack/app.rb
82
111
  - examples/rack/config.ru
112
+ - examples/rails-routing-dsl/README.md
113
+ - examples/rails-routing-dsl/config.ru
83
114
  - examples/rails-single-file-routing/README.md
84
115
  - examples/rails-single-file-routing/config.ru
85
116
  - examples/rails-single-file/README.md
@@ -136,9 +167,13 @@ files:
136
167
  - lib/jsonrpc/notification.rb
137
168
  - lib/jsonrpc/parser.rb
138
169
  - lib/jsonrpc/railtie.rb
170
+ - lib/jsonrpc/railtie/batch_constraint.rb
171
+ - lib/jsonrpc/railtie/mapper_extension.rb
139
172
  - lib/jsonrpc/railtie/method_constraint.rb
173
+ - lib/jsonrpc/railtie/routes_dsl.rb
140
174
  - lib/jsonrpc/request.rb
141
175
  - lib/jsonrpc/response.rb
176
+ - lib/jsonrpc/types.rb
142
177
  - lib/jsonrpc/validator.rb
143
178
  - lib/jsonrpc/version.rb
144
179
  - sig/jsonrpc.rbs
@@ -166,7 +201,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
166
201
  - !ruby/object:Gem::Version
167
202
  version: '0'
168
203
  requirements: []
169
- rubygems_version: 3.7.0
204
+ rubygems_version: 3.7.2
170
205
  specification_version: 4
171
206
  summary: Rack middleware implementing the JSON-RPC 2.0 protocol.
172
207
  test_files: []
File without changes