spikard 0.3.2 → 0.3.3
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/LICENSE +1 -1
- data/README.md +659 -659
- data/ext/spikard_rb/Cargo.toml +17 -17
- data/ext/spikard_rb/extconf.rb +10 -10
- data/ext/spikard_rb/src/lib.rs +6 -6
- data/lib/spikard/app.rb +386 -386
- data/lib/spikard/background.rb +27 -27
- data/lib/spikard/config.rb +396 -396
- data/lib/spikard/converters.rb +13 -13
- data/lib/spikard/handler_wrapper.rb +113 -113
- data/lib/spikard/provide.rb +214 -214
- data/lib/spikard/response.rb +173 -173
- data/lib/spikard/schema.rb +243 -243
- data/lib/spikard/sse.rb +111 -111
- data/lib/spikard/streaming_response.rb +44 -44
- data/lib/spikard/testing.rb +221 -221
- data/lib/spikard/upload_file.rb +131 -131
- data/lib/spikard/version.rb +5 -5
- data/lib/spikard/websocket.rb +59 -59
- data/lib/spikard.rb +43 -43
- data/sig/spikard.rbs +360 -360
- data/vendor/crates/spikard-core/Cargo.toml +40 -40
- data/vendor/crates/spikard-core/src/bindings/mod.rs +3 -3
- data/vendor/crates/spikard-core/src/bindings/response.rs +133 -133
- data/vendor/crates/spikard-core/src/debug.rs +63 -63
- data/vendor/crates/spikard-core/src/di/container.rs +726 -726
- data/vendor/crates/spikard-core/src/di/dependency.rs +273 -273
- data/vendor/crates/spikard-core/src/di/error.rs +118 -118
- data/vendor/crates/spikard-core/src/di/factory.rs +538 -538
- data/vendor/crates/spikard-core/src/di/graph.rs +545 -545
- data/vendor/crates/spikard-core/src/di/mod.rs +192 -192
- data/vendor/crates/spikard-core/src/di/resolved.rs +411 -411
- data/vendor/crates/spikard-core/src/di/value.rs +283 -283
- data/vendor/crates/spikard-core/src/errors.rs +39 -39
- data/vendor/crates/spikard-core/src/http.rs +153 -153
- data/vendor/crates/spikard-core/src/lib.rs +29 -29
- data/vendor/crates/spikard-core/src/lifecycle.rs +422 -422
- data/vendor/crates/spikard-core/src/parameters.rs +722 -722
- data/vendor/crates/spikard-core/src/problem.rs +310 -310
- data/vendor/crates/spikard-core/src/request_data.rs +189 -189
- data/vendor/crates/spikard-core/src/router.rs +249 -249
- data/vendor/crates/spikard-core/src/schema_registry.rs +183 -183
- data/vendor/crates/spikard-core/src/type_hints.rs +304 -304
- data/vendor/crates/spikard-core/src/validation.rs +699 -699
- data/vendor/crates/spikard-http/Cargo.toml +58 -58
- data/vendor/crates/spikard-http/src/auth.rs +247 -247
- data/vendor/crates/spikard-http/src/background.rs +249 -249
- data/vendor/crates/spikard-http/src/bindings/mod.rs +3 -3
- data/vendor/crates/spikard-http/src/bindings/response.rs +1 -1
- data/vendor/crates/spikard-http/src/body_metadata.rs +8 -8
- data/vendor/crates/spikard-http/src/cors.rs +490 -490
- data/vendor/crates/spikard-http/src/debug.rs +63 -63
- data/vendor/crates/spikard-http/src/di_handler.rs +423 -423
- data/vendor/crates/spikard-http/src/handler_response.rs +190 -190
- data/vendor/crates/spikard-http/src/handler_trait.rs +228 -228
- data/vendor/crates/spikard-http/src/handler_trait_tests.rs +284 -284
- data/vendor/crates/spikard-http/src/lib.rs +529 -529
- data/vendor/crates/spikard-http/src/lifecycle/adapter.rs +149 -149
- data/vendor/crates/spikard-http/src/lifecycle.rs +428 -428
- data/vendor/crates/spikard-http/src/middleware/mod.rs +285 -285
- data/vendor/crates/spikard-http/src/middleware/multipart.rs +86 -86
- data/vendor/crates/spikard-http/src/middleware/urlencoded.rs +147 -147
- data/vendor/crates/spikard-http/src/middleware/validation.rs +287 -287
- data/vendor/crates/spikard-http/src/openapi/mod.rs +309 -309
- data/vendor/crates/spikard-http/src/openapi/parameter_extraction.rs +190 -190
- data/vendor/crates/spikard-http/src/openapi/schema_conversion.rs +308 -308
- data/vendor/crates/spikard-http/src/openapi/spec_generation.rs +195 -195
- data/vendor/crates/spikard-http/src/parameters.rs +1 -1
- data/vendor/crates/spikard-http/src/problem.rs +1 -1
- data/vendor/crates/spikard-http/src/query_parser.rs +369 -369
- data/vendor/crates/spikard-http/src/response.rs +399 -399
- data/vendor/crates/spikard-http/src/router.rs +1 -1
- data/vendor/crates/spikard-http/src/schema_registry.rs +1 -1
- data/vendor/crates/spikard-http/src/server/handler.rs +87 -87
- data/vendor/crates/spikard-http/src/server/lifecycle_execution.rs +98 -98
- data/vendor/crates/spikard-http/src/server/mod.rs +805 -805
- data/vendor/crates/spikard-http/src/server/request_extraction.rs +119 -119
- data/vendor/crates/spikard-http/src/sse.rs +447 -447
- data/vendor/crates/spikard-http/src/testing/form.rs +14 -14
- data/vendor/crates/spikard-http/src/testing/multipart.rs +60 -60
- data/vendor/crates/spikard-http/src/testing/test_client.rs +285 -285
- data/vendor/crates/spikard-http/src/testing.rs +377 -377
- data/vendor/crates/spikard-http/src/type_hints.rs +1 -1
- data/vendor/crates/spikard-http/src/validation.rs +1 -1
- data/vendor/crates/spikard-http/src/websocket.rs +324 -324
- data/vendor/crates/spikard-rb/Cargo.toml +42 -42
- data/vendor/crates/spikard-rb/build.rs +8 -8
- data/vendor/crates/spikard-rb/src/background.rs +63 -63
- data/vendor/crates/spikard-rb/src/config.rs +294 -294
- data/vendor/crates/spikard-rb/src/conversion.rs +453 -453
- data/vendor/crates/spikard-rb/src/di.rs +409 -409
- data/vendor/crates/spikard-rb/src/handler.rs +625 -625
- data/vendor/crates/spikard-rb/src/lib.rs +2771 -2771
- data/vendor/crates/spikard-rb/src/lifecycle.rs +274 -274
- data/vendor/crates/spikard-rb/src/server.rs +283 -283
- data/vendor/crates/spikard-rb/src/sse.rs +231 -231
- data/vendor/crates/spikard-rb/src/test_client.rs +404 -404
- data/vendor/crates/spikard-rb/src/test_sse.rs +143 -143
- data/vendor/crates/spikard-rb/src/test_websocket.rs +221 -221
- data/vendor/crates/spikard-rb/src/websocket.rs +233 -233
- data/vendor/spikard-core/Cargo.toml +40 -40
- data/vendor/spikard-core/src/bindings/mod.rs +3 -3
- data/vendor/spikard-core/src/bindings/response.rs +133 -133
- data/vendor/spikard-core/src/debug.rs +63 -63
- data/vendor/spikard-core/src/di/container.rs +726 -726
- data/vendor/spikard-core/src/di/dependency.rs +273 -273
- data/vendor/spikard-core/src/di/error.rs +118 -118
- data/vendor/spikard-core/src/di/factory.rs +538 -538
- data/vendor/spikard-core/src/di/graph.rs +545 -545
- data/vendor/spikard-core/src/di/mod.rs +192 -192
- data/vendor/spikard-core/src/di/resolved.rs +411 -411
- data/vendor/spikard-core/src/di/value.rs +283 -283
- data/vendor/spikard-core/src/http.rs +153 -153
- data/vendor/spikard-core/src/lib.rs +28 -28
- data/vendor/spikard-core/src/lifecycle.rs +422 -422
- data/vendor/spikard-core/src/parameters.rs +719 -719
- data/vendor/spikard-core/src/problem.rs +310 -310
- data/vendor/spikard-core/src/request_data.rs +189 -189
- data/vendor/spikard-core/src/router.rs +249 -249
- data/vendor/spikard-core/src/schema_registry.rs +183 -183
- data/vendor/spikard-core/src/type_hints.rs +304 -304
- data/vendor/spikard-core/src/validation.rs +699 -699
- data/vendor/spikard-http/Cargo.toml +58 -58
- data/vendor/spikard-http/src/auth.rs +247 -247
- data/vendor/spikard-http/src/background.rs +249 -249
- data/vendor/spikard-http/src/bindings/mod.rs +3 -3
- data/vendor/spikard-http/src/bindings/response.rs +1 -1
- data/vendor/spikard-http/src/body_metadata.rs +8 -8
- data/vendor/spikard-http/src/cors.rs +490 -490
- data/vendor/spikard-http/src/debug.rs +63 -63
- data/vendor/spikard-http/src/di_handler.rs +423 -423
- data/vendor/spikard-http/src/handler_response.rs +190 -190
- data/vendor/spikard-http/src/handler_trait.rs +228 -228
- data/vendor/spikard-http/src/handler_trait_tests.rs +284 -284
- data/vendor/spikard-http/src/lib.rs +529 -529
- data/vendor/spikard-http/src/lifecycle/adapter.rs +149 -149
- data/vendor/spikard-http/src/lifecycle.rs +428 -428
- data/vendor/spikard-http/src/middleware/mod.rs +285 -285
- data/vendor/spikard-http/src/middleware/multipart.rs +86 -86
- data/vendor/spikard-http/src/middleware/urlencoded.rs +147 -147
- data/vendor/spikard-http/src/middleware/validation.rs +287 -287
- data/vendor/spikard-http/src/openapi/mod.rs +309 -309
- data/vendor/spikard-http/src/openapi/parameter_extraction.rs +190 -190
- data/vendor/spikard-http/src/openapi/schema_conversion.rs +308 -308
- data/vendor/spikard-http/src/openapi/spec_generation.rs +195 -195
- data/vendor/spikard-http/src/parameters.rs +1 -1
- data/vendor/spikard-http/src/problem.rs +1 -1
- data/vendor/spikard-http/src/query_parser.rs +369 -369
- data/vendor/spikard-http/src/response.rs +399 -399
- data/vendor/spikard-http/src/router.rs +1 -1
- data/vendor/spikard-http/src/schema_registry.rs +1 -1
- data/vendor/spikard-http/src/server/handler.rs +80 -80
- data/vendor/spikard-http/src/server/lifecycle_execution.rs +98 -98
- data/vendor/spikard-http/src/server/mod.rs +805 -805
- data/vendor/spikard-http/src/server/request_extraction.rs +119 -119
- data/vendor/spikard-http/src/sse.rs +447 -447
- data/vendor/spikard-http/src/testing/form.rs +14 -14
- data/vendor/spikard-http/src/testing/multipart.rs +60 -60
- data/vendor/spikard-http/src/testing/test_client.rs +285 -285
- data/vendor/spikard-http/src/testing.rs +377 -377
- data/vendor/spikard-http/src/type_hints.rs +1 -1
- data/vendor/spikard-http/src/validation.rs +1 -1
- data/vendor/spikard-http/src/websocket.rs +324 -324
- data/vendor/spikard-rb/Cargo.toml +42 -42
- data/vendor/spikard-rb/build.rs +8 -8
- data/vendor/spikard-rb/src/background.rs +63 -63
- data/vendor/spikard-rb/src/config.rs +294 -294
- data/vendor/spikard-rb/src/conversion.rs +392 -392
- data/vendor/spikard-rb/src/di.rs +409 -409
- data/vendor/spikard-rb/src/handler.rs +534 -534
- data/vendor/spikard-rb/src/lib.rs +2020 -2020
- data/vendor/spikard-rb/src/lifecycle.rs +267 -267
- data/vendor/spikard-rb/src/server.rs +283 -283
- data/vendor/spikard-rb/src/sse.rs +231 -231
- data/vendor/spikard-rb/src/test_client.rs +404 -404
- data/vendor/spikard-rb/src/test_sse.rs +143 -143
- data/vendor/spikard-rb/src/test_websocket.rs +221 -221
- data/vendor/spikard-rb/src/websocket.rs +233 -233
- metadata +1 -1
|
@@ -1,143 +1,143 @@
|
|
|
1
|
-
//! SSE test client bindings for Ruby
|
|
2
|
-
|
|
3
|
-
use magnus::prelude::*;
|
|
4
|
-
use magnus::{Error, Ruby, Value, method};
|
|
5
|
-
use serde_json::Value as JsonValue;
|
|
6
|
-
use spikard_http::testing::{ResponseSnapshot, SseEvent as RustSseEvent, SseStream as RustSseStream};
|
|
7
|
-
|
|
8
|
-
/// Ruby wrapper for SSE stream
|
|
9
|
-
#[magnus::wrap(class = "Spikard::Native::SseStream", free_immediately)]
|
|
10
|
-
pub struct SseStream {
|
|
11
|
-
inner: RustSseStream,
|
|
12
|
-
}
|
|
13
|
-
|
|
14
|
-
impl SseStream {
|
|
15
|
-
pub fn new(inner: RustSseStream) -> Self {
|
|
16
|
-
Self { inner }
|
|
17
|
-
}
|
|
18
|
-
|
|
19
|
-
/// Get the raw body of the SSE response
|
|
20
|
-
fn body(&self) -> String {
|
|
21
|
-
self.inner.body().to_string()
|
|
22
|
-
}
|
|
23
|
-
|
|
24
|
-
/// Get all events from the stream
|
|
25
|
-
fn events(ruby: &Ruby, this: &Self) -> Result<Value, Error> {
|
|
26
|
-
let ruby_arr = ruby.ary_new();
|
|
27
|
-
for event in this.inner.events() {
|
|
28
|
-
let sse_event = SseEvent::new(event.clone());
|
|
29
|
-
let ruby_event = ruby.obj_wrap(sse_event);
|
|
30
|
-
ruby_arr.push(ruby_event)?;
|
|
31
|
-
}
|
|
32
|
-
Ok(ruby_arr.as_value())
|
|
33
|
-
}
|
|
34
|
-
|
|
35
|
-
/// Get events as JSON values
|
|
36
|
-
fn events_as_json(ruby: &Ruby, this: &Self) -> Result<Value, Error> {
|
|
37
|
-
let json_events = this.inner.events_as_json().map_err(|e| {
|
|
38
|
-
Error::new(
|
|
39
|
-
ruby.exception_runtime_error(),
|
|
40
|
-
format!("Failed to parse events as JSON: {}", e),
|
|
41
|
-
)
|
|
42
|
-
})?;
|
|
43
|
-
|
|
44
|
-
let ruby_arr = ruby.ary_new();
|
|
45
|
-
for value in json_events {
|
|
46
|
-
let ruby_val = json_to_ruby(ruby, &value)?;
|
|
47
|
-
ruby_arr.push(ruby_val)?;
|
|
48
|
-
}
|
|
49
|
-
Ok(ruby_arr.as_value())
|
|
50
|
-
}
|
|
51
|
-
}
|
|
52
|
-
|
|
53
|
-
/// Ruby wrapper for SSE event
|
|
54
|
-
#[magnus::wrap(class = "Spikard::Native::SseEvent", free_immediately)]
|
|
55
|
-
pub struct SseEvent {
|
|
56
|
-
inner: RustSseEvent,
|
|
57
|
-
}
|
|
58
|
-
|
|
59
|
-
impl SseEvent {
|
|
60
|
-
pub fn new(inner: RustSseEvent) -> Self {
|
|
61
|
-
Self { inner }
|
|
62
|
-
}
|
|
63
|
-
|
|
64
|
-
/// Get the data field of the event
|
|
65
|
-
fn data(&self) -> String {
|
|
66
|
-
self.inner.data.clone()
|
|
67
|
-
}
|
|
68
|
-
|
|
69
|
-
/// Parse the event data as JSON
|
|
70
|
-
fn as_json(ruby: &Ruby, this: &Self) -> Result<Value, Error> {
|
|
71
|
-
let value = this
|
|
72
|
-
.inner
|
|
73
|
-
.as_json()
|
|
74
|
-
.map_err(|e| Error::new(ruby.exception_runtime_error(), format!("Failed to parse JSON: {}", e)))?;
|
|
75
|
-
|
|
76
|
-
json_to_ruby(ruby, &value)
|
|
77
|
-
}
|
|
78
|
-
}
|
|
79
|
-
|
|
80
|
-
/// Create an SSE stream from a response snapshot
|
|
81
|
-
pub fn sse_stream_from_response(ruby: &Ruby, response: &ResponseSnapshot) -> Result<Value, Error> {
|
|
82
|
-
let stream = RustSseStream::from_response(response)
|
|
83
|
-
.map_err(|e| Error::new(ruby.exception_runtime_error(), format!("Failed to parse SSE: {}", e)))?;
|
|
84
|
-
|
|
85
|
-
let sse_stream = SseStream::new(stream);
|
|
86
|
-
Ok(ruby.obj_wrap(sse_stream).as_value())
|
|
87
|
-
}
|
|
88
|
-
|
|
89
|
-
/// Helper to convert JSON to Ruby object
|
|
90
|
-
fn json_to_ruby(ruby: &Ruby, value: &JsonValue) -> Result<Value, Error> {
|
|
91
|
-
match value {
|
|
92
|
-
JsonValue::Null => Ok(ruby.qnil().as_value()),
|
|
93
|
-
JsonValue::Bool(b) => Ok(if *b {
|
|
94
|
-
ruby.qtrue().as_value()
|
|
95
|
-
} else {
|
|
96
|
-
ruby.qfalse().as_value()
|
|
97
|
-
}),
|
|
98
|
-
JsonValue::Number(n) => {
|
|
99
|
-
if let Some(i) = n.as_i64() {
|
|
100
|
-
Ok(ruby.integer_from_i64(i).as_value())
|
|
101
|
-
} else if let Some(u) = n.as_u64() {
|
|
102
|
-
Ok(ruby.integer_from_i64(u as i64).as_value())
|
|
103
|
-
} else if let Some(f) = n.as_f64() {
|
|
104
|
-
Ok(ruby.float_from_f64(f).as_value())
|
|
105
|
-
} else {
|
|
106
|
-
Ok(ruby.qnil().as_value())
|
|
107
|
-
}
|
|
108
|
-
}
|
|
109
|
-
JsonValue::String(s) => Ok(ruby.str_new(s).as_value()),
|
|
110
|
-
JsonValue::Array(arr) => {
|
|
111
|
-
let ruby_arr = ruby.ary_new();
|
|
112
|
-
for item in arr {
|
|
113
|
-
let ruby_val = json_to_ruby(ruby, item)?;
|
|
114
|
-
ruby_arr.push(ruby_val)?;
|
|
115
|
-
}
|
|
116
|
-
Ok(ruby_arr.as_value())
|
|
117
|
-
}
|
|
118
|
-
JsonValue::Object(obj) => {
|
|
119
|
-
let ruby_hash = ruby.hash_new();
|
|
120
|
-
for (key, val) in obj {
|
|
121
|
-
let ruby_val = json_to_ruby(ruby, val)?;
|
|
122
|
-
ruby_hash.aset(ruby.str_new(key), ruby_val)?;
|
|
123
|
-
}
|
|
124
|
-
Ok(ruby_hash.as_value())
|
|
125
|
-
}
|
|
126
|
-
}
|
|
127
|
-
}
|
|
128
|
-
|
|
129
|
-
/// Initialize SSE test client bindings
|
|
130
|
-
pub fn init(ruby: &Ruby, module: &magnus::RModule) -> Result<(), Error> {
|
|
131
|
-
let native_module = module.define_module("Native")?;
|
|
132
|
-
|
|
133
|
-
let sse_stream_class = native_module.define_class("SseStream", ruby.class_object())?;
|
|
134
|
-
sse_stream_class.define_method("body", method!(SseStream::body, 0))?;
|
|
135
|
-
sse_stream_class.define_method("events", method!(SseStream::events, 0))?;
|
|
136
|
-
sse_stream_class.define_method("events_as_json", method!(SseStream::events_as_json, 0))?;
|
|
137
|
-
|
|
138
|
-
let sse_event_class = native_module.define_class("SseEvent", ruby.class_object())?;
|
|
139
|
-
sse_event_class.define_method("data", method!(SseEvent::data, 0))?;
|
|
140
|
-
sse_event_class.define_method("as_json", method!(SseEvent::as_json, 0))?;
|
|
141
|
-
|
|
142
|
-
Ok(())
|
|
143
|
-
}
|
|
1
|
+
//! SSE test client bindings for Ruby
|
|
2
|
+
|
|
3
|
+
use magnus::prelude::*;
|
|
4
|
+
use magnus::{Error, Ruby, Value, method};
|
|
5
|
+
use serde_json::Value as JsonValue;
|
|
6
|
+
use spikard_http::testing::{ResponseSnapshot, SseEvent as RustSseEvent, SseStream as RustSseStream};
|
|
7
|
+
|
|
8
|
+
/// Ruby wrapper for SSE stream
|
|
9
|
+
#[magnus::wrap(class = "Spikard::Native::SseStream", free_immediately)]
|
|
10
|
+
pub struct SseStream {
|
|
11
|
+
inner: RustSseStream,
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
impl SseStream {
|
|
15
|
+
pub fn new(inner: RustSseStream) -> Self {
|
|
16
|
+
Self { inner }
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
/// Get the raw body of the SSE response
|
|
20
|
+
fn body(&self) -> String {
|
|
21
|
+
self.inner.body().to_string()
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
/// Get all events from the stream
|
|
25
|
+
fn events(ruby: &Ruby, this: &Self) -> Result<Value, Error> {
|
|
26
|
+
let ruby_arr = ruby.ary_new();
|
|
27
|
+
for event in this.inner.events() {
|
|
28
|
+
let sse_event = SseEvent::new(event.clone());
|
|
29
|
+
let ruby_event = ruby.obj_wrap(sse_event);
|
|
30
|
+
ruby_arr.push(ruby_event)?;
|
|
31
|
+
}
|
|
32
|
+
Ok(ruby_arr.as_value())
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
/// Get events as JSON values
|
|
36
|
+
fn events_as_json(ruby: &Ruby, this: &Self) -> Result<Value, Error> {
|
|
37
|
+
let json_events = this.inner.events_as_json().map_err(|e| {
|
|
38
|
+
Error::new(
|
|
39
|
+
ruby.exception_runtime_error(),
|
|
40
|
+
format!("Failed to parse events as JSON: {}", e),
|
|
41
|
+
)
|
|
42
|
+
})?;
|
|
43
|
+
|
|
44
|
+
let ruby_arr = ruby.ary_new();
|
|
45
|
+
for value in json_events {
|
|
46
|
+
let ruby_val = json_to_ruby(ruby, &value)?;
|
|
47
|
+
ruby_arr.push(ruby_val)?;
|
|
48
|
+
}
|
|
49
|
+
Ok(ruby_arr.as_value())
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
/// Ruby wrapper for SSE event
|
|
54
|
+
#[magnus::wrap(class = "Spikard::Native::SseEvent", free_immediately)]
|
|
55
|
+
pub struct SseEvent {
|
|
56
|
+
inner: RustSseEvent,
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
impl SseEvent {
|
|
60
|
+
pub fn new(inner: RustSseEvent) -> Self {
|
|
61
|
+
Self { inner }
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
/// Get the data field of the event
|
|
65
|
+
fn data(&self) -> String {
|
|
66
|
+
self.inner.data.clone()
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
/// Parse the event data as JSON
|
|
70
|
+
fn as_json(ruby: &Ruby, this: &Self) -> Result<Value, Error> {
|
|
71
|
+
let value = this
|
|
72
|
+
.inner
|
|
73
|
+
.as_json()
|
|
74
|
+
.map_err(|e| Error::new(ruby.exception_runtime_error(), format!("Failed to parse JSON: {}", e)))?;
|
|
75
|
+
|
|
76
|
+
json_to_ruby(ruby, &value)
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
/// Create an SSE stream from a response snapshot
|
|
81
|
+
pub fn sse_stream_from_response(ruby: &Ruby, response: &ResponseSnapshot) -> Result<Value, Error> {
|
|
82
|
+
let stream = RustSseStream::from_response(response)
|
|
83
|
+
.map_err(|e| Error::new(ruby.exception_runtime_error(), format!("Failed to parse SSE: {}", e)))?;
|
|
84
|
+
|
|
85
|
+
let sse_stream = SseStream::new(stream);
|
|
86
|
+
Ok(ruby.obj_wrap(sse_stream).as_value())
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
/// Helper to convert JSON to Ruby object
|
|
90
|
+
fn json_to_ruby(ruby: &Ruby, value: &JsonValue) -> Result<Value, Error> {
|
|
91
|
+
match value {
|
|
92
|
+
JsonValue::Null => Ok(ruby.qnil().as_value()),
|
|
93
|
+
JsonValue::Bool(b) => Ok(if *b {
|
|
94
|
+
ruby.qtrue().as_value()
|
|
95
|
+
} else {
|
|
96
|
+
ruby.qfalse().as_value()
|
|
97
|
+
}),
|
|
98
|
+
JsonValue::Number(n) => {
|
|
99
|
+
if let Some(i) = n.as_i64() {
|
|
100
|
+
Ok(ruby.integer_from_i64(i).as_value())
|
|
101
|
+
} else if let Some(u) = n.as_u64() {
|
|
102
|
+
Ok(ruby.integer_from_i64(u as i64).as_value())
|
|
103
|
+
} else if let Some(f) = n.as_f64() {
|
|
104
|
+
Ok(ruby.float_from_f64(f).as_value())
|
|
105
|
+
} else {
|
|
106
|
+
Ok(ruby.qnil().as_value())
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
JsonValue::String(s) => Ok(ruby.str_new(s).as_value()),
|
|
110
|
+
JsonValue::Array(arr) => {
|
|
111
|
+
let ruby_arr = ruby.ary_new();
|
|
112
|
+
for item in arr {
|
|
113
|
+
let ruby_val = json_to_ruby(ruby, item)?;
|
|
114
|
+
ruby_arr.push(ruby_val)?;
|
|
115
|
+
}
|
|
116
|
+
Ok(ruby_arr.as_value())
|
|
117
|
+
}
|
|
118
|
+
JsonValue::Object(obj) => {
|
|
119
|
+
let ruby_hash = ruby.hash_new();
|
|
120
|
+
for (key, val) in obj {
|
|
121
|
+
let ruby_val = json_to_ruby(ruby, val)?;
|
|
122
|
+
ruby_hash.aset(ruby.str_new(key), ruby_val)?;
|
|
123
|
+
}
|
|
124
|
+
Ok(ruby_hash.as_value())
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
/// Initialize SSE test client bindings
|
|
130
|
+
pub fn init(ruby: &Ruby, module: &magnus::RModule) -> Result<(), Error> {
|
|
131
|
+
let native_module = module.define_module("Native")?;
|
|
132
|
+
|
|
133
|
+
let sse_stream_class = native_module.define_class("SseStream", ruby.class_object())?;
|
|
134
|
+
sse_stream_class.define_method("body", method!(SseStream::body, 0))?;
|
|
135
|
+
sse_stream_class.define_method("events", method!(SseStream::events, 0))?;
|
|
136
|
+
sse_stream_class.define_method("events_as_json", method!(SseStream::events_as_json, 0))?;
|
|
137
|
+
|
|
138
|
+
let sse_event_class = native_module.define_class("SseEvent", ruby.class_object())?;
|
|
139
|
+
sse_event_class.define_method("data", method!(SseEvent::data, 0))?;
|
|
140
|
+
sse_event_class.define_method("as_json", method!(SseEvent::as_json, 0))?;
|
|
141
|
+
|
|
142
|
+
Ok(())
|
|
143
|
+
}
|