jsonrpc-middleware 0.1.0 → 0.2.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.
Files changed (76) hide show
  1. checksums.yaml +4 -4
  2. data/.aiexclude +4 -0
  3. data/.claude/commands/document.md +105 -0
  4. data/.claude/docs/yard.md +602 -0
  5. data/.claude/settings.local.json +2 -1
  6. data/.env.example +5 -0
  7. data/CHANGELOG.md +22 -2
  8. data/CLAUDE.md +114 -0
  9. data/README.md +42 -102
  10. data/Rakefile +59 -1
  11. data/examples/README.md +37 -0
  12. data/examples/procedures.rb +6 -1
  13. data/examples/rack/README.md +26 -1
  14. data/examples/rack/app.rb +1 -1
  15. data/examples/rack-echo/README.md +23 -1
  16. data/examples/rack-single-file/README.md +37 -0
  17. data/examples/rack-single-file/config.ru +54 -0
  18. data/examples/rails/.gitignore +21 -0
  19. data/examples/rails/.ruby-version +1 -0
  20. data/examples/rails/Gemfile +15 -0
  21. data/examples/rails/Gemfile.lock +261 -0
  22. data/examples/rails/README.md +32 -0
  23. data/examples/rails/Rakefile +8 -0
  24. data/examples/rails/app/controllers/application_controller.rb +4 -0
  25. data/examples/rails/app/controllers/jsonrpc_controller.rb +44 -0
  26. data/examples/rails/bin/dev +4 -0
  27. data/examples/rails/bin/rails +6 -0
  28. data/examples/rails/bin/rake +6 -0
  29. data/examples/rails/bin/setup +28 -0
  30. data/examples/rails/config/application.rb +47 -0
  31. data/examples/rails/config/boot.rb +5 -0
  32. data/examples/rails/config/credentials.yml.enc +1 -0
  33. data/examples/rails/config/environment.rb +7 -0
  34. data/examples/rails/config/environments/development.rb +42 -0
  35. data/examples/rails/config/environments/production.rb +60 -0
  36. data/examples/rails/config/environments/test.rb +44 -0
  37. data/examples/rails/config/initializers/cors.rb +18 -0
  38. data/examples/rails/config/initializers/filter_parameter_logging.rb +10 -0
  39. data/examples/rails/config/initializers/inflections.rb +18 -0
  40. data/examples/rails/config/initializers/jsonrpc.rb +62 -0
  41. data/examples/rails/config/locales/en.yml +31 -0
  42. data/examples/rails/config/puma.rb +40 -0
  43. data/examples/rails/config/routes.rb +14 -0
  44. data/examples/rails/config.ru +8 -0
  45. data/examples/rails/public/robots.txt +1 -0
  46. data/examples/rails-single-file/config.ru +71 -0
  47. data/examples/sinatra-classic/Gemfile +9 -0
  48. data/examples/sinatra-classic/Gemfile.lock +95 -0
  49. data/examples/sinatra-classic/README.md +32 -0
  50. data/examples/sinatra-classic/app.rb +54 -0
  51. data/examples/sinatra-classic/config.ru +6 -0
  52. data/examples/sinatra-modular/Gemfile +9 -0
  53. data/examples/sinatra-modular/Gemfile.lock +95 -0
  54. data/examples/sinatra-modular/README.md +32 -0
  55. data/examples/sinatra-modular/app.rb +57 -0
  56. data/examples/sinatra-modular/config.ru +6 -0
  57. data/lib/jsonrpc/batch_request.rb +67 -2
  58. data/lib/jsonrpc/batch_response.rb +56 -0
  59. data/lib/jsonrpc/configuration.rb +156 -14
  60. data/lib/jsonrpc/error.rb +83 -2
  61. data/lib/jsonrpc/errors/internal_error.rb +14 -2
  62. data/lib/jsonrpc/errors/invalid_params_error.rb +13 -1
  63. data/lib/jsonrpc/errors/invalid_request_error.rb +8 -0
  64. data/lib/jsonrpc/errors/method_not_found_error.rb +8 -0
  65. data/lib/jsonrpc/errors/parse_error.rb +8 -0
  66. data/lib/jsonrpc/helpers.rb +212 -21
  67. data/lib/jsonrpc/middleware.rb +211 -5
  68. data/lib/jsonrpc/notification.rb +58 -0
  69. data/lib/jsonrpc/parser.rb +30 -0
  70. data/lib/jsonrpc/railtie.rb +57 -0
  71. data/lib/jsonrpc/request.rb +68 -1
  72. data/lib/jsonrpc/response.rb +76 -0
  73. data/lib/jsonrpc/validator.rb +67 -6
  74. data/lib/jsonrpc/version.rb +11 -1
  75. data/lib/jsonrpc.rb +53 -1
  76. metadata +49 -1
