clamo 0.12.0 → 1.0.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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 7596405122290bf9bce3c04760bbb5e03eef24f8e5e6b3c6e99105c8faa7d14e
4
- data.tar.gz: 219e2f1f54ffd99c03dcde0c18508d24625904daa2aa65f5c7c1aabbfacee11c
3
+ metadata.gz: fb802891a70c42e2bb89446fd258fc7e9114ff29f64c4cc6051f819332172307
4
+ data.tar.gz: 10af0f3deb9d61fd068ebd9a1c6bdbc9f93aca02b8491b8c1856032338c5a56d
5
5
  SHA512:
6
- metadata.gz: 7d6a2c1407df2fc1427a7c95500d07f4873660c2322bcd4ae1a4f642550e89d6a723e7854f2126404f985446432a8e59e2690873d28ff25b218e1f01e260898a
7
- data.tar.gz: eb941c6f05333536695f9f3d6531de593b592653b17c6fb5a10e18c5cca693c6cb2fe3e922a25f17c5a1bf3d90fae8b518674b14fc78b7b2926deff1f3d7223b
6
+ metadata.gz: bdbb35a70e40adad88ef1c19b0247e11512d6d51a50fcba039cb74699e60ad7088b42f0ca8d7297c19d5e075100602c5ee79d1dc28f0604a6f0160c440a0db6f
7
+ data.tar.gz: b8a2d1c0002003468c4d4e3bbc03348d36b56e9ed13396c07653640c00cd3e924a6df45a3951a1d8c5a235bd189fd38d66418cf405f2786db3338570e8bf790a
data/README.md CHANGED
@@ -1,7 +1,47 @@
1
1
  # Clamo
2
2
 
