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 pub config: Option<serde_json::Value>,
401}
402
403#[derive(Debug, Clone, PartialEq, Eq)]
404pub struct DelayStepDef {
405 pub delay_ms: u64,
406 pub dynamic_header: Option<String>,
407}
408
409#[derive(Debug, Clone, PartialEq)]
410pub struct LoopStepDef {
411 pub count: Option<usize>,
412 pub while_predicate: Option<LanguageExpressionDef>,
413 pub steps: Vec<DeclarativeStep>,
414 pub max_iterations: Option<usize>,
415}
416
417#[derive(Debug, Clone, PartialEq, Eq)]
418pub struct StreamCacheStepDef {
419 pub threshold: Option<usize>,
420}
421
422#[derive(Debug, Clone, PartialEq, Eq)]
423pub struct ValidateStepDef {
424 pub predicate: LanguageExpressionDef,
425}
426
427#[derive(Debug, Clone, PartialEq, Eq)]
431pub struct ClaimCheckStepDef {
432 pub repository: String,
434 pub operation: String,
436 pub key: LanguageExpressionDef,
438 pub filter: Option<String>,
440}
441
442#[derive(Debug, Clone, PartialEq)]
447pub struct IdempotentConsumerStepDef {
448 pub repository: String,
450 pub expression: LanguageExpressionDef,
452 pub steps: Vec<DeclarativeStep>,
454 pub eager: Option<bool>,
457 pub remove_on_failure: Option<bool>,
460}
461
462#[derive(Debug, Clone, PartialEq, Eq)]
466pub struct SamplingStepDef {
467 pub period: usize,
469}
470
471#[derive(Debug, Clone, PartialEq, Eq)]
476pub struct SortStepDef {
477 pub expression: LanguageExpressionDef,
479 pub reverse: bool,
481}
482
483#[derive(Debug, Clone, PartialEq, Eq)]
487pub struct ResequenceStepDef {
488 pub mode: ResequenceModeDef,
489}
490
491#[derive(Debug, Clone, PartialEq, Eq)]
493pub enum ResequenceModeDef {
494 Batch {
495 correlation: String,
496 sort: String,
497 completion: camel_api::resequencer::BatchCompletion,
498 },
499 Stream {
500 sequence: String,
501 capacity: usize,
502 gap_timeout: u64,
503 on_gap: camel_api::resequencer::GapPolicy,
504 on_capacity_exceeded: camel_api::resequencer::CapacityPolicy,
505 dedup: bool,
506 },
507}
508
509#[derive(Debug, Clone, PartialEq, Eq)]
510pub struct EnrichStepDef {
511 pub uri: String,
512 pub strategy: Option<String>,
513 pub timeout_ms: Option<u64>,
514}
515
516#[derive(Debug, Clone, PartialEq)]
517pub struct DoTryCatchClauseDef {
518 pub exception: Option<Vec<String>>,
519 pub when: Option<LanguageExpressionDef>,
520 pub on_when: Option<LanguageExpressionDef>,
521 pub disposition: camel_api::error_handler::ExceptionDisposition,
522 pub steps: Vec<DeclarativeStep>,
523}
524
525#[derive(Debug, Clone, PartialEq)]
526pub struct DoTryFinallyDef {
527 pub on_when: Option<LanguageExpressionDef>,
528 pub steps: Vec<DeclarativeStep>,
529}
530
531#[derive(Debug, Clone, PartialEq)]
532pub enum DeclarativeStep {
533 To(ToStepDef),
534 SetHeader(SetHeaderStepDef),
535 SetHeaderIfAbsent(SetHeaderStepDef),
536 SetProperty(SetPropertyStepDef),
537 SetBody(SetBodyStepDef),
538 ConvertBodyTo(BodyTypeDef),
539 DynamicRouter(DynamicRouterStepDef),
540 Filter(FilterStepDef),
541 Function(FunctionStepDef),
542 LoadBalance(LoadBalanceStepDef),
543 Log(LogStepDef),
544 Choice(ChoiceStepDef),
545 Split(SplitStepDef),
546 Aggregate(AggregateStepDef),
547 WireTap(WireTapStepDef),
548 Multicast(MulticastStepDef),
549 RoutingSlip(RoutingSlipStepDef),
550 RecipientList(RecipientListStepDef),
551 Stop,
552 Throttle(ThrottleStepDef),
553 Script(ScriptStepDef),
554 StreamCache(StreamCacheStepDef),
555 Marshal(DataFormatDef),
556 Unmarshal(DataFormatDef),
557 Validate(ValidateStepDef),
558 Bean(BeanStepDef),
559 Delay(DelayStepDef),
560 Loop(LoopStepDef),
561 Enrich(EnrichStepDef),
562 PollEnrich(EnrichStepDef),
563 IdempotentConsumer(IdempotentConsumerStepDef),
564 ClaimCheck(ClaimCheckStepDef),
565 Sampling(SamplingStepDef),
566 Sort(SortStepDef),
567 Resequence(ResequenceStepDef),
568 DoTry {
569 steps: Vec<DeclarativeStep>,
570 catch: Vec<DoTryCatchClauseDef>,
571 finally: Option<DoTryFinallyDef>,
572 },
573}
574
575impl DeclarativeStep {
576 pub fn kind(&self) -> crate::contract::DeclarativeStepKind {
577 match self {
578 DeclarativeStep::To(_) => crate::contract::DeclarativeStepKind::To,
579 DeclarativeStep::Log(_) => crate::contract::DeclarativeStepKind::Log,
580 DeclarativeStep::SetHeader(_) => crate::contract::DeclarativeStepKind::SetHeader,
581 DeclarativeStep::SetHeaderIfAbsent(_) => {
582 crate::contract::DeclarativeStepKind::SetHeaderIfAbsent
583 }
584 DeclarativeStep::SetProperty(_) => crate::contract::DeclarativeStepKind::SetProperty,
585 DeclarativeStep::SetBody(_) => crate::contract::DeclarativeStepKind::SetBody,
586 DeclarativeStep::ConvertBodyTo(_) => {
587 crate::contract::DeclarativeStepKind::ConvertBodyTo
588 }
589 DeclarativeStep::DynamicRouter(_) => {
590 crate::contract::DeclarativeStepKind::DynamicRouter
591 }
592 DeclarativeStep::Filter(_) => crate::contract::DeclarativeStepKind::Filter,
593 DeclarativeStep::Function(_) => crate::contract::DeclarativeStepKind::Function,
594 DeclarativeStep::LoadBalance(_) => crate::contract::DeclarativeStepKind::LoadBalance,
595 DeclarativeStep::Choice(_) => crate::contract::DeclarativeStepKind::Choice,
596 DeclarativeStep::Split(_) => crate::contract::DeclarativeStepKind::Split,
597 DeclarativeStep::Aggregate(_) => crate::contract::DeclarativeStepKind::Aggregate,
598 DeclarativeStep::WireTap(_) => crate::contract::DeclarativeStepKind::WireTap,
599 DeclarativeStep::Multicast(_) => crate::contract::DeclarativeStepKind::Multicast,
600 DeclarativeStep::RoutingSlip(_) => crate::contract::DeclarativeStepKind::RoutingSlip,
601 DeclarativeStep::RecipientList(_) => {
602 crate::contract::DeclarativeStepKind::RecipientList
603 }
604 DeclarativeStep::Stop => crate::contract::DeclarativeStepKind::Stop,
605 DeclarativeStep::Throttle(_) => crate::contract::DeclarativeStepKind::Throttle,
606 DeclarativeStep::Script(_) => crate::contract::DeclarativeStepKind::Script,
607 DeclarativeStep::StreamCache(_) => crate::contract::DeclarativeStepKind::StreamCache,
608 DeclarativeStep::Marshal(_) => crate::contract::DeclarativeStepKind::Marshal,
609 DeclarativeStep::Unmarshal(_) => crate::contract::DeclarativeStepKind::Unmarshal,
610 DeclarativeStep::Validate(_) => crate::contract::DeclarativeStepKind::Validate,
611 DeclarativeStep::Bean(_) => crate::contract::DeclarativeStepKind::Bean,
612 DeclarativeStep::Delay(_) => crate::contract::DeclarativeStepKind::Delay,
613 DeclarativeStep::Loop(_) => crate::contract::DeclarativeStepKind::Loop,
614 DeclarativeStep::Enrich(_) => crate::contract::DeclarativeStepKind::Enrich,
615 DeclarativeStep::PollEnrich(_) => crate::contract::DeclarativeStepKind::PollEnrich,
616 DeclarativeStep::IdempotentConsumer(_) => {
617 crate::contract::DeclarativeStepKind::IdempotentConsumer
618 }
619 DeclarativeStep::ClaimCheck(_) => crate::contract::DeclarativeStepKind::ClaimCheck,
620 DeclarativeStep::Sampling(_) => crate::contract::DeclarativeStepKind::Sampling,
621 DeclarativeStep::Sort(_) => crate::contract::DeclarativeStepKind::Sort,
622 DeclarativeStep::Resequence(_) => crate::contract::DeclarativeStepKind::Resequence,
623 DeclarativeStep::DoTry { .. } => crate::contract::DeclarativeStepKind::DoTry,
624 }
625 }
626}
627
628#[cfg(test)]
629mod tests {
630 use super::*;
631
632 #[test]
633 fn to_step_def_new() {
634 let def = ToStepDef::new("direct:a");
635 assert_eq!(def.uri, "direct:a");
636 }
637
638 #[test]
639 fn log_step_def_info() {
640 let def = LogStepDef::info("hello");
641 assert_eq!(def.level, LogLevelDef::Info);
642 match def.message {
643 ValueSourceDef::Literal(v) => assert_eq!(v, serde_json::Value::String("hello".into())),
644 _ => panic!("expected literal"),
645 }
646 }
647
648 #[test]
649 fn set_header_literal() {
650 let def = SetHeaderStepDef::literal("key", "value");
651 assert_eq!(def.key, "key");
652 match def.value {
653 ValueSourceDef::Literal(v) => assert_eq!(v, serde_json::Value::String("value".into())),
654 _ => panic!("expected literal"),
655 }
656 }
657
658 #[test]
659 fn bean_step_def_new() {
660 let def = BeanStepDef::new("myBean", "process");
661 assert_eq!(def.name, "myBean");
662 assert_eq!(def.method, "process");
663 }
664
665 #[test]
666 fn throttle_strategy_default() {
667 assert_eq!(ThrottleStrategyDef::default(), ThrottleStrategyDef::Delay);
668 }
669
670 #[test]
671 fn load_balance_strategy_default() {
672 assert_eq!(
673 LoadBalanceStrategyDef::default(),
674 LoadBalanceStrategyDef::RoundRobin
675 );
676 }
677
678 #[test]
679 fn concurrency_variants_equality() {
680 assert_eq!(
681 DeclarativeConcurrency::Sequential,
682 DeclarativeConcurrency::Sequential
683 );
684 assert_ne!(
685 DeclarativeConcurrency::Sequential,
686 DeclarativeConcurrency::Concurrent { max: None }
687 );
688 }
689
690 #[test]
691 fn body_type_variants() {
692 assert_eq!(BodyTypeDef::Text, BodyTypeDef::Text);
693 assert_ne!(BodyTypeDef::Text, BodyTypeDef::Json);
694 }
695
696 #[test]
697 fn data_format_def() {
698 let def = DataFormatDef {
699 format: "protobuf".into(),
700 schema: None,
701 config: None,
702 };
703 assert_eq!(def.format, "protobuf");
704 assert!(def.schema.is_none());
705 }
706
707 #[test]
708 fn stream_cache_step_def() {
709 let def = StreamCacheStepDef {
710 threshold: Some(1024),
711 };
712 assert_eq!(def.threshold, Some(1024));
713 }
714
715 #[test]
716 fn delay_step_def() {
717 let def = DelayStepDef {
718 delay_ms: 500,
719 dynamic_header: Some("X-Delay".into()),
720 };
721 assert_eq!(def.delay_ms, 500);
722 assert_eq!(def.dynamic_header.as_deref(), Some("X-Delay"));
723 }
724
725 #[test]
726 fn circuit_breaker_def() {
727 let cb = DeclarativeCircuitBreaker {
728 failure_threshold: 3,
729 open_duration_ms: 5000,
730 };
731 assert_eq!(cb.failure_threshold, 3);
732 assert_eq!(cb.open_duration_ms, 5000);
733 }
734}