spikard 0.4.0-arm64-darwin-23
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 +7 -0
- data/LICENSE +1 -0
- data/README.md +659 -0
- data/ext/spikard_rb/Cargo.toml +17 -0
- data/ext/spikard_rb/extconf.rb +10 -0
- data/ext/spikard_rb/src/lib.rs +6 -0
- data/lib/spikard/app.rb +405 -0
- data/lib/spikard/background.rb +27 -0
- data/lib/spikard/config.rb +396 -0
- data/lib/spikard/converters.rb +13 -0
- data/lib/spikard/handler_wrapper.rb +113 -0
- data/lib/spikard/provide.rb +214 -0
- data/lib/spikard/response.rb +173 -0
- data/lib/spikard/schema.rb +243 -0
- data/lib/spikard/sse.rb +111 -0
- data/lib/spikard/streaming_response.rb +44 -0
- data/lib/spikard/testing.rb +221 -0
- data/lib/spikard/upload_file.rb +131 -0
- data/lib/spikard/version.rb +5 -0
- data/lib/spikard/websocket.rb +59 -0
- data/lib/spikard.rb +43 -0
- data/sig/spikard.rbs +366 -0
- data/vendor/bundle/ruby/3.4.0/gems/diff-lcs-1.6.2/mise.toml +5 -0
- data/vendor/bundle/ruby/3.4.0/gems/rake-compiler-dock-1.10.0/build/buildkitd.toml +2 -0
- data/vendor/crates/spikard-bindings-shared/Cargo.toml +63 -0
- data/vendor/crates/spikard-bindings-shared/examples/config_extraction.rs +139 -0
- data/vendor/crates/spikard-bindings-shared/src/config_extractor.rs +561 -0
- data/vendor/crates/spikard-bindings-shared/src/conversion_traits.rs +194 -0
- data/vendor/crates/spikard-bindings-shared/src/di_traits.rs +246 -0
- data/vendor/crates/spikard-bindings-shared/src/error_response.rs +403 -0
- data/vendor/crates/spikard-bindings-shared/src/handler_base.rs +274 -0
- data/vendor/crates/spikard-bindings-shared/src/lib.rs +25 -0
- data/vendor/crates/spikard-bindings-shared/src/lifecycle_base.rs +298 -0
- data/vendor/crates/spikard-bindings-shared/src/lifecycle_executor.rs +637 -0
- data/vendor/crates/spikard-bindings-shared/src/response_builder.rs +309 -0
- data/vendor/crates/spikard-bindings-shared/src/test_client_base.rs +248 -0
- data/vendor/crates/spikard-bindings-shared/src/validation_helpers.rs +355 -0
- data/vendor/crates/spikard-bindings-shared/tests/comprehensive_coverage.rs +502 -0
- data/vendor/crates/spikard-bindings-shared/tests/error_response_edge_cases.rs +389 -0
- data/vendor/crates/spikard-bindings-shared/tests/handler_base_integration.rs +413 -0
- data/vendor/crates/spikard-core/Cargo.toml +40 -0
- data/vendor/crates/spikard-core/src/bindings/mod.rs +3 -0
- data/vendor/crates/spikard-core/src/bindings/response.rs +133 -0
- data/vendor/crates/spikard-core/src/debug.rs +63 -0
- data/vendor/crates/spikard-core/src/di/container.rs +726 -0
- data/vendor/crates/spikard-core/src/di/dependency.rs +273 -0
- data/vendor/crates/spikard-core/src/di/error.rs +118 -0
- data/vendor/crates/spikard-core/src/di/factory.rs +538 -0
- data/vendor/crates/spikard-core/src/di/graph.rs +545 -0
- data/vendor/crates/spikard-core/src/di/mod.rs +192 -0
- data/vendor/crates/spikard-core/src/di/resolved.rs +411 -0
- data/vendor/crates/spikard-core/src/di/value.rs +283 -0
- data/vendor/crates/spikard-core/src/errors.rs +39 -0
- data/vendor/crates/spikard-core/src/http.rs +153 -0
- data/vendor/crates/spikard-core/src/lib.rs +29 -0
- data/vendor/crates/spikard-core/src/lifecycle.rs +422 -0
- data/vendor/crates/spikard-core/src/metadata.rs +397 -0
- data/vendor/crates/spikard-core/src/parameters.rs +723 -0
- data/vendor/crates/spikard-core/src/problem.rs +310 -0
- data/vendor/crates/spikard-core/src/request_data.rs +189 -0
- data/vendor/crates/spikard-core/src/router.rs +249 -0
- data/vendor/crates/spikard-core/src/schema_registry.rs +183 -0
- data/vendor/crates/spikard-core/src/type_hints.rs +304 -0
- data/vendor/crates/spikard-core/src/validation/error_mapper.rs +689 -0
- data/vendor/crates/spikard-core/src/validation/mod.rs +459 -0
- data/vendor/crates/spikard-http/Cargo.toml +58 -0
- data/vendor/crates/spikard-http/examples/sse-notifications.rs +147 -0
- data/vendor/crates/spikard-http/examples/websocket-chat.rs +91 -0
- data/vendor/crates/spikard-http/src/auth.rs +247 -0
- data/vendor/crates/spikard-http/src/background.rs +1562 -0
- data/vendor/crates/spikard-http/src/bindings/mod.rs +3 -0
- data/vendor/crates/spikard-http/src/bindings/response.rs +1 -0
- data/vendor/crates/spikard-http/src/body_metadata.rs +8 -0
- data/vendor/crates/spikard-http/src/cors.rs +490 -0
- data/vendor/crates/spikard-http/src/debug.rs +63 -0
- data/vendor/crates/spikard-http/src/di_handler.rs +1878 -0
- data/vendor/crates/spikard-http/src/handler_response.rs +532 -0
- data/vendor/crates/spikard-http/src/handler_trait.rs +861 -0
- data/vendor/crates/spikard-http/src/handler_trait_tests.rs +284 -0
- data/vendor/crates/spikard-http/src/lib.rs +524 -0
- data/vendor/crates/spikard-http/src/lifecycle/adapter.rs +149 -0
- data/vendor/crates/spikard-http/src/lifecycle.rs +428 -0
- data/vendor/crates/spikard-http/src/middleware/mod.rs +285 -0
- data/vendor/crates/spikard-http/src/middleware/multipart.rs +930 -0
- data/vendor/crates/spikard-http/src/middleware/urlencoded.rs +541 -0
- data/vendor/crates/spikard-http/src/middleware/validation.rs +287 -0
- data/vendor/crates/spikard-http/src/openapi/mod.rs +309 -0
- data/vendor/crates/spikard-http/src/openapi/parameter_extraction.rs +535 -0
- data/vendor/crates/spikard-http/src/openapi/schema_conversion.rs +867 -0
- data/vendor/crates/spikard-http/src/openapi/spec_generation.rs +678 -0
- data/vendor/crates/spikard-http/src/query_parser.rs +369 -0
- data/vendor/crates/spikard-http/src/response.rs +399 -0
- data/vendor/crates/spikard-http/src/server/handler.rs +1557 -0
- data/vendor/crates/spikard-http/src/server/lifecycle_execution.rs +98 -0
- data/vendor/crates/spikard-http/src/server/mod.rs +806 -0
- data/vendor/crates/spikard-http/src/server/request_extraction.rs +630 -0
- data/vendor/crates/spikard-http/src/server/routing_factory.rs +497 -0
- data/vendor/crates/spikard-http/src/sse.rs +961 -0
- data/vendor/crates/spikard-http/src/testing/form.rs +14 -0
- data/vendor/crates/spikard-http/src/testing/multipart.rs +60 -0
- data/vendor/crates/spikard-http/src/testing/test_client.rs +285 -0
- data/vendor/crates/spikard-http/src/testing.rs +377 -0
- data/vendor/crates/spikard-http/src/websocket.rs +831 -0
- data/vendor/crates/spikard-http/tests/background_behavior.rs +918 -0
- data/vendor/crates/spikard-http/tests/common/handlers.rs +308 -0
- data/vendor/crates/spikard-http/tests/common/mod.rs +21 -0
- data/vendor/crates/spikard-http/tests/di_integration.rs +202 -0
- data/vendor/crates/spikard-http/tests/doc_snippets.rs +4 -0
- data/vendor/crates/spikard-http/tests/lifecycle_execution.rs +1135 -0
- data/vendor/crates/spikard-http/tests/multipart_behavior.rs +688 -0
- data/vendor/crates/spikard-http/tests/server_config_builder.rs +324 -0
- data/vendor/crates/spikard-http/tests/sse_behavior.rs +728 -0
- data/vendor/crates/spikard-http/tests/websocket_behavior.rs +724 -0
- data/vendor/crates/spikard-rb/Cargo.toml +43 -0
- data/vendor/crates/spikard-rb/build.rs +199 -0
- data/vendor/crates/spikard-rb/src/background.rs +63 -0
- data/vendor/crates/spikard-rb/src/config/mod.rs +5 -0
- data/vendor/crates/spikard-rb/src/config/server_config.rs +283 -0
- data/vendor/crates/spikard-rb/src/conversion.rs +459 -0
- data/vendor/crates/spikard-rb/src/di/builder.rs +105 -0
- data/vendor/crates/spikard-rb/src/di/mod.rs +413 -0
- data/vendor/crates/spikard-rb/src/handler.rs +612 -0
- data/vendor/crates/spikard-rb/src/integration/mod.rs +3 -0
- data/vendor/crates/spikard-rb/src/lib.rs +1857 -0
- data/vendor/crates/spikard-rb/src/lifecycle.rs +275 -0
- data/vendor/crates/spikard-rb/src/metadata/mod.rs +5 -0
- data/vendor/crates/spikard-rb/src/metadata/route_extraction.rs +427 -0
- data/vendor/crates/spikard-rb/src/runtime/mod.rs +5 -0
- data/vendor/crates/spikard-rb/src/runtime/server_runner.rs +326 -0
- data/vendor/crates/spikard-rb/src/server.rs +283 -0
- data/vendor/crates/spikard-rb/src/sse.rs +231 -0
- data/vendor/crates/spikard-rb/src/testing/client.rs +404 -0
- data/vendor/crates/spikard-rb/src/testing/mod.rs +7 -0
- data/vendor/crates/spikard-rb/src/testing/sse.rs +143 -0
- data/vendor/crates/spikard-rb/src/testing/websocket.rs +221 -0
- data/vendor/crates/spikard-rb/src/websocket.rs +233 -0
- data/vendor/crates/spikard-rb/tests/magnus_ffi_tests.rs +14 -0
- metadata +213 -0
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
//! Shared utilities for language bindings
|
|
2
|
+
//!
|
|
3
|
+
//! This crate provides common functionality used across all language bindings
|
|
4
|
+
//! (Python, Node.js, Ruby, PHP, WASM) to eliminate code duplication and ensure
|
|
5
|
+
//! consistent behavior.
|
|
6
|
+
|
|
7
|
+
pub mod config_extractor;
|
|
8
|
+
pub mod conversion_traits;
|
|
9
|
+
pub mod di_traits;
|
|
10
|
+
pub mod error_response;
|
|
11
|
+
pub mod handler_base;
|
|
12
|
+
pub mod lifecycle_base;
|
|
13
|
+
pub mod lifecycle_executor;
|
|
14
|
+
pub mod response_builder;
|
|
15
|
+
pub mod test_client_base;
|
|
16
|
+
pub mod validation_helpers;
|
|
17
|
+
|
|
18
|
+
// Re-export commonly used types
|
|
19
|
+
pub use config_extractor::{ConfigExtractor, ConfigSource};
|
|
20
|
+
pub use di_traits::{FactoryDependencyAdapter, ValueDependencyAdapter};
|
|
21
|
+
pub use error_response::ErrorResponseBuilder;
|
|
22
|
+
pub use handler_base::{HandlerError, HandlerExecutor, LanguageHandler};
|
|
23
|
+
pub use lifecycle_executor::{
|
|
24
|
+
HookResultData, LanguageLifecycleHook, LifecycleExecutor, RequestModifications, extract_body,
|
|
25
|
+
};
|
|
@@ -0,0 +1,298 @@
|
|
|
1
|
+
//! Lifecycle hook base implementations
|
|
2
|
+
|
|
3
|
+
use std::sync::Arc;
|
|
4
|
+
|
|
5
|
+
/// Lifecycle hook types supported across all bindings
|
|
6
|
+
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
|
|
7
|
+
pub enum LifecycleHookType {
|
|
8
|
+
/// Called at the start of request processing
|
|
9
|
+
OnRequest,
|
|
10
|
+
/// Called before validation
|
|
11
|
+
PreValidation,
|
|
12
|
+
/// Called before handler execution
|
|
13
|
+
PreHandler,
|
|
14
|
+
/// Called after handler execution
|
|
15
|
+
OnResponse,
|
|
16
|
+
/// Called when an error occurs
|
|
17
|
+
OnError,
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
/// Result type for lifecycle hooks
|
|
21
|
+
#[derive(Clone)]
|
|
22
|
+
pub enum HookResult {
|
|
23
|
+
/// Continue with normal processing
|
|
24
|
+
Continue,
|
|
25
|
+
/// Short-circuit and return this response
|
|
26
|
+
ShortCircuit(serde_json::Value),
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
/// Trait for implementing lifecycle hooks in language bindings
|
|
30
|
+
pub trait LifecycleHook: Send + Sync {
|
|
31
|
+
/// Execute the lifecycle hook
|
|
32
|
+
fn execute(&self, context: serde_json::Value) -> Result<HookResult, String>;
|
|
33
|
+
|
|
34
|
+
/// Get the hook type
|
|
35
|
+
fn hook_type(&self) -> LifecycleHookType;
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
/// Base configuration for lifecycle hooks
|
|
39
|
+
pub struct LifecycleConfig {
|
|
40
|
+
/// Registered hooks by type
|
|
41
|
+
hooks: std::collections::HashMap<LifecycleHookType, Vec<Arc<dyn LifecycleHook>>>,
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
impl LifecycleConfig {
|
|
45
|
+
/// Create a new lifecycle configuration
|
|
46
|
+
pub fn new() -> Self {
|
|
47
|
+
Self {
|
|
48
|
+
hooks: std::collections::HashMap::new(),
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
/// Register a lifecycle hook
|
|
53
|
+
pub fn register(&mut self, hook: Arc<dyn LifecycleHook>) {
|
|
54
|
+
self.hooks.entry(hook.hook_type()).or_default().push(hook);
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
/// Get hooks for a specific type
|
|
58
|
+
pub fn get_hooks(&self, hook_type: LifecycleHookType) -> Vec<Arc<dyn LifecycleHook>> {
|
|
59
|
+
self.hooks.get(&hook_type).cloned().unwrap_or_default()
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
impl Default for LifecycleConfig {
|
|
64
|
+
fn default() -> Self {
|
|
65
|
+
Self::new()
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
#[cfg(test)]
|
|
70
|
+
mod tests {
|
|
71
|
+
use super::*;
|
|
72
|
+
use serde_json::json;
|
|
73
|
+
|
|
74
|
+
struct TestHook {
|
|
75
|
+
hook_type: LifecycleHookType,
|
|
76
|
+
result: HookResult,
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
impl LifecycleHook for TestHook {
|
|
80
|
+
fn execute(&self, _context: serde_json::Value) -> Result<HookResult, String> {
|
|
81
|
+
Ok(self.result.clone())
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
fn hook_type(&self) -> LifecycleHookType {
|
|
85
|
+
self.hook_type
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
#[test]
|
|
90
|
+
fn test_lifecycle_hook_type_equality() {
|
|
91
|
+
assert_eq!(LifecycleHookType::OnRequest, LifecycleHookType::OnRequest);
|
|
92
|
+
assert_ne!(LifecycleHookType::OnRequest, LifecycleHookType::OnResponse);
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
#[test]
|
|
96
|
+
fn test_lifecycle_hook_type_hash() {
|
|
97
|
+
use std::collections::HashSet;
|
|
98
|
+
|
|
99
|
+
let mut set = HashSet::new();
|
|
100
|
+
set.insert(LifecycleHookType::OnRequest);
|
|
101
|
+
set.insert(LifecycleHookType::PreHandler);
|
|
102
|
+
set.insert(LifecycleHookType::OnRequest);
|
|
103
|
+
|
|
104
|
+
assert_eq!(set.len(), 2); // OnRequest should only be added once
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
#[test]
|
|
108
|
+
fn test_hook_result_continue() {
|
|
109
|
+
let result = HookResult::Continue;
|
|
110
|
+
match result {
|
|
111
|
+
HookResult::Continue => {
|
|
112
|
+
// Expected
|
|
113
|
+
}
|
|
114
|
+
HookResult::ShortCircuit(_) => panic!("Expected Continue"),
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
#[test]
|
|
119
|
+
fn test_hook_result_short_circuit() {
|
|
120
|
+
let response = json!({ "status": "error" });
|
|
121
|
+
let result = HookResult::ShortCircuit(response.clone());
|
|
122
|
+
match result {
|
|
123
|
+
HookResult::Continue => panic!("Expected ShortCircuit"),
|
|
124
|
+
HookResult::ShortCircuit(r) => {
|
|
125
|
+
assert_eq!(r, response);
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
#[test]
|
|
131
|
+
fn test_lifecycle_config_new() {
|
|
132
|
+
let config = LifecycleConfig::new();
|
|
133
|
+
assert_eq!(config.get_hooks(LifecycleHookType::OnRequest).len(), 0);
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
#[test]
|
|
137
|
+
fn test_lifecycle_config_default() {
|
|
138
|
+
let config = LifecycleConfig::default();
|
|
139
|
+
assert_eq!(config.get_hooks(LifecycleHookType::OnRequest).len(), 0);
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
#[test]
|
|
143
|
+
fn test_register_single_hook() {
|
|
144
|
+
let mut config = LifecycleConfig::new();
|
|
145
|
+
let hook = Arc::new(TestHook {
|
|
146
|
+
hook_type: LifecycleHookType::OnRequest,
|
|
147
|
+
result: HookResult::Continue,
|
|
148
|
+
});
|
|
149
|
+
|
|
150
|
+
config.register(hook);
|
|
151
|
+
|
|
152
|
+
let hooks = config.get_hooks(LifecycleHookType::OnRequest);
|
|
153
|
+
assert_eq!(hooks.len(), 1);
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
#[test]
|
|
157
|
+
fn test_register_multiple_hooks_same_type() {
|
|
158
|
+
let mut config = LifecycleConfig::new();
|
|
159
|
+
|
|
160
|
+
for i in 0..3 {
|
|
161
|
+
let hook = Arc::new(TestHook {
|
|
162
|
+
hook_type: LifecycleHookType::OnRequest,
|
|
163
|
+
result: if i == 0 {
|
|
164
|
+
HookResult::Continue
|
|
165
|
+
} else {
|
|
166
|
+
HookResult::ShortCircuit(json!({ "index": i }))
|
|
167
|
+
},
|
|
168
|
+
});
|
|
169
|
+
config.register(hook);
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
let hooks = config.get_hooks(LifecycleHookType::OnRequest);
|
|
173
|
+
assert_eq!(hooks.len(), 3);
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
#[test]
|
|
177
|
+
fn test_register_hooks_different_types() {
|
|
178
|
+
let mut config = LifecycleConfig::new();
|
|
179
|
+
|
|
180
|
+
let hook_on_request = Arc::new(TestHook {
|
|
181
|
+
hook_type: LifecycleHookType::OnRequest,
|
|
182
|
+
result: HookResult::Continue,
|
|
183
|
+
});
|
|
184
|
+
|
|
185
|
+
let hook_on_error = Arc::new(TestHook {
|
|
186
|
+
hook_type: LifecycleHookType::OnError,
|
|
187
|
+
result: HookResult::Continue,
|
|
188
|
+
});
|
|
189
|
+
|
|
190
|
+
config.register(hook_on_request);
|
|
191
|
+
config.register(hook_on_error);
|
|
192
|
+
|
|
193
|
+
assert_eq!(config.get_hooks(LifecycleHookType::OnRequest).len(), 1);
|
|
194
|
+
assert_eq!(config.get_hooks(LifecycleHookType::OnError).len(), 1);
|
|
195
|
+
assert_eq!(config.get_hooks(LifecycleHookType::PreHandler).len(), 0);
|
|
196
|
+
}
|
|
197
|
+
|
|
198
|
+
#[test]
|
|
199
|
+
fn test_get_hooks_empty() {
|
|
200
|
+
let config = LifecycleConfig::new();
|
|
201
|
+
let hooks = config.get_hooks(LifecycleHookType::PreValidation);
|
|
202
|
+
assert!(hooks.is_empty());
|
|
203
|
+
}
|
|
204
|
+
|
|
205
|
+
#[test]
|
|
206
|
+
fn test_get_hooks_multiple_calls() {
|
|
207
|
+
let mut config = LifecycleConfig::new();
|
|
208
|
+
|
|
209
|
+
let hook1 = Arc::new(TestHook {
|
|
210
|
+
hook_type: LifecycleHookType::OnResponse,
|
|
211
|
+
result: HookResult::Continue,
|
|
212
|
+
});
|
|
213
|
+
|
|
214
|
+
let hook2 = Arc::new(TestHook {
|
|
215
|
+
hook_type: LifecycleHookType::OnResponse,
|
|
216
|
+
result: HookResult::Continue,
|
|
217
|
+
});
|
|
218
|
+
|
|
219
|
+
config.register(hook1);
|
|
220
|
+
config.register(hook2);
|
|
221
|
+
|
|
222
|
+
// Multiple calls should return independent clones
|
|
223
|
+
let hooks1 = config.get_hooks(LifecycleHookType::OnResponse);
|
|
224
|
+
let hooks2 = config.get_hooks(LifecycleHookType::OnResponse);
|
|
225
|
+
|
|
226
|
+
assert_eq!(hooks1.len(), 2);
|
|
227
|
+
assert_eq!(hooks2.len(), 2);
|
|
228
|
+
}
|
|
229
|
+
|
|
230
|
+
#[test]
|
|
231
|
+
fn test_hook_execute() {
|
|
232
|
+
let hook = TestHook {
|
|
233
|
+
hook_type: LifecycleHookType::OnRequest,
|
|
234
|
+
result: HookResult::Continue,
|
|
235
|
+
};
|
|
236
|
+
|
|
237
|
+
let context = json!({ "test": "data" });
|
|
238
|
+
let result = hook.execute(context);
|
|
239
|
+
|
|
240
|
+
assert!(result.is_ok());
|
|
241
|
+
match result.unwrap() {
|
|
242
|
+
HookResult::Continue => {
|
|
243
|
+
// Expected
|
|
244
|
+
}
|
|
245
|
+
HookResult::ShortCircuit(_) => panic!("Expected Continue"),
|
|
246
|
+
}
|
|
247
|
+
}
|
|
248
|
+
|
|
249
|
+
#[test]
|
|
250
|
+
fn test_hook_type_retrieval() {
|
|
251
|
+
let hook = TestHook {
|
|
252
|
+
hook_type: LifecycleHookType::PreValidation,
|
|
253
|
+
result: HookResult::Continue,
|
|
254
|
+
};
|
|
255
|
+
|
|
256
|
+
assert_eq!(hook.hook_type(), LifecycleHookType::PreValidation);
|
|
257
|
+
}
|
|
258
|
+
|
|
259
|
+
#[test]
|
|
260
|
+
fn test_all_hook_types() {
|
|
261
|
+
let hook_types = vec![
|
|
262
|
+
LifecycleHookType::OnRequest,
|
|
263
|
+
LifecycleHookType::PreValidation,
|
|
264
|
+
LifecycleHookType::PreHandler,
|
|
265
|
+
LifecycleHookType::OnResponse,
|
|
266
|
+
LifecycleHookType::OnError,
|
|
267
|
+
];
|
|
268
|
+
|
|
269
|
+
let mut config = LifecycleConfig::new();
|
|
270
|
+
|
|
271
|
+
for hook_type in hook_types.iter() {
|
|
272
|
+
let hook = Arc::new(TestHook {
|
|
273
|
+
hook_type: *hook_type,
|
|
274
|
+
result: HookResult::Continue,
|
|
275
|
+
});
|
|
276
|
+
config.register(hook);
|
|
277
|
+
}
|
|
278
|
+
|
|
279
|
+
// Verify all types are registered
|
|
280
|
+
for hook_type in hook_types {
|
|
281
|
+
let hooks = config.get_hooks(hook_type);
|
|
282
|
+
assert_eq!(hooks.len(), 1);
|
|
283
|
+
}
|
|
284
|
+
}
|
|
285
|
+
|
|
286
|
+
#[test]
|
|
287
|
+
fn test_hook_result_clone() {
|
|
288
|
+
let original = HookResult::ShortCircuit(json!({ "key": "value" }));
|
|
289
|
+
let cloned = original.clone();
|
|
290
|
+
|
|
291
|
+
match cloned {
|
|
292
|
+
HookResult::ShortCircuit(response) => {
|
|
293
|
+
assert_eq!(response["key"], "value");
|
|
294
|
+
}
|
|
295
|
+
_ => panic!("Expected ShortCircuit"),
|
|
296
|
+
}
|
|
297
|
+
}
|
|
298
|
+
}
|