spikard 0.5.0 → 0.6.1
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 +674 -674
- data/ext/spikard_rb/Cargo.toml +17 -17
- data/ext/spikard_rb/extconf.rb +13 -10
- data/ext/spikard_rb/src/lib.rs +6 -6
- data/lib/spikard/app.rb +405 -405
- 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 +256 -256
- 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 +366 -366
- data/vendor/crates/spikard-bindings-shared/Cargo.toml +63 -63
- data/vendor/crates/spikard-bindings-shared/examples/config_extraction.rs +132 -132
- data/vendor/crates/spikard-bindings-shared/src/config_extractor.rs +752 -752
- data/vendor/crates/spikard-bindings-shared/src/conversion_traits.rs +194 -194
- data/vendor/crates/spikard-bindings-shared/src/di_traits.rs +246 -246
- data/vendor/crates/spikard-bindings-shared/src/error_response.rs +401 -401
- data/vendor/crates/spikard-bindings-shared/src/handler_base.rs +238 -238
- data/vendor/crates/spikard-bindings-shared/src/lib.rs +24 -24
- data/vendor/crates/spikard-bindings-shared/src/lifecycle_base.rs +292 -292
- data/vendor/crates/spikard-bindings-shared/src/lifecycle_executor.rs +616 -616
- data/vendor/crates/spikard-bindings-shared/src/response_builder.rs +305 -305
- data/vendor/crates/spikard-bindings-shared/src/test_client_base.rs +248 -248
- data/vendor/crates/spikard-bindings-shared/src/validation_helpers.rs +351 -351
- data/vendor/crates/spikard-bindings-shared/tests/comprehensive_coverage.rs +454 -454
- data/vendor/crates/spikard-bindings-shared/tests/error_response_edge_cases.rs +383 -383
- data/vendor/crates/spikard-bindings-shared/tests/handler_base_integration.rs +280 -280
- 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 +127 -127
- data/vendor/crates/spikard-core/src/di/container.rs +702 -702
- 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 +534 -534
- data/vendor/crates/spikard-core/src/di/graph.rs +506 -506
- data/vendor/crates/spikard-core/src/di/mod.rs +192 -192
- data/vendor/crates/spikard-core/src/di/resolved.rs +405 -405
- data/vendor/crates/spikard-core/src/di/value.rs +281 -281
- data/vendor/crates/spikard-core/src/errors.rs +69 -69
- data/vendor/crates/spikard-core/src/http.rs +415 -415
- data/vendor/crates/spikard-core/src/lib.rs +29 -29
- data/vendor/crates/spikard-core/src/lifecycle.rs +1186 -1186
- data/vendor/crates/spikard-core/src/metadata.rs +389 -389
- data/vendor/crates/spikard-core/src/parameters.rs +2525 -2525
- data/vendor/crates/spikard-core/src/problem.rs +344 -344
- data/vendor/crates/spikard-core/src/request_data.rs +1154 -1154
- data/vendor/crates/spikard-core/src/router.rs +510 -510
- 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/error_mapper.rs +696 -688
- data/vendor/crates/spikard-core/src/validation/mod.rs +457 -457
- data/vendor/crates/spikard-http/Cargo.toml +62 -64
- data/vendor/crates/spikard-http/examples/sse-notifications.rs +148 -148
- data/vendor/crates/spikard-http/examples/websocket-chat.rs +92 -92
- data/vendor/crates/spikard-http/src/auth.rs +296 -296
- data/vendor/crates/spikard-http/src/background.rs +1860 -1860
- 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 +1005 -1005
- data/vendor/crates/spikard-http/src/debug.rs +128 -128
- data/vendor/crates/spikard-http/src/di_handler.rs +1668 -1668
- data/vendor/crates/spikard-http/src/handler_response.rs +901 -901
- data/vendor/crates/spikard-http/src/handler_trait.rs +838 -830
- data/vendor/crates/spikard-http/src/handler_trait_tests.rs +290 -290
- data/vendor/crates/spikard-http/src/lib.rs +534 -534
- data/vendor/crates/spikard-http/src/lifecycle/adapter.rs +230 -230
- data/vendor/crates/spikard-http/src/lifecycle.rs +1193 -1193
- data/vendor/crates/spikard-http/src/middleware/mod.rs +560 -540
- data/vendor/crates/spikard-http/src/middleware/multipart.rs +912 -912
- data/vendor/crates/spikard-http/src/middleware/urlencoded.rs +513 -513
- data/vendor/crates/spikard-http/src/middleware/validation.rs +768 -735
- data/vendor/crates/spikard-http/src/openapi/mod.rs +309 -309
- data/vendor/crates/spikard-http/src/openapi/parameter_extraction.rs +535 -535
- data/vendor/crates/spikard-http/src/openapi/schema_conversion.rs +1363 -1363
- data/vendor/crates/spikard-http/src/openapi/spec_generation.rs +665 -665
- data/vendor/crates/spikard-http/src/query_parser.rs +793 -793
- data/vendor/crates/spikard-http/src/response.rs +720 -720
- data/vendor/crates/spikard-http/src/server/handler.rs +1650 -1650
- data/vendor/crates/spikard-http/src/server/lifecycle_execution.rs +234 -234
- data/vendor/crates/spikard-http/src/server/mod.rs +1593 -1502
- data/vendor/crates/spikard-http/src/server/request_extraction.rs +789 -770
- data/vendor/crates/spikard-http/src/server/routing_factory.rs +629 -599
- data/vendor/crates/spikard-http/src/sse.rs +1409 -1409
- data/vendor/crates/spikard-http/src/testing/form.rs +52 -52
- data/vendor/crates/spikard-http/src/testing/multipart.rs +64 -60
- data/vendor/crates/spikard-http/src/testing/test_client.rs +311 -283
- data/vendor/crates/spikard-http/src/testing.rs +406 -377
- data/vendor/crates/spikard-http/src/websocket.rs +1404 -1375
- data/vendor/crates/spikard-http/tests/background_behavior.rs +832 -832
- data/vendor/crates/spikard-http/tests/common/handlers.rs +309 -309
- data/vendor/crates/spikard-http/tests/common/mod.rs +26 -26
- data/vendor/crates/spikard-http/tests/di_integration.rs +192 -192
- data/vendor/crates/spikard-http/tests/doc_snippets.rs +5 -5
- data/vendor/crates/spikard-http/tests/lifecycle_execution.rs +1093 -1093
- data/vendor/crates/spikard-http/tests/multipart_behavior.rs +656 -656
- data/vendor/crates/spikard-http/tests/server_config_builder.rs +314 -314
- data/vendor/crates/spikard-http/tests/sse_behavior.rs +620 -620
- data/vendor/crates/spikard-http/tests/websocket_behavior.rs +663 -663
- data/vendor/crates/spikard-rb/Cargo.toml +48 -48
- data/vendor/crates/spikard-rb/build.rs +199 -199
- data/vendor/crates/spikard-rb/src/background.rs +63 -63
- data/vendor/crates/spikard-rb/src/config/mod.rs +5 -5
- data/vendor/crates/spikard-rb/src/config/server_config.rs +285 -285
- data/vendor/crates/spikard-rb/src/conversion.rs +554 -554
- data/vendor/crates/spikard-rb/src/di/builder.rs +100 -100
- data/vendor/crates/spikard-rb/src/di/mod.rs +375 -375
- data/vendor/crates/spikard-rb/src/handler.rs +618 -618
- data/vendor/crates/spikard-rb/src/integration/mod.rs +3 -3
- data/vendor/crates/spikard-rb/src/lib.rs +1806 -1810
- data/vendor/crates/spikard-rb/src/lifecycle.rs +275 -275
- data/vendor/crates/spikard-rb/src/metadata/mod.rs +5 -5
- data/vendor/crates/spikard-rb/src/metadata/route_extraction.rs +442 -447
- data/vendor/crates/spikard-rb/src/runtime/mod.rs +5 -5
- data/vendor/crates/spikard-rb/src/runtime/server_runner.rs +324 -324
- data/vendor/crates/spikard-rb/src/server.rs +305 -308
- data/vendor/crates/spikard-rb/src/sse.rs +231 -231
- data/vendor/crates/spikard-rb/src/testing/client.rs +538 -551
- data/vendor/crates/spikard-rb/src/testing/mod.rs +7 -7
- data/vendor/crates/spikard-rb/src/testing/sse.rs +143 -143
- data/vendor/crates/spikard-rb/src/testing/websocket.rs +608 -635
- data/vendor/crates/spikard-rb/src/websocket.rs +377 -374
- metadata +15 -1
|
@@ -1,69 +1,69 @@
|
|
|
1
|
-
//! Shared structured error types and panic shielding utilities.
|
|
2
|
-
//!
|
|
3
|
-
//! Bindings should convert all fatal paths into this shape to keep cross-language
|
|
4
|
-
//! error payloads consistent and avoid panics crossing FFI boundaries.
|
|
5
|
-
|
|
6
|
-
use serde::Serialize;
|
|
7
|
-
use serde_json::Value;
|
|
8
|
-
use std::panic::{UnwindSafe, catch_unwind};
|
|
9
|
-
|
|
10
|
-
/// Canonical error payload: { error, code, details }.
|
|
11
|
-
#[derive(Debug, Clone, Serialize)]
|
|
12
|
-
pub struct StructuredError {
|
|
13
|
-
pub error: String,
|
|
14
|
-
pub code: String,
|
|
15
|
-
#[serde(default)]
|
|
16
|
-
pub details: Value,
|
|
17
|
-
}
|
|
18
|
-
|
|
19
|
-
impl StructuredError {
|
|
20
|
-
pub fn new(code: impl Into<String>, error: impl Into<String>, details: Value) -> Self {
|
|
21
|
-
Self {
|
|
22
|
-
code: code.into(),
|
|
23
|
-
error: error.into(),
|
|
24
|
-
details,
|
|
25
|
-
}
|
|
26
|
-
}
|
|
27
|
-
|
|
28
|
-
pub fn simple(code: impl Into<String>, error: impl Into<String>) -> Self {
|
|
29
|
-
Self::new(code, error, Value::Object(serde_json::Map::new()))
|
|
30
|
-
}
|
|
31
|
-
}
|
|
32
|
-
|
|
33
|
-
/// Catch panics and convert to a structured error so they don't cross FFI boundaries.
|
|
34
|
-
pub fn shield_panic<T, F>(f: F) -> Result<T, StructuredError>
|
|
35
|
-
where
|
|
36
|
-
F: FnOnce() -> T + UnwindSafe,
|
|
37
|
-
{
|
|
38
|
-
catch_unwind(f).map_err(|_| StructuredError::simple("panic", "Unexpected panic in Rust code"))
|
|
39
|
-
}
|
|
40
|
-
|
|
41
|
-
#[cfg(test)]
|
|
42
|
-
mod tests {
|
|
43
|
-
use super::*;
|
|
44
|
-
use serde_json::json;
|
|
45
|
-
|
|
46
|
-
#[test]
|
|
47
|
-
fn structured_error_constructors_populate_fields() {
|
|
48
|
-
let details = json!({"field": "name"});
|
|
49
|
-
let err = StructuredError::new("invalid", "bad input", details.clone());
|
|
50
|
-
assert_eq!(err.code, "invalid");
|
|
51
|
-
assert_eq!(err.error, "bad input");
|
|
52
|
-
assert_eq!(err.details, details);
|
|
53
|
-
|
|
54
|
-
let simple = StructuredError::simple("missing", "not found");
|
|
55
|
-
assert_eq!(simple.code, "missing");
|
|
56
|
-
assert_eq!(simple.error, "not found");
|
|
57
|
-
assert!(simple.details.is_object());
|
|
58
|
-
}
|
|
59
|
-
|
|
60
|
-
#[test]
|
|
61
|
-
fn shield_panic_returns_ok_or_structured_error() {
|
|
62
|
-
let ok = shield_panic(|| 42);
|
|
63
|
-
assert_eq!(ok.unwrap(), 42);
|
|
64
|
-
|
|
65
|
-
let err = shield_panic(|| panic!("boom")).unwrap_err();
|
|
66
|
-
assert_eq!(err.code, "panic");
|
|
67
|
-
assert!(err.error.contains("Unexpected panic"));
|
|
68
|
-
}
|
|
69
|
-
}
|
|
1
|
+
//! Shared structured error types and panic shielding utilities.
|
|
2
|
+
//!
|
|
3
|
+
//! Bindings should convert all fatal paths into this shape to keep cross-language
|
|
4
|
+
//! error payloads consistent and avoid panics crossing FFI boundaries.
|
|
5
|
+
|
|
6
|
+
use serde::Serialize;
|
|
7
|
+
use serde_json::Value;
|
|
8
|
+
use std::panic::{UnwindSafe, catch_unwind};
|
|
9
|
+
|
|
10
|
+
/// Canonical error payload: { error, code, details }.
|
|
11
|
+
#[derive(Debug, Clone, Serialize)]
|
|
12
|
+
pub struct StructuredError {
|
|
13
|
+
pub error: String,
|
|
14
|
+
pub code: String,
|
|
15
|
+
#[serde(default)]
|
|
16
|
+
pub details: Value,
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
impl StructuredError {
|
|
20
|
+
pub fn new(code: impl Into<String>, error: impl Into<String>, details: Value) -> Self {
|
|
21
|
+
Self {
|
|
22
|
+
code: code.into(),
|
|
23
|
+
error: error.into(),
|
|
24
|
+
details,
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
pub fn simple(code: impl Into<String>, error: impl Into<String>) -> Self {
|
|
29
|
+
Self::new(code, error, Value::Object(serde_json::Map::new()))
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
/// Catch panics and convert to a structured error so they don't cross FFI boundaries.
|
|
34
|
+
pub fn shield_panic<T, F>(f: F) -> Result<T, StructuredError>
|
|
35
|
+
where
|
|
36
|
+
F: FnOnce() -> T + UnwindSafe,
|
|
37
|
+
{
|
|
38
|
+
catch_unwind(f).map_err(|_| StructuredError::simple("panic", "Unexpected panic in Rust code"))
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
#[cfg(test)]
|
|
42
|
+
mod tests {
|
|
43
|
+
use super::*;
|
|
44
|
+
use serde_json::json;
|
|
45
|
+
|
|
46
|
+
#[test]
|
|
47
|
+
fn structured_error_constructors_populate_fields() {
|
|
48
|
+
let details = json!({"field": "name"});
|
|
49
|
+
let err = StructuredError::new("invalid", "bad input", details.clone());
|
|
50
|
+
assert_eq!(err.code, "invalid");
|
|
51
|
+
assert_eq!(err.error, "bad input");
|
|
52
|
+
assert_eq!(err.details, details);
|
|
53
|
+
|
|
54
|
+
let simple = StructuredError::simple("missing", "not found");
|
|
55
|
+
assert_eq!(simple.code, "missing");
|
|
56
|
+
assert_eq!(simple.error, "not found");
|
|
57
|
+
assert!(simple.details.is_object());
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
#[test]
|
|
61
|
+
fn shield_panic_returns_ok_or_structured_error() {
|
|
62
|
+
let ok = shield_panic(|| 42);
|
|
63
|
+
assert_eq!(ok.unwrap(), 42);
|
|
64
|
+
|
|
65
|
+
let err = shield_panic(|| panic!("boom")).unwrap_err();
|
|
66
|
+
assert_eq!(err.code, "panic");
|
|
67
|
+
assert!(err.error.contains("Unexpected panic"));
|
|
68
|
+
}
|
|
69
|
+
}
|