@@ -2,7 +2,8 @@
2
2
  "permissions": {
3
3
  "allow": [
4
4
  "Bash(bundle exec rspec:*)",
5
- "Bash(bundle exec rubocop:*)"
5
+ "Bash(bundle exec rubocop:*)",
6
+ "Bash(bundle exec rake:*)"
6
7
  ]
7
8
  },
8
9
  "enableAllProjectMcpServers": false
data/.env.example ADDED
@@ -0,0 +1,5 @@
1
+ # Whether the code coverage is displayed in the terminal after the test run
2
+ COVERAGE=false
3
+
4
+ # Enable debug mode for Zeitwerk autoloader (shows file loading activity)
5
+ DEBUG_ZEITWERK=false
data/CHANGELOG.md CHANGED
@@ -7,6 +7,25 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
7
7
 
8
8
  ## [Unreleased]
9
9
 
10
+ ## [0.2.0] - 2025-07-10
11
+
12
+ ### Added
13
+ - Rails support via Railtie for automatic middleware registration
14
+ - Configuration options for logging, internal error handling, and error rendering
15
+ - Complete YARD documentation for all public APIs
16
+ - Rails application examples (single-file and full application)
17
+ - Sinatra application examples (classic and modular styles)
18
+ - Pure Rack application examples
19
+ - AI development guidelines for Claude Code, Copilot, and Cursor
20
+
21
+ ### Changed
22
+ - Enhanced helper methods with improved framework-agnostic support
23
+ - Improved error handling with configurable logging capabilities
24
+ - Updated development dependencies for better compatibility
25
+
26
+ ### Fixed
27
+ - Method parameter handling in Rack examples
28
+
10
29
  ## [0.1.0] - 2025-06-14
11
30
 
12
31
  ### Added
@@ -33,5 +52,6 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
33
52
  - Helper methods for request and response processing
34
53
  - Examples for basic and advanced usage scenarios
35
54
 