3
- A Ruby implementation of [JSON-RPC 2.0](https://www.jsonrpc.org/specification) designed for simplicity and compliance with the specification.
3
+ [![CI](https://github.com/rubakas/clamo/actions/workflows/main.yml/badge.svg)](https://github.com/rubakas/clamo/actions/workflows/main.yml)
4
+ [![Gem Version](https://badge.fury.io/rb/clamo.svg)](https://badge.fury.io/rb/clamo)
5
+ [![Ruby](https://img.shields.io/badge/ruby-%3E%3D%203.3-ruby.svg)](https://www.ruby-lang.org)
6
+ [![License: MIT](https://img.shields.io/badge/license-MIT-blue.svg)](https://opensource.org/licenses/MIT)
7
+ [![JSON-RPC 2.0](https://img.shields.io/badge/JSON--RPC-2.0-orange.svg)](https://www.jsonrpc.org/specification)
8
+
9
+ A Ruby implementation of [JSON-RPC 2.0](https://www.jsonrpc.org/specification) designed for simplicity and compliance with the specification. Expose any Ruby module or class as a JSON-RPC service with minimal effort — just point Clamo at your object and its public methods become callable.
10
+
11
+ JSON-RPC 2.0 is the transport protocol behind [MCP](https://modelcontextprotocol.io/) and [LSP](https://microsoft.github.io/language-server-protocol/) — Clamo makes it easy to build spec-compliant services in Ruby.
12
+
13
+ ## Table of Contents
14
+
15
+ - [Installation](#installation)
16
+ - [Usage](#usage)
17
+ - [Basic Usage](#basic-usage)
18
+ - [Batch Requests](#batch-requests)
19
+ - [Notifications](#notifications)
20
+ - [Error Handling](#error-handling)
21
+ - [Configuration](#configuration)
22
+ - [Error Callback](#error-callback)
23
+ - [Per-Call Configuration](#per-call-configuration)
24
+ - [Advanced Features](#advanced-features)
25
+ - [Parallel Processing](#parallel-processing)
26
+ - [Building JSON-RPC Requests](#building-json-rpc-requests)
27
+ - [Roadmap](#roadmap)
28
+ - [Development](#development)
29
+ - [Contributing](#contributing)
30
+ - [License](#license)
31
+
32
+ ## Installation
33
+
34
+ Add to your Gemfile:
4
35
 
36
+ ```ruby
37
+ gem "clamo"
38
+ ```
39
+
40
+ Or install directly:
41
+
42
+ ```
43
+ gem install clamo
44
+ ```
5
45
 
6
46
  ## Usage
7
47
 
@@ -54,17 +94,7 @@ response = Clamo::Server.dispatch(
54
94
 
55
95
  The longer names `parsed_dispatch_to_object`, `unparsed_dispatch_to_object`, and `handle` still work as deprecated aliases.
56
96
 
57
- ### Handling Different Parameter Types
58
-
59
- Clamo supports both positional (array) and named (object/hash) parameters:
60
-
61
- ```ruby
62
- # Positional parameters
63
- request = '{"jsonrpc": "2.0", "method": "add", "params": [1, 2], "id": 1}'
64
-
65
- # Named parameters
66
- request = '{"jsonrpc": "2.0", "method": "subtract", "params": {"a": 5, "b": 3}, "id": 2}'
67
- ```
97
+ Both positional (`[1, 2]`) and named (`{"a": 5, "b": 3}`) parameters are supported — they map to positional and keyword arguments on the Ruby method respectively.
68
98
 
69
99
  ### Batch Requests
70
100
 
@@ -102,21 +132,6 @@ puts response
102
132
  # => nil
103
133
  ```
104
134
 
105
- ### Building JSON-RPC Requests
106
-
107
- Clamo provides utilities for building JSON-RPC requests:
108
-
109
- ```ruby
110
- request = Clamo::JSONRPC.build_request(
111
- method: "add",
112
- params: [1, 2],
113
- id: 1
114
- )
115
-
116
- puts request
117
- # => {"jsonrpc" => "2.0", "method" => "add", "params" => [1, 2], "id" => 1}
118
- ```
119
-
120
135
  ## Error Handling
121
136
 
122
137
  Clamo follows the JSON-RPC 2.0 specification for error handling:
@@ -172,6 +187,38 @@ Clamo::Server.dispatch(
172
187
  )
173
188
  ```
174
189
 
190
+ ### Building JSON-RPC Requests
191
+
192
+ Clamo provides utilities for building JSON-RPC requests:
193
+
194
+ ```ruby
195
+ request = Clamo::JSONRPC.build_request(
196
+ method: "add",
197
+ params: [1, 2],
198
+ id: 1
199
+ )
200
+
201
+ puts request
202
+ # => {"jsonrpc" => "2.0", "method" => "add", "params" => [1, 2], "id" => 1}
203
+ ```
204
+
205
+ ## Roadmap
206
+
207
+ - [x] Per-call configuration
208
+ - [ ] Method metadata caching
209
+ - [ ] Method allowlists/denylists
210
+ - [ ] Observability and logging
211
+ - [ ] Profiling
212
+ - [ ] Hooks
213
+ - [ ] Rack helpers and framework helpers (Rails)
214
+ - [ ] Autodoc (Markdown?)
215
+ - [ ] Error data builder
216
+ - [ ] Schemas
217
+ - [ ] Method auto-prefixing (namespace to prefix)
218
+ - [ ] Multiple objects (namespace fusion)
219
+ - [ ] Context injection
220
+ - [ ] More examples
221
+
175
222
  ## Development
176
223
 
177
224
  After checking out the repo, run `bin/setup` to install dependencies. Then, run `rake test` to run the tests. You can also run `bin/console` for an interactive prompt that will allow you to experiment.
data/lib/clamo/jsonrpc.rb CHANGED
@@ -1,8 +1,11 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Clamo
4
+ # Utilities for building and validating JSON-RPC 2.0 messages.
4
5
  module JSONRPC
6
+ # Standard JSON-RPC 2.0 error codes and messages.
5
7
  module ProtocolErrors
8
+ # Immutable descriptor pairing an error code with its message.
6
9
  ErrorDescriptor = Data.define(:code, :message)
7
10
 
8
11
  PARSE_ERROR = ErrorDescriptor.new(code: -32_700, message: "Parse error")
@@ -14,6 +17,13 @@ module Clamo
14
17
  end
15
18
 
16
19
  class << self
20
+ # Builds a JSON-RPC 2.0 request Hash.
21
+ #
22
+ # Clamo::JSONRPC.build_request(method: "add", params: [1, 2], id: 1)
23
+ # # => {"jsonrpc"=>"2.0", "method"=>"add", "params"=>[1, 2], "id"=>1}
24
+ #
25
+ # +method+ is required. +params+ (Array or Hash) and +id+ are optional.
26
+ # Omitting +id+ produces a notification.
17
27
  def build_request(**opts)
18
28
  raise ArgumentError, "method is required" unless opts.key?(:method)
19
29
 
@@ -24,10 +34,13 @@ module Clamo
24
34
  .then { |r| opts.key?(:id) ? r.merge("id" => opts[:id]) : r }
25
35
  end
26
36
 
37
+ # Builds a successful JSON-RPC 2.0 response Hash.
27
38
  def build_result_response(id:, result:)
28
39
  { "jsonrpc" => "2.0", "result" => result, "id" => id }
29
40
  end
30
41
 
42
+ # Builds a JSON-RPC 2.0 error response Hash.
43
+ # Requires +error:+ with +:code+ and +:message+ keys. +:data+ is optional.
31
44
  def build_error_response(**opts)
32
45
  raise ArgumentError, "error code is required" unless opts.dig(:error, :code)
33
46
  raise ArgumentError, "error message is required" unless opts.dig(:error, :message)
@@ -41,6 +54,7 @@ module Clamo
41
54
  }.reject { |k, _| k == "data" && !opts[:error].key?(:data) } }
42
55
  end
43
56
 
57
+ # Builds a JSON-RPC 2.0 error response from an ErrorDescriptor.
44
58
  def build_error_response_from(descriptor:, id: nil)
45
59
  build_error_response(
46
60
  id: id,
@@ -51,6 +65,7 @@ module Clamo
51
65
  )
52
66
  end
53
67
 
68
+ # Convenience method for a parse error (-32700) response.
54
69
  def build_error_response_parse_error
55
70
  build_error_response(
56
71
  id: nil,
data/lib/clamo/server.rb CHANGED
@@ -3,16 +3,35 @@
3
3
  require "json"
4
4
 
5
5
  module Clamo
6
+ # JSON-RPC 2.0 request dispatcher. All public methods on the target +object+
7
+ # become callable JSON-RPC methods.
8
+ #
9
+ # Three entry points, from highest to lowest level:
10
+ # - handle_json — JSON string in, JSON string out
11
+ # - dispatch_json — JSON string in, parsed Hash out
12
+ # - dispatch — parsed Hash in, parsed Hash out
13
+ #
14
+ # == Example
15
+ #
16
+ # Clamo::Server.handle_json(
17
+ # request: '{"jsonrpc":"2.0","method":"add","params":[1,2],"id":1}',
18
+ # object: MyService
19
+ # )
20
+ # # => '{"jsonrpc":"2.0","result":3,"id":1}'
6
21
  module Server
7
22
  Config = Data.define(:on_error)
8
23
 
9
24
  class << self
25
+ # Global error callback. Called with +(exception, method, params)+ whenever
26
+ # a dispatched method raises. Fires for both requests and notifications.
10
27
  attr_accessor :on_error
11
28
 
12
- # JSON string in, JSON string out. Full round-trip for HTTP/socket integrations.
29
+ # JSON string in, JSON string out. The primary entry point for HTTP/socket
30
+ # integrations. Returns +nil+ for notifications (no response expected).
13
31
  #
14
32
  # Clamo::Server.handle_json(request: body, object: MyService)
15
33
  #
34
+ # All extra keyword arguments are forwarded to #dispatch.
16
35
  def handle_json(request:, object:, **)
17
36
  response = dispatch_json(request: request, object: object, **)
18
37
  response&.to_json
@@ -20,10 +39,13 @@ module Clamo
20
39
 
21
40
  alias handle handle_json
22
41
 
23
- # JSON string in, parsed response out.
42
+ # JSON string in, parsed response Hash out. Parses the JSON and delegates
43
+ # to #dispatch. Returns a Hash (or Array of Hashes for batches), or +nil+
44
+ # for notifications.
24
45
  #
25
- # Clamo::Server.dispatch_json(request: json_string, object: MyModule)
46
+ # Clamo::Server.dispatch_json(request: json_string, object: MyService)
26
47
  #
48
+ # All extra keyword arguments are forwarded to #dispatch.
27
49
  def dispatch_json(request:, object:, **)
28
50
  raise ArgumentError, "object is required" unless object
29
51
 
@@ -38,10 +60,15 @@ module Clamo
38
60
 
39
61
  alias unparsed_dispatch_to_object dispatch_json
40
62
 
41
- # Parsed hash in, parsed response out.
63
+ # Parsed Hash (or Array) in, parsed response Hash out. Validates the
64
+ # request, resolves the method on +object+, checks parameter arity,
65
+ # and dispatches. Returns +nil+ for notifications.
42
66
  #
43
- # Clamo::Server.dispatch(request: hash_or_array, object: MyModule)
67
+ # Clamo::Server.dispatch(request: hash_or_array, object: MyService)
44
68
  #
69
+ # ==== Options
70
+ # +on_error+:: Error callback for this call, overrides the global on_error.
71
+ # Extra keyword arguments are forwarded to +Parallel.map+ for batch requests.
45
72
  def dispatch(request:, object:,
46
73
  on_error: self.on_error,
47
74
  **opts)
data/lib/clamo/version.rb CHANGED
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Clamo
4
- VERSION = "0.12.0"
4
+ VERSION = "1.0.0"
5
5
  end
data/lib/clamo.rb CHANGED
@@ -4,5 +4,10 @@ require_relative "clamo/version"
4
4
  require_relative "clamo/jsonrpc"
5
5
  require_relative "clamo/server"
6
6
 
7
+ # Clamo is a minimal, spec-compliant JSON-RPC 2.0 server for Ruby.
8
+ # Expose any module or class as a JSON-RPC service — public methods
9
+ # become callable via JSON-RPC requests.
10
+ #
11
+ # See Clamo::Server for the main entry points.
7
12
  module Clamo
8
13
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: clamo
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.12.0
4
+ version: 1.0.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Andriy Tyurnikov
@@ -9,8 +9,9 @@ bindir: exe
9
9
  cert_chain: []
10
10
  date: 1980-01-02 00:00:00.000000000 Z
11
11
  dependencies: []
12
- description: Minimal, spec-compliant JSON-RPC 2.0 server for Ruby with request validation,
13
- method dispatch, batch processing, and notification support.
12
+ description: Minimal, spec-compliant JSON-RPC 2.0 server for Ruby. Expose any module
13
+ or class as a JSON-RPC service with request validation, batch processing, and notification
14
+ support.
14
15
  email:
15
16
  - Andriy.Tyurnikov@gmail.com
16
17
  executables: []