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 +4 -4
- data/README.md +74 -27
- data/lib/clamo/jsonrpc.rb +15 -0
- data/lib/clamo/server.rb +32 -5
- data/lib/clamo/version.rb +1 -1
- data/lib/clamo.rb +5 -0
- metadata +4 -3
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: fb802891a70c42e2bb89446fd258fc7e9114ff29f64c4cc6051f819332172307
|
|
4
|
+
data.tar.gz: 10af0f3deb9d61fd068ebd9a1c6bdbc9f93aca02b8491b8c1856032338c5a56d
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: bdbb35a70e40adad88ef1c19b0247e11512d6d51a50fcba039cb74699e60ad7088b42f0ca8d7297c19d5e075100602c5ee79d1dc28f0604a6f0160c440a0db6f
|
|
7
|
+
data.tar.gz: b8a2d1c0002003468c4d4e3bbc03348d36b56e9ed13396c07653640c00cd3e924a6df45a3951a1d8c5a235bd189fd38d66418cf405f2786db3338570e8bf790a
|
data/README.md
CHANGED
|
@@ -1,7 +1,47 @@
|
|
|
1
1
|
# Clamo
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
[](https://github.com/rubakas/clamo/actions/workflows/main.yml)
|
|
4
|
+
[](https://badge.fury.io/rb/clamo)
|
|
5
|
+
[](https://www.ruby-lang.org)
|
|
6
|
+
[](https://opensource.org/licenses/MIT)
|
|
7
|
+
[](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
|
-
|
|
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.
|
|
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:
|
|
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
|
|
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:
|
|
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
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.
|
|
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
|
|
13
|
-
|
|
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: []
|