1pub use camel_api::{LanguageExpressionDef, StreamSplitConfig, ValueSourceDef};
2
3#[derive(Default)]
4pub struct SecurityCompileContext {
5 pub authenticator: Option<std::sync::Arc<dyn camel_auth::TokenAuthenticator>>,
6 pub registry: Option<std::sync::Arc<camel_auth::SecurityPolicyRegistry>>,
7 pub evaluator_registry: Option<std::sync::Arc<camel_auth::PermissionEvaluatorRegistry>>,
8}
9
10impl Clone for SecurityCompileContext {
11 fn clone(&self) -> Self {
12 Self {
13 authenticator: self.authenticator.clone(),
14 registry: self.registry.clone(),
15 evaluator_registry: self.evaluator_registry.clone(),
16 }
17 }
18}
19
20impl SecurityCompileContext {
21 pub fn new(
22 authenticator: Option<std::sync::Arc<dyn camel_auth::TokenAuthenticator>>,
23 registry: Option<std::sync::Arc<camel_auth::SecurityPolicyRegistry>>,
24 ) -> Self {
25 Self {
26 authenticator,
27 registry,
28 evaluator_registry: None,
29 }
30 }
31
32 pub fn with_evaluator_registry(
33 mut self,
34 registry: std::sync::Arc<camel_auth::PermissionEvaluatorRegistry>,
35 ) -> Self {
36 self.evaluator_registry = Some(registry);
37 self
38 }
39
40 pub fn with_security_policy_registry(
41 mut self,
42 registry: std::sync::Arc<camel_auth::SecurityPolicyRegistry>,
43 ) -> Self {
44 self.registry = Some(registry);
45 self
46 }
47}
48
49#[derive(Debug, Clone, PartialEq, Eq)]
50pub enum DeclarativeConcurrency {
51 Sequential,
52 Concurrent { max: Option<usize> },
53}
54
55#[derive(Debug, Clone, PartialEq, Eq)]
56pub struct DeclarativeCircuitBreaker {
57 pub failure_threshold: u32,
58 pub open_duration_ms: u64,
59}
60
61#[derive(Debug, Clone, PartialEq)]
62pub enum DeclarativeSecurityPolicy {
63 Roles {
64 roles: Vec<String>,
65 all_required: bool,
66 trust_upstream_principal: bool,
67 },
68 Scopes {
69 scopes: Vec<String>,
70 all_required: bool,
71 trust_upstream_principal: bool,
72 },
73 Ref {
74 name: String,
75 },
76 Wasm {
81 path: String,
83 config: std::collections::HashMap<String, String>,
85 },
86 Permission {
87 policy: String,
88 resource: camel_auth::PermissionValueSource,
89 action: camel_auth::PermissionValueSource,
90 scopes: Vec<String>,
91 context: camel_auth::PermissionContextConfig,
92 cache_ttl_secs: Option<u64>,
93 cache_negative_ttl_secs: Option<u64>,
94 },
95}
96
97#[derive(Debug, Clone, PartialEq)]
98pub struct DeclarativeRedeliveryPolicy {
99 pub max_attempts: u32,
100 pub initial_delay_ms: u64,
101 pub multiplier: f64,
102 pub max_delay_ms: u64,
103 pub jitter_factor: f64,
104 pub handled_by: Option<String>,
105}
106
107#[derive(Debug, Clone, PartialEq)]
108pub struct DeclarativeOnException {
109 pub kind: Option<String>,
110 pub message_contains: Option<String>,
111 pub retry: Option<DeclarativeRedeliveryPolicy>,
112 pub steps: Vec<DeclarativeStep>,
113 pub handled: Option<bool>,
114 pub continued: Option<bool>,
115}
116
117#[derive(Debug, Clone, PartialEq, Default)]
118pub struct DeclarativeErrorHandler {
119 pub dead_letter_channel: Option<String>,
120 pub retry: Option<DeclarativeRedeliveryPolicy>,
121 pub on_exceptions: Option<Vec<DeclarativeOnException>>,
122 pub use_original_message: bool,
123}
124
125#[derive(Debug, Clone)]
126pub struct DeclarativeRoute {
127 pub from: String,
128 pub route_id: String,
129 pub auto_startup: bool,
130 pub startup_order: i32,
131 pub concurrency: Option<DeclarativeConcurrency>,
132 pub error_handler: Option<DeclarativeErrorHandler>,
133 pub circuit_breaker: Option<DeclarativeCircuitBreaker>,
134 pub security_policy: Option<DeclarativeSecurityPolicy>,
135 pub unit_of_work: Option<camel_api::UnitOfWorkConfig>,
136 pub steps: Vec<DeclarativeStep>,
137}
138
139#[derive(Debug, Clone, PartialEq, Eq)]
140pub struct ToStepDef {
141 pub uri: String,
142}
143
144impl ToStepDef {
145 pub fn new(uri: impl Into<String>) -> Self {
146 Self { uri: uri.into() }
147 }
148}
149
150#[derive(Debug, Clone, PartialEq, Eq)]
151pub enum LogLevelDef {
152 Trace,
153 Debug,
154 Info,
155 Warn,
156 Error,
157}
158
159#[derive(Debug, Clone, PartialEq)]
162pub struct LogStepDef {
163 pub message: ValueSourceDef,
164 pub level: LogLevelDef,
165}
166
167impl LogStepDef {
168 pub fn info(message: impl Into<String>) -> Self {
169 Self {
170 message: ValueSourceDef::Literal(serde_json::Value::String(message.into())),
171 level: LogLevelDef::Info,
172 }
173 }
174}
175
176#[derive(Debug, Clone, PartialEq)]
177pub struct SetHeaderStepDef {
178 pub key: String,
179 pub value: ValueSourceDef,
180}
181
182impl SetHeaderStepDef {
183 pub fn literal(key: impl Into<String>, value: impl Into<String>) -> Self {
184 Self {
185 key: key.into(),
186 value: ValueSourceDef::Literal(serde_json::Value::String(value.into())),
187 }
188 }
189}
190
191#[derive(Debug, Clone, PartialEq)]
192pub struct SetPropertyStepDef {
193 pub key: String,
194 pub value: ValueSourceDef,
195}
196
197impl SetPropertyStepDef {
198 pub fn literal(key: impl Into<String>, value: impl Into<String>) -> Self {
199 Self {
200 key: key.into(),
201 value: ValueSourceDef::Literal(serde_json::Value::String(value.into())),
202 }
203 }
204}
205
206#[derive(Debug, Clone, PartialEq)]
207pub struct SetBodyStepDef {
208 pub value: ValueSourceDef,
209}
210
211#[derive(Debug, Clone, PartialEq)]
212pub struct FilterStepDef {
213 pub predicate: LanguageExpressionDef,
214 pub steps: Vec<DeclarativeStep>,
215}
216
217#[derive(Debug, Clone, PartialEq, Eq)]
218pub struct FunctionStepDef {
219 pub runtime: String,
220 pub source: String,
221 pub timeout_ms: Option<u64>,
222}
223
224#[derive(Debug, Clone, PartialEq)]
225pub struct WhenStepDef {
226 pub predicate: LanguageExpressionDef,
227 pub steps: Vec<DeclarativeStep>,
228}
229
230#[derive(Debug, Clone, PartialEq)]
231pub struct ChoiceStepDef {
232 pub whens: Vec<WhenStepDef>,
233 pub otherwise: Option<Vec<DeclarativeStep>>,
234}
235
236#[derive(Debug, Clone, PartialEq)]
237pub enum SplitExpressionDef {
238 BodyLines,
239 BodyJsonArray,
240 Language(LanguageExpressionDef),
241 Stream(StreamSplitConfig),
242}
243
244#[derive(Debug, Clone, PartialEq, Eq)]
245pub enum SplitAggregationDef {
246 LastWins,
247 CollectAll,
248 Original,
249}
250
251#[derive(Debug, Clone, PartialEq)]
252pub struct SplitStepDef {
253 pub expression: SplitExpressionDef,
254 pub aggregation: SplitAggregationDef,
255 pub parallel: bool,
256 pub parallel_limit: Option<usize>,
257 pub stop_on_exception: bool,
258 pub steps: Vec<DeclarativeStep>,
259}
260
261#[derive(Debug, Clone, PartialEq, Eq)]
262pub enum AggregateStrategyDef {
263 CollectAll,
264}
265
266#[derive(Debug, Clone, PartialEq)]
267pub struct AggregateStepDef {
268 pub header: String,
269 pub correlation_key: Option<String>,
270 pub completion_size: Option<usize>,
271 pub completion_timeout_ms: Option<u64>,
272 pub completion_predicate: Option<LanguageExpressionDef>,
273 pub strategy: AggregateStrategyDef,
274 pub max_buckets: Option<usize>,
275 pub bucket_ttl_ms: Option<u64>,
276 pub force_completion_on_stop: Option<bool>,
277 pub discard_on_timeout: Option<bool>,
278}
279
280#[derive(Debug, Clone, PartialEq, Eq)]
281pub struct WireTapStepDef {
282 pub uri: String,
283}
284
285#[derive(Debug, Clone, PartialEq, Eq)]
286pub struct BeanStepDef {
287 pub name: String,
288 pub method: String,
289}
290
291impl BeanStepDef {
292 pub fn new(name: impl Into<String>, method: impl Into<String>) -> Self {
293 Self {
294 name: name.into(),
295 method: method.into(),
296 }
297 }
298}
299
300#[derive(Debug, Clone, PartialEq, Eq, Default)]
301pub enum ThrottleStrategyDef {
302 #[default]
303 Delay,
304 Reject,
305 Drop,
306}
307
308#[derive(Debug, Clone, PartialEq)]
309pub struct ThrottleStepDef {
310 pub max_requests: usize,
311 pub period_ms: u64,
312 pub strategy: ThrottleStrategyDef,
313 pub steps: Vec<DeclarativeStep>,
314}
315
316#[derive(Debug, Clone, PartialEq, Eq, Default)]
317pub enum LoadBalanceStrategyDef {
318 #[default]
319 RoundRobin,
320 Random,
321 Failover,
322 Weighted {
323 distribution_ratio: String,
324 },
325}
326
327#[derive(Debug, Clone, PartialEq)]
328pub struct LoadBalanceStepDef {
329 pub strategy: LoadBalanceStrategyDef,
330 pub steps: Vec<DeclarativeStep>,
331}
332
333#[derive(Debug, Clone, PartialEq, Eq)]
334pub struct DynamicRouterStepDef {
335 pub expression: LanguageExpressionDef,
336 pub uri_delimiter: String,
337 pub cache_size: i32,
338 pub ignore_invalid_endpoints: bool,
339 pub max_iterations: usize,
340}
341
342#[derive(Debug, Clone, PartialEq, Eq)]
343pub struct RoutingSlipStepDef {
344 pub expression: LanguageExpressionDef,
345 pub uri_delimiter: String,
346 pub cache_size: i32,
347 pub ignore_invalid_endpoints: bool,
348}
349
350#[derive(Debug, Clone, PartialEq, Eq)]
351pub struct RecipientListStepDef {
352 pub expression: LanguageExpressionDef,
353 pub delimiter: String,
354 pub parallel: bool,
355 pub parallel_limit: Option<usize>,
356 pub stop_on_exception: bool,
357 pub aggregation: MulticastAggregationDef,
358}
359
360#[derive(Debug, Clone, PartialEq, Eq)]
361pub enum MulticastAggregationDef {
362 LastWins,
363 CollectAll,
364 Original,
365}
366
367#[derive(Debug, Clone, PartialEq)]
368pub struct MulticastStepDef {
369 pub steps: Vec<DeclarativeStep>,
370 pub parallel: bool,
371 pub parallel_limit: Option<usize>,
372 pub stop_on_exception: bool,
373 pub timeout_ms: Option<u64>,
374 pub aggregation: MulticastAggregationDef,
375}
376
377#[derive(Debug, Clone, PartialEq, Eq)]
378pub struct ScriptStepDef {
379 pub expression: LanguageExpressionDef,
380}
381
382#[derive(Debug, Clone, PartialEq, Eq)]
383pub enum BodyTypeDef {
384 Text,
385 Json,
386 Bytes,
387 Xml,
388 Empty,
389}
390
391#[derive(Debug, Clone, PartialEq)]
392pub struct DataFormatDef {
393 pub format: String,
394 pub schema: Option<serde_json::Value>,
398}
399
400#[derive(Debug, Clone, PartialEq, Eq)]
401pub struct DelayStepDef {
402 pub delay_ms: u64,
403 pub dynamic_header: Option<String>,
404}
405
406#[derive(Debug, Clone, PartialEq)]
407pub struct LoopStepDef {
408 pub count: Option<usize>,
409 pub while_predicate: Option<LanguageExpressionDef>,
410 pub steps: Vec<DeclarativeStep>,
411}
412
413#[derive(Debug, Clone, PartialEq, Eq)]
414pub struct StreamCacheStepDef {
415 pub threshold: Option<usize>,
416}
417
418#[derive(Debug, Clone, PartialEq, Eq)]
419pub struct ValidateStepDef {
420 pub predicate: LanguageExpressionDef,
421}
422
423#[derive(Debug, Clone, PartialEq, Eq)]
427pub struct ClaimCheckStepDef {
428 pub repository: String,
430 pub operation: String,
432 pub key: LanguageExpressionDef,
434 pub filter: Option<String>,
436}
437
438#[derive(Debug, Clone, PartialEq)]
443pub struct IdempotentConsumerStepDef {
444 pub repository: String,
446 pub expression: LanguageExpressionDef,
448 pub steps: Vec<DeclarativeStep>,
450 pub eager: Option<bool>,
453 pub remove_on_failure: Option<bool>,
456}
457
458#[derive(Debug, Clone, PartialEq, Eq)]
462pub struct SamplingStepDef {
463 pub period: usize,
465}
466
467#[derive(Debug, Clone, PartialEq, Eq)]
472pub struct SortStepDef {
473 pub expression: LanguageExpressionDef,
475 pub reverse: bool,
477}
478
479#[derive(Debug, Clone, PartialEq, Eq)]
483pub struct ResequenceStepDef {
484 pub mode: ResequenceModeDef,
485}
486
487#[derive(Debug, Clone, PartialEq, Eq)]
489pub enum ResequenceModeDef {
490 Batch {
491 correlation: String,
492 sort: String,
493 completion: camel_api::resequencer::BatchCompletion,
494 },
495 Stream {
496 sequence: String,
497 capacity: usize,
498 gap_timeout: u64,
499 on_gap: camel_api::resequencer::GapPolicy,
500 on_capacity_exceeded: camel_api::resequencer::CapacityPolicy,
501 dedup: bool,
502 },
503}
504
505#[derive(Debug, Clone, PartialEq, Eq)]
506pub struct EnrichStepDef {
507 pub uri: String,
508 pub strategy: Option<String>,
509 pub timeout_ms: Option<u64>,
510}
511
512#[derive(Debug, Clone, PartialEq)]
513pub struct DoTryCatchClauseDef {
514 pub exception: Option<Vec<String>>,
515 pub when: Option<LanguageExpressionDef>,
516 pub on_when: Option<LanguageExpressionDef>,
517 pub disposition: camel_api::error_handler::ExceptionDisposition,
518 pub steps: Vec<DeclarativeStep>,
519}
520
521#[derive(Debug, Clone, PartialEq)]
522pub struct DoTryFinallyDef {
523 pub on_when: Option<LanguageExpressionDef>,
524 pub steps: Vec<DeclarativeStep>,
525}
526
527#[derive(Debug, Clone, PartialEq)]
528pub enum DeclarativeStep {
529 To(ToStepDef),
530 SetHeader(SetHeaderStepDef),
531 SetProperty(SetPropertyStepDef),
532 SetBody(SetBodyStepDef),
533 ConvertBodyTo(BodyTypeDef),
534 DynamicRouter(DynamicRouterStepDef),
535 Filter(FilterStepDef),
536 Function(FunctionStepDef),
537 LoadBalance(LoadBalanceStepDef),
538 Log(LogStepDef),
539 Choice(ChoiceStepDef),
540 Split(SplitStepDef),
541 Aggregate(AggregateStepDef),
542 WireTap(WireTapStepDef),
543 Multicast(MulticastStepDef),
544 RoutingSlip(RoutingSlipStepDef),
545 RecipientList(RecipientListStepDef),
546 Stop,
547 Throttle(ThrottleStepDef),
548 Script(ScriptStepDef),
549 StreamCache(StreamCacheStepDef),
550 Marshal(DataFormatDef),
551 Unmarshal(DataFormatDef),
552 Validate(ValidateStepDef),
553 Bean(BeanStepDef),
554 Delay(DelayStepDef),
555 Loop(LoopStepDef),
556 Enrich(EnrichStepDef),
557 PollEnrich(EnrichStepDef),
558 IdempotentConsumer(IdempotentConsumerStepDef),
559 ClaimCheck(ClaimCheckStepDef),
560 Sampling(SamplingStepDef),
561 Sort(SortStepDef),
562 Resequence(ResequenceStepDef),
563 DoTry {
564 steps: Vec<DeclarativeStep>,
565 catch: Vec<DoTryCatchClauseDef>,
566 finally: Option<DoTryFinallyDef>,
567 },
568}
569
570impl DeclarativeStep {
571 pub fn kind(&self) -> crate::contract::DeclarativeStepKind {
572 match self {
573 DeclarativeStep::To(_) => crate::contract::DeclarativeStepKind::To,
574 DeclarativeStep::Log(_) => crate::contract::DeclarativeStepKind::Log,
575 DeclarativeStep::SetHeader(_) => crate::contract::DeclarativeStepKind::SetHeader,
576 DeclarativeStep::SetProperty(_) => crate::contract::DeclarativeStepKind::SetProperty,
577 DeclarativeStep::SetBody(_) => crate::contract::DeclarativeStepKind::SetBody,
578 DeclarativeStep::ConvertBodyTo(_) => {
579 crate::contract::DeclarativeStepKind::ConvertBodyTo
580 }
581 DeclarativeStep::DynamicRouter(_) => {
582 crate::contract::DeclarativeStepKind::DynamicRouter
583 }
584 DeclarativeStep::Filter(_) => crate::contract::DeclarativeStepKind::Filter,
585 DeclarativeStep::Function(_) => crate::contract::DeclarativeStepKind::Function,
586 DeclarativeStep::LoadBalance(_) => crate::contract::DeclarativeStepKind::LoadBalance,
587 DeclarativeStep::Choice(_) => crate::contract::DeclarativeStepKind::Choice,
588 DeclarativeStep::Split(_) => crate::contract::DeclarativeStepKind::Split,
589 DeclarativeStep::Aggregate(_) => crate::contract::DeclarativeStepKind::Aggregate,
590 DeclarativeStep::WireTap(_) => crate::contract::DeclarativeStepKind::WireTap,
591 DeclarativeStep::Multicast(_) => crate::contract::DeclarativeStepKind::Multicast,
592 DeclarativeStep::RoutingSlip(_) => crate::contract::DeclarativeStepKind::RoutingSlip,
593 DeclarativeStep::RecipientList(_) => {
594 crate::contract::DeclarativeStepKind::RecipientList
595 }
596 DeclarativeStep::Stop => crate::contract::DeclarativeStepKind::Stop,
597 DeclarativeStep::Throttle(_) => crate::contract::DeclarativeStepKind::Throttle,
598 DeclarativeStep::Script(_) => crate::contract::DeclarativeStepKind::Script,
599 DeclarativeStep::StreamCache(_) => crate::contract::DeclarativeStepKind::StreamCache,
600 DeclarativeStep::Marshal(_) => crate::contract::DeclarativeStepKind::Marshal,
601 DeclarativeStep::Unmarshal(_) => crate::contract::DeclarativeStepKind::Unmarshal,
602 DeclarativeStep::Validate(_) => crate::contract::DeclarativeStepKind::Validate,
603 DeclarativeStep::Bean(_) => crate::contract::DeclarativeStepKind::Bean,
604 DeclarativeStep::Delay(_) => crate::contract::DeclarativeStepKind::Delay,
605 DeclarativeStep::Loop(_) => crate::contract::DeclarativeStepKind::Loop,
606 DeclarativeStep::Enrich(_) => crate::contract::DeclarativeStepKind::Enrich,
607 DeclarativeStep::PollEnrich(_) => crate::contract::DeclarativeStepKind::PollEnrich,
608 DeclarativeStep::IdempotentConsumer(_) => {
609 crate::contract::DeclarativeStepKind::IdempotentConsumer
610 }
611 DeclarativeStep::ClaimCheck(_) => crate::contract::DeclarativeStepKind::ClaimCheck,
612 DeclarativeStep::Sampling(_) => crate::contract::DeclarativeStepKind::Sampling,
613 DeclarativeStep::Sort(_) => crate::contract::DeclarativeStepKind::Sort,
614 DeclarativeStep::Resequence(_) => crate::contract::DeclarativeStepKind::Resequence,
615 DeclarativeStep::DoTry { .. } => crate::contract::DeclarativeStepKind::DoTry,
616 }
617 }
618}
619
620#[cfg(test)]
621mod tests {
622 use super::*;
623
624 #[test]
625 fn to_step_def_new() {
626 let def = ToStepDef::new("direct:a");
627 assert_eq!(def.uri, "direct:a");
628 }
629
630 #[test]
631 fn log_step_def_info() {
632 let def = LogStepDef::info("hello");
633 assert_eq!(def.level, LogLevelDef::Info);
634 match def.message {
635 ValueSourceDef::Literal(v) => assert_eq!(v, serde_json::Value::String("hello".into())),
636 _ => panic!("expected literal"),
637 }
638 }
639
640 #[test]
641 fn set_header_literal() {
642 let def = SetHeaderStepDef::literal("key", "value");
643 assert_eq!(def.key, "key");
644 match def.value {
645 ValueSourceDef::Literal(v) => assert_eq!(v, serde_json::Value::String("value".into())),
646 _ => panic!("expected literal"),
647 }
648 }
649
650 #[test]
651 fn bean_step_def_new() {
652 let def = BeanStepDef::new("myBean", "process");
653 assert_eq!(def.name, "myBean");
654 assert_eq!(def.method, "process");
655 }
656
657 #[test]
658 fn throttle_strategy_default() {
659 assert_eq!(ThrottleStrategyDef::default(), ThrottleStrategyDef::Delay);
660 }
661
662 #[test]
663 fn load_balance_strategy_default() {
664 assert_eq!(
665 LoadBalanceStrategyDef::default(),
666 LoadBalanceStrategyDef::RoundRobin
667 );
668 }
669
670 #[test]
671 fn concurrency_variants_equality() {
672 assert_eq!(
673 DeclarativeConcurrency::Sequential,
674 DeclarativeConcurrency::Sequential
675 );
676 assert_ne!(
677 DeclarativeConcurrency::Sequential,
678 DeclarativeConcurrency::Concurrent { max: None }
679 );
680 }
681
682 #[test]
683 fn body_type_variants() {
684 assert_eq!(BodyTypeDef::Text, BodyTypeDef::Text);
685 assert_ne!(BodyTypeDef::Text, BodyTypeDef::Json);
686 }
687
688 #[test]
689 fn data_format_def() {
690 let def = DataFormatDef {
691 format: "protobuf".into(),
692 schema: None,
693 };
694 assert_eq!(def.format, "protobuf");
695 assert!(def.schema.is_none());
696 }
697
698 #[test]
699 fn stream_cache_step_def() {
700 let def = StreamCacheStepDef {
701 threshold: Some(1024),
702 };
703 assert_eq!(def.threshold, Some(1024));
704 }
705
706 #[test]
707 fn delay_step_def() {
708 let def = DelayStepDef {
709 delay_ms: 500,
710 dynamic_header: Some("X-Delay".into()),
711 };
712 assert_eq!(def.delay_ms, 500);
713 assert_eq!(def.dynamic_header.as_deref(), Some("X-Delay"));
714 }
715
716 #[test]
717 fn circuit_breaker_def() {
718 let cb = DeclarativeCircuitBreaker {
719 failure_threshold: 3,
720 open_duration_ms: 5000,
721 };
722 assert_eq!(cb.failure_threshold, 3);
723 assert_eq!(cb.open_duration_ms, 5000);
724 }
725}