36
- [Unreleased]: https://github.com/wilsonsilva/jsonrpc-middleware/compare/v0.1.0...HEAD
37
- [0.1.0]: https://github.com/wilsonsilva/jsonrpc-middleware/releases/tag/v0.1.0
55
+ [Unreleased]: https://github.com/wilsonsilva/jsonrpc-middleware/compare/v0.2.0...HEAD
56
+ [0.2.0]: https://github.com/wilsonsilva/jsonrpc-middleware/compare/v0.1.0...v0.2.0
57
+ [0.1.0]: https://github.com/wilsonsilva/jsonrpc-middleware/compare/745b5a...v0.1.0
data/CLAUDE.md ADDED
@@ -0,0 +1,114 @@
1
+ # CLAUDE.md
2
+
3
+ This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
4
+
5
+ ## Development Commands
6
+
7
+ ### Testing
8
+ - `bundle exec rspec` - Run all tests
9
+ - `bundle exec rspec spec/path/to/spec.rb` - Run specific test file
10
+ - `rake coverage` - Run tests with coverage report (opens in browser)
11
+
12
+ ### Code Quality
13
+ - `bundle exec rake qa` - Complete quality check (tests, linting, security, docs)
14
+ - `bundle exec rubocop` - Run Ruby linter
15
+ - `bundle exec rubocop --autocorrect` - Auto-fix safe Ruby style issues
16
+ - `bundle exec rubocop --autocorrect-all` - Auto-fix all Ruby style issues
17
+ - `bundle exec steep check` - Run type checking with Steep/RBS
18
+
19
+ ### Security & Dependencies
20
+ - `bundle exec rake bundle:audit:check` - Check for vulnerable dependencies
21
+ - `bundle exec rake bundle:audit:update` - Update vulnerability database
22
+
23
+ ### Documentation
24
+ - `bundle exec rake yard` - Generate YARD documentation
25
+ - `bundle exec rake yard:format` - Format YARD comments in code
26
+ - `bundle exec rake verify_measurements` - Verify 100% documentation coverage
27
+
28
+ ### Build & Release
29
+ - `bundle exec rake build` - Build gem package
30
+ - `bundle exec rake install` - Install gem locally
31
+ - `bin/console` - Interactive console with gem loaded
32
+
33
+ ## Architecture Overview
34
+
35
+ ### Core Components
36
+
37
+ **JSONRPC Module** (`lib/jsonrpc.rb`)
38
+ - Main entry point with configuration DSL
39
+ - Uses Zeitwerk for autoloading with specific inflection rules
40
+ - Singleton Configuration pattern for procedure definitions
41
+
42
+ **Middleware** (`lib/jsonrpc/middleware.rb`)
43
+ - Rack middleware implementing JSON-RPC 2.0 specification
44
+ - Handles parsing, validation, and error responses
45
+ - Supports single requests, notifications, and batch operations
46
+ - Complex batch processing with mixed error/success handling
47
+
48
+ **Parser** (`lib/jsonrpc/parser.rb`)
49
+ - Converts JSON strings into Request/Notification/BatchRequest objects
50
+ - Handles malformed JSON and invalid request structures
51
+
52
+ **Validator** (`lib/jsonrpc/validator.rb`)
53
+ - Validates requests against procedure definitions using dry-validation
54
+ - Supports both positional and named parameters
55
+ - Handles method existence and parameter validation
56
+
57
+ **Helpers** (`lib/jsonrpc/helpers.rb`)
58
+ - Framework-agnostic helper methods for apps
59
+ - Provides convenience methods for checking request types
60
+ - Response generation helpers for different scenarios
61
+
62
+ ### Request/Response Objects
63
+ - `Request` - Standard JSON-RPC request with id
64
+ - `Notification` - Request without id (no response expected)
65
+ - `BatchRequest` - Collection of requests/notifications
66
+ - `Response` - JSON-RPC response with result or error
67
+ - `BatchResponse` - Collection of responses
68
+
69
+ ### Error System
70
+ Structured error hierarchy in `lib/jsonrpc/errors/`:
71
+ - `ParseError` (-32700) - Invalid JSON
72
+ - `InvalidRequestError` (-32600) - Invalid request object
73
+ - `MethodNotFoundError` (-32601) - Method not found
74
+ - `InvalidParamsError` (-32602) - Invalid parameters
75
+ - `InternalError` (-32603) - Server error
76
+
77
+ ### Configuration DSL
78
+ ```ruby
79
+ JSONRPC.configure do
80
+ procedure('method_name') do
81
+ params do
82
+ required(:param).value(:type)
83
+ end
84
+
85
+ rule(:param) do
86
+ # Custom validation rules
87
+ end
88
+ end
89
+ end
90
+ ```
91
+
92
+ ## Type System
93
+
94
+ The project uses RBS (Ruby Type Signatures) with Steep for type checking:
95
+ - Type definitions in `sig/` directory
96
+ - Run `bundle exec steep check` for type validation
97
+ - Generate types with `bundle exec typeprof FILENAME`
98
+
99
+ ## Examples
100
+
101
+ Comprehensive examples in `examples/` directory showing integration with:
102
+ - Pure Rack applications
103
+ - Sinatra (classic and modular)
104
+ - Single-file applications with bundler/inline
105
+
106
+ Each example implements calculator operations (add, subtract, multiply, divide) demonstrating different usage patterns.
107
+
108
+ ## Testing Strategy
109
+
110
+ - RSpec with comprehensive test coverage
111
+ - Factory Bot for test data generation
112
+ - Rack::Test for middleware testing
113
+ - SimpleCov for coverage reporting with multiple formatters
114
+ - Examples include both unit and integration tests
data/README.md CHANGED
@@ -1,9 +1,9 @@
1
- # JSONRPC::Middleware - Ruby JSON-RPC Implementation
1
+ # JSONRPC::Middleware
2
2
 
3
3
  [![Gem Version](https://badge.fury.io/rb/jsonrpc-middleware.svg)](https://badge.fury.io/rb/jsonrpc-middleware)
4
4
  ![Build](https://github.com/wilsonsilva/jsonrpc-middleware/actions/workflows/main.yml/badge.svg)
5
- [![Maintainability](https://qlty.sh/badges/73ebc4bb-d1db-4b5b-9a7c-a4acd59dfe69/maintainability.svg)](https://qlty.sh/gh/wilsonsilva/projects/jsonrpc-middleware)
6
- [![Code Coverage](https://qlty.sh/badges/73ebc4bb-d1db-4b5b-9a7c-a4acd59dfe69/test_coverage.svg)](https://qlty.sh/gh/wilsonsilva/projects/jsonrpc-middleware)
5
+ [![Maintainability](https://qlty.sh/badges/a275de81-94e3-45af-9469-523aa5345871/maintainability.svg)](https://qlty.sh/gh/wilsonsilva/projects/jsonrpc-middleware)
6
+ [![Code Coverage](https://qlty.sh/badges/a275de81-94e3-45af-9469-523aa5345871/test_coverage.svg)](https://qlty.sh/gh/wilsonsilva/projects/jsonrpc-middleware)
7
7
 
8
8
  A Ruby implementation of the JSON-RPC protocol, enabling standardized communication between systems via remote procedure
9
9
  calls encoded in JSON.
@@ -13,63 +13,52 @@ calls encoded in JSON.
13
13
  - [Key features](#-key-features)
14
14
  - [Installation](#-installation)
15
15
  - [Quickstart](#-quickstart)
16
+ - [Examples](#-examples)
16
17
  - [Documentation](#-documentation)
17
18
  - [Development](#-development)
18
- * [Type checking](#type-checking)
19
+ * [Type checking](#-type-checking)
19
20
  - [Contributing](#-contributing)
20
21
  - [License](#-license)
21
22
  - [Code of Conduct](#-code-of-conduct)
22
23
 
23
24
  ## 🔑 Key features
24
25
 
25
- - **Complete JSON-RPC 2.0 Implementation**: Fully implements the [JSON-RPC 2.0 specification](https://www.jsonrpc.org/specification)
26
- - **Rack Middleware integration**: Seamlessly integrates with Rack applications
27
- - **Advanced request validation**: Define request parameter specifications and validations using `Dry::Validation`
26
+ - **Spec-compliant**: Fully implements the [JSON-RPC 2.0 specification](https://www.jsonrpc.org/specification)
27
+ - **Rack middleware integration**: Seamlessly integrates with Rack applications (Rails, Sinatra, Hanami, etc)
28
28
  - **Support for all request types**: Handles single requests, notifications, and batch requests
29
- - **Parameter validation**: Supports both positional and named arguments with customizable validation rules
30
29
  - **Error handling**: Comprehensive error handling with standard JSON-RPC error responses
31
- - **Helper methods**: Convenient helper methods to simplify request and response processing
32
- - **Type checking**: Ruby type checking support via RBS definitions
30
+ - **Request validation**: Define request parameter specifications and validations
31
+ - **Helpers**: Convenient helper methods to simplify request and response processing
33
32
 
34
33
  ## 📦 Installation
35
34
 
36
- Install the gem by executing:
35
+ Install the gem and add to the application's Gemfile by executing:
36
+
37
+ $ bundle add jsonrpc-middleware
38
+
39
+ If bundler is not being used to manage dependencies, install the gem by executing:
37
40
 
38
41
  $ gem install jsonrpc-middleware
39
42
 
40
43
  ## ⚡️ Quickstart
41
44
 
42
- ### Basic Setup with Rack
45
+ Create a file called `config.ru` and run `bundle exec rackup`:
43
46
 
44
47
  ```ruby
45
- # Gemfile
46
- source 'https://rubygems.org'
47
- gem 'jsonrpc-middleware'
48
- gem 'rack'
49
- ```
50
-
51
- ```ruby
52
- # config.ru
53
- require 'jsonrpc'
54
- require_relative 'app'
55
-
56
- # Use the middleware
57
- use JSONRPC::Middleware
48
+ # frozen_string_literal: true
58
49
 
59
- # Your application
60
- run App.new
61
- ```
50
+ require 'bundler/inline'
62
51
 
63
- ### Define Your JSON-RPC Procedures
52
+ gemfile do
53
+ source 'https://rubygems.org'
64
54
 
65
- Define your available procedures with validation rules:
66
-
67
- ```ruby
68
- # procedures.rb
69
- require 'jsonrpc'
55
+ gem 'jsonrpc-middleware', require: 'jsonrpc'
56
+ gem 'puma'
57
+ gem 'rack'
58
+ gem 'rackup'
59
+ end
70
60
 
71
61
  JSONRPC.configure do
72
- # Define a procedure that accepts both positional and named arguments
73
62
  procedure(:add, allow_positional_arguments: true) do
74
63
  params do
75
64
  required(:addends).filled(:array)
@@ -80,37 +69,21 @@ JSONRPC.configure do
80
69
  key.failure('must contain at least one addend') if value.empty?
81
70
  end
82
71
  end
83
-
84
- # Define a procedure with named arguments only
85
- procedure(:subtract) do
86
- params do
87
- required(:minuend).filled(:integer)
88
- required(:subtrahend).filled(:integer)
89
- end
90
- end
91
72
  end
92
- ```
93
-
94
- ### Create Your Application
95
73
 
96
- ```ruby
97
- # app.rb
98
74
  class App
99
75
  include JSONRPC::Helpers
100
76
 
101
77
  def call(env)
102
- @env = env # Set the env instance variable to use JSONRPC helpers
78
+ @env = env
103
79
 
104
80
  if jsonrpc_request?
105
- # Handle a standard JSON-RPC request
106
81
  result = handle_single(jsonrpc_request)
107
82
  jsonrpc_response(result)
108
83
  elsif jsonrpc_notification?
109
- # Handle a notification (no response needed)
110
84
  handle_single(jsonrpc_notification)
111
85
  jsonrpc_notification_response
112
86
  else
113
- # Handle batch requests
114
87
  responses = handle_batch(jsonrpc_batch)
115
88
  jsonrpc_batch_response(responses)
116
89
  end
@@ -121,68 +94,34 @@ class App
121
94
  def handle_single(request_or_notification)
122
95
  params = request_or_notification.params
123
96
 
124
- case request_or_notification.method
125
- when 'add'
126
- # Handle both positional and named arguments
127
- addends = params.is_a?(Array) ? params : params['addends']
128
- addends.sum
129
- when 'subtract'
130
- params['minuend'] - params['subtrahend']
131
- end
97
+ addends = params.is_a?(Array) ? params : params['addends'] # Handle positional and named arguments
98
+ addends.sum
132
99
  end
133
100
 
134
101
  def handle_batch(batch)
135
102
  batch.flat_map do |request_or_notification|
136
103
  result = handle_single(request_or_notification)
137
- # Only create responses for requests, not notifications
138
- JSONRPC::Response.new(id: request_or_notification.id, result: result) if request_or_notification.is_a?(JSONRPC::Request)
104
+ JSONRPC::Response.new(id: request_or_notification.id, result:) if request_or_notification.is_a?(JSONRPC::Request)
139
105
  end.compact
140
106
  end
141
107
  end
142
- ```
143
108
 
144
- ### Example Requests
145
-
146
- Here are example JSON-RPC requests you can make to your application:
147
-
148
- ```json
149
- // Standard request with named params
150
- {
151
- "jsonrpc": "2.0",
152
- "method": "subtract",
153
- "params": {
154
- "minuend": 42,
155
- "subtrahend": 23
156
- },
157
- "id": 1
158
- }
159
-
160
- // Request with positional params (if allowed)
161
- {
162
- "jsonrpc": "2.0",
163
- "method": "add",
164
- "params": [1, 2, 3, 4, 5],
165
- "id": 2
166
- }
167
-
168
- // Notification (no response)
169
- {
170
- "jsonrpc": "2.0",
171
- "method": "add",
172
- "params": {"addends": [1, 2, 3]}
173
- }
174
-
175
- // Batch request
176
- [
177
- {"jsonrpc": "2.0", "method": "add", "params": {"addends": [1, 2]}, "id": 1},
178
- {"jsonrpc": "2.0", "method": "subtract", "params": {"minuend": 10, "subtrahend": 5}, "id": 2}
179
- ]
109
+ use JSONRPC::Middleware
110
+ run App.new
180
111
  ```
181
112
 
113
+ This will give you a fully-featured JSON-RPC server.
114
+
115
+ For more advanced setups, check the [examples](https://github.com/wilsonsilva/jsonrpc-middleware/blob/main/examples/README.md).
116
+
182
117
  ## 📚 Documentation
183
118
 
184
119
  - [YARD documentation](https://rubydoc.info/gems/jsonrpc-middleware)
185
120
 
121
+ ## 📜 Examples
122
+
123
+ Examples for the most common Rack-based applications, including Rails and Sinatra can be found [here](https://github.com/wilsonsilva/jsonrpc-middleware/blob/main/examples/README.md)
124
+
186
125
  ## 🔨 Development
187
126
 
188
127
  After checking out the repo, run `bin/setup` to install dependencies.
@@ -200,7 +139,7 @@ Rake tasks to test, lint and audit the gem for security vulnerabilities and docu
200
139
 
201
140
  ```
202
141
  rake build # Build jsonrpc-middleware.gem into the pkg directory
203
- rake build:checksum # Generate SHA512 checksum if jsonrpc-middleware.gem into the checksums directory
142
+ rake build:checksum # Generate SHA512 checksum of jsonrpc-middleware.gem into the checksums directory
204
143
  rake bundle:audit:check # Checks the Gemfile.lock for insecure dependencies
205
144
  rake bundle:audit:update # Updates the bundler-audit vulnerability database
206
145
  rake clean # Remove any temporary products
@@ -209,18 +148,19 @@ rake coverage # Run spec with coverage
209
148
  rake install # Build and install jsonrpc-middleware.gem into system gems
210
149
  rake install:local # Build and install jsonrpc-middleware.gem into system gems without network access
211
150
  rake qa # Test, lint and perform security and documentation audits
212
- rake release[remote] # Create a tag, build and push jsonrpc-middleware.gem to rubygems.org
151
+ rake release[remote] # Create tag v0.1.0 and build and push jsonrpc-middleware-0.1.0.gem to rubygems.org
213
152
  rake rubocop # Run RuboCop
214
153
  rake rubocop:autocorrect # Autocorrect RuboCop offenses (only when it's safe)
215
154
  rake rubocop:autocorrect_all # Autocorrect RuboCop offenses (safe and unsafe)
216
155
  rake spec # Run RSpec code examples
217
156
  rake verify_measurements # Verify that yardstick coverage is at least 100%
218
157
  rake yard # Generate YARD Documentation
158
+ rake yard:format # Format YARD documentation
219
159
  rake yard:junk # Check the junk in your YARD Documentation
220
160
  rake yardstick_measure # Measure docs in lib/**/*.rb with yardstick
221
161
  ```
222
162
 
223
- ### Type checking
163
+ ### 🧪 Type checking
224
164
 
225
165
  This gem leverages [RBS](https://github.com/ruby/rbs), a language to describe the structure of Ruby programs. It is
226
166
  used to provide type checking and autocompletion in your editor. Run `bundle exec typeprof FILENAME` to generate
data/Rakefile CHANGED
@@ -20,7 +20,7 @@ end
20
20
  YARD::Rake::YardocTask.new
21
21
  YardJunk::Rake.define_task
22
22
  Yardstick::Rake::Measurement.new(:yardstick_measure, yardstick_options)
23
- Yardstick::Rake::Verify.new
23
+ Yardstick::Rake::Verify.new(:verify_measurements, yardstick_options)
24
24
 
25
25
  task default: %i[spec rubocop]
26
26
 
@@ -39,3 +39,61 @@ end
39
39
 
40
40
  desc 'Test, lint and perform security and documentation audits'
41
41
  task qa: %w[spec rubocop yard:junk verify_measurements bundle:audit]
42
+
43
+ namespace :yard do
44
+ desc 'Format YARD documentation'
45
+ task :format do
46
+ require 'fileutils'
47
+
48
+ ruby_files = Dir.glob(File.join(Dir.pwd, 'lib', '**', '*.rb'))
49
+
50
+ puts "Found #{ruby_files.length} Ruby files in lib directory"
51
+ puts
52
+
53
+ ruby_files.each do |file_path|
54
+ puts "Processing #{file_path}..."
55
+
56
+ content = File.read(file_path)
57
+ lines = content.split("\n")
58
+ result = []
59
+
60
+ lines.each_with_index do |line, index|
61
+ result << line
62
+
63
+ current_is_yard = line.strip.match?(/^\s*#\s*@\w+/)
64
+ next_line_exists = index + 1 < lines.length
65
+
66
+ # Process YARD tag spacing
67
+ next unless current_is_yard && next_line_exists
68
+
69
+ next_line = lines[index + 1]
70
+
71
+ next unless next_line.strip.match?(/^\s*#\s*@\w+/)
72
+
73
+ current_tag = line.strip.match(/^\s*#\s*@(\w+)/)[1]
74
+ next_tag = next_line.strip.match(/^\s*#\s*@(\w+)/)[1]
75
+
76
+ groupable = %w[param option]
77
+ should_group = groupable.include?(current_tag) && groupable.include?(next_tag)
78
+
79
+ # Add blank line between different tag types
80
+ unless should_group
81
+ indentation = line.match(/^(\s*)/)[1]
82
+ result << "#{indentation}#"
83
+ end
84
+ end
85
+
86
+ formatted_content = "#{result.join("\n")}\n"
87
+
88
+ if content == formatted_content
89
+ puts ' - No changes needed'
90
+ else
91
+ File.write(file_path, formatted_content)
92
+ puts ' ✓ Updated'
93
+ end
94
+ end
95
+
96
+ puts
97
+ puts 'Done!'
98
+ end
99
+ end
@@ -0,0 +1,37 @@
1
+ # Examples
2
+
3
+ This directory contains example implementations of JSON-RPC servers using the jsonrpc-middleware gem with different Ruby web frameworks.
4
+
5
+ ## Examples
6
+
7
+ - [**rack-echo**](./rack-echo/) - Echo server using Rack with helpers
8
+ - [**rack-single-file**](./rack-single-file/) - Minimal single-file example with bundler/inline
9
+ - [**rack**](./rack/) - Calculator server using pure Rack
10
+ - [**rails**](./rails-single-file/) - Calculator server using Rails
11
+ - [**rails-single-file**](./rails-single-file/) - Echo server using Rails with bundler/inline
12
+ - [**sinatra-classic**](./sinatra-classic/) - Calculator server using classic Sinatra
13
+ - [**sinatra-modular**](./sinatra-modular/) - Calculator server using modular Sinatra
14
+
15
+ ## Common Procedures
16
+
17
+ Most examples implement a calculator API with these procedures:
18
+
19
+ - `add` - Add numbers (supports both positional and named arguments)
20
+ - `subtract` - Subtract two numbers
21
+ - `multiply` - Multiply two numbers
22
+ - `divide` - Divide two numbers
23
+ - `explode` - Test procedure that throws an error
24
+
25
+ The echo examples implement:
26
+
27
+ - `echo` - Returns the input message
28
+
29
+ ## Running Examples
30
+
31
+ Each example directory contains its own README with specific instructions. Generally:
32
+
33
+ ```sh
34
+ cd <example-directory>
35
+ bundle install # if Gemfile present
36
+ bundle exec rackup # or ruby app.rb for Sinatra classic
37
+ ```
@@ -1,6 +1,11 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- JSONRPC.configure do
3
+ JSONRPC.configure do |config|
4
+ config.log_internal_errors = true # Log internal error backtraces (default: true)
5
+ config.log_request_validation_errors = true # Log JSON-RPC request validation errors (default: false)
6
+ config.render_internal_errors = true # Render detailed internal error information in responses (default: true)
7
+ config.rescue_internal_errors = true # Handle and serialize internal errors (default: true)
8
+
4
9
  # Allow positional and named arguments
5
10
  procedure(:add, allow_positional_arguments: true) do
6
11
  params do
@@ -1,7 +1,32 @@
1
- # Rack
1
+ # Rack Calculator
2
+
3
+ A JSON-RPC calculator server using pure Rack with JSONRPC helpers.
2
4
 
3
5
  ## Running
4
6
 
5
7
  ```sh
8
+ bundle install
6
9
  bundle exec rackup
7
10
  ```
11
+
12
+ ## API
13
+
14
+ The server implements a calculator with these procedures:
15
+
16
+ - `add` - Add numbers (supports both positional and named arguments)
17
+ - `subtract` - Subtract two numbers
18
+ - `multiply` - Multiply two numbers
19
+ - `divide` - Divide two numbers
20
+ - `explode` - Test procedure that throws an error
21
+
22
+ ## Example Requests
23
+
24
+ ```sh
25
+ curl -X POST http://localhost:9292 \
26
+ -H "Content-Type: application/json" \
27
+ -d '{"jsonrpc": "2.0", "method": "add", "params": {"addends": [1, 2, 3]}, "id": 1}'
28
+
29
+ curl -X POST http://localhost:9292 \
30
+ -H "Content-Type: application/json" \
31
+ -d '{"jsonrpc": "2.0", "method": "divide", "params": {"dividend": 20, "divisor": 4}, "id": 4}'
32
+ ```
data/examples/rack/app.rb CHANGED
@@ -26,7 +26,7 @@ class App
26
26
 
27
27
  case request_or_notification.method
28
28
  when 'add'
29
- addends = params.is_a?(Array) ? params : { addends: params } # Handle positional and named arguments
29
+ addends = params.is_a?(Array) ? params : params['addends'] # Handle positional and named arguments
30
30
  addends.sum
31
31
  when 'subtract'
32
32
  params['minuend'] - params['subtrahend']
@@ -1,7 +1,29 @@
1
- # Rack
1
+ # Rack Echo Server
2
+
3
+ A simple JSON-RPC echo server using Rack with JSONRPC helpers.
2
4
 
3
5
  ## Running
4
6
 
5
7
  ```sh
8
+ bundle install
6
9
  bundle exec rackup
7
10
  ```
11
+
12
+ ## API
13
+
14
+ The server implements a single procedure:
15
+
16
+ - `echo` - Returns the input message
17
+
18
+ ## Example Requests
19
+
20
+ ```sh
21
+ curl -X POST http://localhost:9292 \
22
+ -H "Content-Type: application/json" \
23
+ -d '{"jsonrpc": "2.0", "method": "echo", "params": {"message": "Hello, world!"}, "id": 1}'
24
+
25
+ # Notification (no response)
26
+ curl -X POST http://localhost:9292 \
27
+ -H "Content-Type: application/json" \
28
+ -d '{"jsonrpc": "2.0", "method": "echo", "params": {"message": "Hello, world!"}}'
29
+ ```
@@ -0,0 +1,37 @@
1
+ # Rack Single File Echo Server
2
+
3
+ A minimal single-file JSON-RPC echo server using bundler/inline for dependencies.
4
+
5
+ ## Running
6
+
7
+ ```sh
8
+ rackup
9
+ ```
10
+
11
+ ## API
12
+
13
+ The server implements a single procedure:
14
+
15
+ - `echo` - Returns the input message
16
+
17
+ ## Features
18
+
19
+ - Uses `bundler/inline` to define dependencies inline
20
+ - Self-contained in a single `config.ru` file
21
+ - Supports single requests, notifications, and batch requests
22
+
23
+ ## Example Requests
24
+
25
+ ```sh
26
+ curl -X POST http://localhost:9292 \
27
+ -H "Content-Type: application/json" \
28
+ -d '{"jsonrpc": "2.0", "method": "echo", "params": {"message": "Hello!"}, "id": 1}'
29
+
30
+ # Batch request
31
+ curl -X POST http://localhost:9292 \
32
+ -H "Content-Type: application/json" \
33
+ -d '[
34
+ {"jsonrpc": "2.0", "method": "echo", "params": {"message": "ping"}, "id": 1},
35
+ {"jsonrpc": "2.0", "method": "echo", "params": {"message": "pong"}}
36
+ ]'
37
+ ```