1mod service_definition;
8mod service_method;
9mod dynamic_discovery;
10
11use proc_macro::TokenStream;
12use quote::quote;
13use syn::{parse_macro_input, ItemImpl, ImplItem, Type};
14fn generate_jwt_validator() -> proc_macro2::TokenStream {
19 quote! {
20 fn validate_jwt_token(token: &str) -> Result<std::collections::HashMap<String, serde_json::Value>, String> {
22 use jsonwebtoken::{decode, DecodingKey, Validation, Algorithm, errors::ErrorKind};
23 use serde_json::Value;
24
25 let jwt_secret = std::env::var("JWT_SECRET").unwrap_or_else(|_| "your-secret-key".to_string());
28 let key = DecodingKey::from_secret(jwt_secret.as_ref());
29
30 let mut validation = Validation::new(Algorithm::HS256);
32 validation.validate_exp = true; validation.validate_aud = false; let token_data = decode::<Value>(token, &key, &validation)
37 .map_err(|err| {
38 match err.kind() {
39 ErrorKind::ExpiredSignature => "JWT token has expired".to_string(),
40 ErrorKind::InvalidSignature => "Invalid JWT signature".to_string(),
41 ErrorKind::InvalidToken => "Invalid JWT token format".to_string(),
42 _ => format!("JWT validation error: {}", err),
43 }
44 })?;
45
46 let mut claims = std::collections::HashMap::new();
48 if let Value::Object(claim_map) = token_data.claims {
49 for (key, value) in claim_map {
50 claims.insert(key, value);
51 }
52 }
53
54 let has_user_id = claims.contains_key("sub") ||
56 claims.contains_key("user_id") ||
57 claims.contains_key("id") ||
58 claims.contains_key("username");
59
60 if !has_user_id {
61 return Err("JWT token missing user identifier (sub, user_id, id, or username)".to_string());
62 }
63
64 Ok(claims)
65 }
66 }
67}
68
69fn generate_universal_utilities() -> proc_macro2::TokenStream {
71 quote! {
72 use std::sync::{Arc, Mutex, RwLock, OnceLock};
74 use std::collections::HashMap;
75 use std::time::{Instant, SystemTime, UNIX_EPOCH, Duration};
76 use serde_json::Value;
77
78 static RATE_LIMITER: OnceLock<Arc<RwLock<HashMap<String, (Instant, u32)>>>> = OnceLock::new();
80 static CACHE_STORE: OnceLock<Arc<RwLock<HashMap<String, (Value, Instant)>>>> = OnceLock::new();
81 static METRICS_STORE: OnceLock<Arc<RwLock<HashMap<String, u64>>>> = OnceLock::new();
82 static AUDIT_LOG: OnceLock<Arc<Mutex<Vec<String>>>> = OnceLock::new();
83 static EVENT_QUEUE: OnceLock<Arc<Mutex<Vec<Value>>>> = OnceLock::new();
84 static BATCH_QUEUE: OnceLock<Arc<Mutex<Vec<Value>>>> = OnceLock::new();
85
86 fn validate_input(payload: &Value) -> Result<(), String> {
88 if let Some(obj) = payload.as_object() {
90 for (key, value) in obj {
91 if key.starts_with('_') {
93 continue;
94 }
95
96 if let Some(s) = value.as_str() {
98 if s.trim().is_empty() && !key.ends_with("_optional") {
99 return Err(format!("Field '{}' cannot be empty", key));
100 }
101 if s.len() > 10000 {
103 return Err(format!("Field '{}' exceeds maximum length", key));
104 }
105 }
106
107 if key.contains("email") {
109 if let Some(email) = value.as_str() {
110 if !email.contains('@') || !email.contains('.') {
111 return Err(format!("Invalid email format in field '{}'", key));
112 }
113 }
114 }
115 }
116 Ok(())
117 } else {
118 Err("Payload must be a JSON object".to_string())
119 }
120 }
121
122 fn check_rate_limit(key: &str, max_requests: u32, window_secs: u64) -> Result<(), String> {
124 let store = RATE_LIMITER.get_or_init(|| Arc::new(RwLock::new(HashMap::new())));
125 let mut limiter = store.write().unwrap();
126 let now = Instant::now();
127 let window = Duration::from_secs(window_secs);
128
129 match limiter.get_mut(key) {
130 Some((last_reset, count)) => {
131 if now.duration_since(*last_reset) > window {
132 *last_reset = now;
134 *count = 1;
135 Ok(())
136 } else if *count >= max_requests {
137 Err(format!("Rate limit exceeded: {} requests per {}s", max_requests, window_secs))
138 } else {
139 *count += 1;
140 Ok(())
141 }
142 }
143 None => {
144 limiter.insert(key.to_string(), (now, 1));
145 Ok(())
146 }
147 }
148 }
149
150 fn get_from_cache(key: &str, ttl_secs: u64) -> Option<Value> {
152 let store = CACHE_STORE.get_or_init(|| Arc::new(RwLock::new(HashMap::new())));
153 let cache = store.read().unwrap();
154
155 if let Some((value, stored_at)) = cache.get(key) {
156 let now = Instant::now();
157 if now.duration_since(*stored_at) <= Duration::from_secs(ttl_secs) {
158 Some(value.clone())
159 } else {
160 None }
162 } else {
163 None
164 }
165 }
166
167 fn set_cache(key: &str, value: Value) {
168 let store = CACHE_STORE.get_or_init(|| Arc::new(RwLock::new(HashMap::new())));
169 let mut cache = store.write().unwrap();
170 cache.insert(key.to_string(), (value, Instant::now()));
171 }
172
173 fn record_metric(name: &str, value: u64) {
175 let store = METRICS_STORE.get_or_init(|| Arc::new(RwLock::new(HashMap::new())));
176 let mut metrics = store.write().unwrap();
177 *metrics.entry(name.to_string()).or_insert(0) += value;
178 }
179
180 fn get_metrics() -> HashMap<String, u64> {
181 let store = METRICS_STORE.get_or_init(|| Arc::new(RwLock::new(HashMap::new())));
182 let metrics = store.read().unwrap();
183 metrics.clone()
184 }
185
186 fn audit_log(message: String) {
188 let store = AUDIT_LOG.get_or_init(|| Arc::new(Mutex::new(Vec::new())));
189 let mut log = store.lock().unwrap();
190 let timestamp = SystemTime::now()
191 .duration_since(UNIX_EPOCH)
192 .unwrap()
193 .as_secs();
194 log.push(format!("[{}] {}", timestamp, message));
195 }
196
197 fn publish_event(event: Value) {
199 let store = EVENT_QUEUE.get_or_init(|| Arc::new(Mutex::new(Vec::new())));
200 let mut queue = store.lock().unwrap();
201 queue.push(event);
202 }
203
204 fn add_to_batch(item: Value) -> bool {
206 let store = BATCH_QUEUE.get_or_init(|| Arc::new(Mutex::new(Vec::new())));
207 let mut queue = store.lock().unwrap();
208 queue.push(item);
209 queue.len() >= 10 }
211
212 fn get_batch() -> Vec<Value> {
213 let store = BATCH_QUEUE.get_or_init(|| Arc::new(Mutex::new(Vec::new())));
214 let mut queue = store.lock().unwrap();
215 std::mem::take(&mut *queue)
216 }
217 }
218}
219
220#[proc_macro_attribute]
222pub fn service_definition(args: TokenStream, input: TokenStream) -> TokenStream {
223 service_definition::impl_service_definition(args, input)
224}
225
226#[proc_macro_attribute]
228pub fn service_method(args: TokenStream, input: TokenStream) -> TokenStream {
229 service_method::impl_service_method(args, input)
230}
231
232
233#[proc_macro_attribute]
235pub fn service_impl(_args: TokenStream, input: TokenStream) -> TokenStream {
236 let input = parse_macro_input!(input as ItemImpl);
237
238 let service_name = match &*input.self_ty {
240 Type::Path(path) => {
241 path.path.segments.last()
242 .map(|seg| seg.ident.to_string())
243 .unwrap_or_else(|| "UnknownService".to_string())
244 }
245 _ => "UnknownService".to_string(),
246 };
247
248 let mut generated_methods = Vec::new();
249 let mut generated_registrations = Vec::new();
250 let mut service_methods = Vec::new();
251
252 for item in &input.items {
254 if let ImplItem::Fn(method) = item {
255 let method_name = method.sig.ident.to_string();
256
257 let macro_attrs: Vec<String> = method.attrs.iter()
259 .filter_map(|attr| {
260 let path_str = attr.path().get_ident()?.to_string();
261 if is_universal_macro_attribute(&path_str) {
262 Some(path_str)
263 } else {
264 None
265 }
266 })
267 .collect();
268
269 let service_method_route = method.attrs.iter()
271 .find(|attr| attr.path().is_ident("service_method"))
272 .and_then(|attr| {
273 if let Ok(lit_str) = attr.parse_args::<syn::LitStr>() {
274 Some(lit_str.value())
275 } else {
276 None
277 }
278 });
279
280 if let Some(ref route) = service_method_route {
281 let parts: Vec<&str> = route.splitn(2, ' ').collect();
282 let (http_method, path) = if parts.len() == 2 {
283 (parts[0], parts[1])
284 } else {
285 ("POST", route.as_str())
286 };
287
288 service_methods.push(quote! {
289 serde_json::json!({
290 "name": #method_name,
291 "route": #route,
292 "http_method": #http_method,
293 "path": #path,
294 "description": format!("Auto-generated from {}", #method_name)
295 })
296 });
297 }
298
299 if !macro_attrs.is_empty() || service_method_route.is_some() {
301 let universal_wrapper = generate_universal_wrapper(&service_name, &method_name, ¯o_attrs);
302
303 let method_ident = syn::Ident::new(&method_name, proc_macro2::Span::call_site());
305 generated_registrations.push(quote! {
306 service.register_function(#method_name, |msg: rabbitmesh::Message| async move {
307 #universal_wrapper
308 match Self::#method_ident(msg).await {
309 Ok(response) => Ok(rabbitmesh::message::RpcResponse::Success {
310 data: response,
311 processing_time_ms: 0
312 }),
313 Err(e) => Err(rabbitmesh::error::RabbitMeshError::Handler(e)),
314 }
315 }).await;
316 tracing::info!("Registered RPC handler for method: {}", #method_name);
317 });
318
319 generated_methods.push(method);
320 }
321 }
322 }
323
324 if !service_methods.is_empty() {
326 let kebab_service_name = service_name
327 .chars()
328 .enumerate()
329 .map(|(i, c)| {
330 if c.is_uppercase() && i > 0 {
331 format!("-{}", c.to_lowercase())
332 } else {
333 c.to_lowercase().to_string()
334 }
335 })
336 .collect::<String>()
337 .trim_end_matches("-service")
338 .to_string() + "-service";
339
340 generated_registrations.push(quote! {
341 service.register_function("schema", |_msg: rabbitmesh::Message| async move {
342 let schema = serde_json::json!({
343 "service": #kebab_service_name,
344 "version": "1.0.0",
345 "description": format!("Auto-generated schema for {}", #service_name),
346 "methods": [#(#service_methods),*]
347 });
348 Ok(rabbitmesh::message::RpcResponse::Success {
349 data: schema,
350 processing_time_ms: 0
351 })
352 }).await;
353 tracing::info!("Auto-generated schema method registered for service: {}", #kebab_service_name);
354 });
355 }
356
357 let type_name = &input.self_ty;
359 let (impl_generics, ty_generics, where_clause) = input.generics.split_for_impl();
360
361 let expanded = quote! {
362 #input
363
364 impl #impl_generics #type_name #ty_generics #where_clause {
365 pub async fn register_handlers(service: &rabbitmesh::MicroService) -> anyhow::Result<()> {
367 tracing::info!("🌟 Registering service methods with Universal Macro Framework...");
368 tracing::info!("🔐 Authorization: RBAC, ABAC, Hybrid patterns supported");
369 tracing::info!("💾 Database: Universal transactions for SQL/NoSQL/Graph/TimeSeries");
370 tracing::info!("⚡ Caching: Multi-level intelligent caching with domain optimizations");
371 tracing::info!("✅ Validation: Comprehensive input validation + security + compliance");
372 tracing::info!("📊 Observability: Complete metrics, tracing, logging, monitoring");
373 tracing::info!("🎭 Workflows: State machines, sagas, approvals, event sourcing, CQRS");
374
375 #(#generated_registrations)*
376
377 tracing::info!("✨ All service methods registered with enterprise-grade features!");
378 Ok(())
379 }
380 }
381 };
382
383 expanded.into()
384}
385
386#[proc_macro]
395pub fn generate_auto_gateway(_input: TokenStream) -> TokenStream {
396 use dynamic_discovery::ServiceDiscovery;
397
398 let discovered_services = ServiceDiscovery::discover_workspace_services();
400
401 let gateway_code = ServiceDiscovery::generate_dynamic_gateway(discovered_services);
403
404 gateway_code.into()
405}
406
407fn generate_universal_wrapper(_service_name: &str, _method_name: &str, macro_attrs: &[String]) -> proc_macro2::TokenStream {
409
410 let jwt_validator = if macro_attrs.iter().any(|attr| matches!(attr.as_str(), "require_auth" | "jwt_auth" | "bearer_auth" | "api_key_auth")) {
412 generate_jwt_validator()
413 } else {
414 quote! {}
415 };
416
417 let preprocessing = generate_preprocessing(_service_name, _method_name, macro_attrs);
419 let postprocessing = generate_postprocessing(_service_name, _method_name, macro_attrs);
420
421 quote! {
422 #jwt_validator
424
425 #preprocessing
427
428 #postprocessing
431 }
432}
433
434fn generate_preprocessing(_service_name: &str, _method_name: &str, macro_attrs: &[String]) -> proc_macro2::TokenStream {
436 let mut steps = Vec::new();
437
438 let needs_utilities = macro_attrs.iter().any(|attr| {
440 matches!(attr.as_str(),
441 "validate" | "rate_limit" | "cached" | "cache_read" | "redis_cache" | "memory_cache" |
442 "transactional" | "metrics" | "trace" | "monitor" | "prometheus" |
443 "audit_log" | "event_publish" | "batch_process"
444 )
445 });
446
447 if needs_utilities {
448 let utilities = generate_universal_utilities();
449 steps.push(utilities);
450 }
451
452 if macro_attrs.iter().any(|attr| matches!(attr.as_str(), "require_auth" | "jwt_auth" | "bearer_auth" | "api_key_auth")) {
454 steps.push(quote! {
455 tracing::debug!("🔐 Validating JWT authentication");
456
457 let auth_token = msg.payload.as_object()
459 .and_then(|obj| obj.get("_headers"))
460 .and_then(|headers| headers.as_object())
461 .and_then(|headers_obj| headers_obj.get("authorization"))
462 .and_then(|auth_header| auth_header.as_str())
463 .and_then(|auth_str| {
464 if auth_str.starts_with("Bearer ") {
465 Some(&auth_str[7..]) } else {
467 None
468 }
469 })
470 .or_else(|| {
471 msg.payload.as_object()
473 .and_then(|obj| obj.get("auth_token"))
474 .and_then(|token| token.as_str())
475 });
476
477 let auth_token = auth_token.ok_or_else(|| {
478 tracing::warn!("❌ Authentication failed: Missing or invalid Authorization header");
479 rabbitmesh::error::RabbitMeshError::Handler("Authentication required: Missing Authorization header".to_string())
480 })?;
481
482 match validate_jwt_token(auth_token) {
484 Ok(claims) => {
485 tracing::debug!("✅ JWT authentication successful for user: {:?}",
486 claims.get("sub").or(claims.get("user_id")).or(claims.get("username")));
487
488 if let Ok(mut payload) = serde_json::from_value::<serde_json::Map<String, serde_json::Value>>(msg.payload.clone()) {
491 payload.insert("_auth_user".to_string(), serde_json::Value::Object(
492 claims.into_iter().collect::<serde_json::Map<String, serde_json::Value>>()
493 ));
494 }
496 }
497 Err(auth_error) => {
498 tracing::warn!("❌ JWT validation failed: {}", auth_error);
499 return Err(rabbitmesh::error::RabbitMeshError::Handler(format!("Authentication failed: {}", auth_error)));
500 }
501 }
502 });
503 }
504
505 if macro_attrs.iter().any(|attr| matches!(attr.as_str(), "require_role" | "require_permission" | "rbac" | "abac" | "authorize")) {
507 steps.push(quote! {
508 tracing::debug!("👮 Checking authorization");
509 });
511 }
512
513 if macro_attrs.contains(&"validate".to_string()) {
515 steps.push(quote! {
516 tracing::debug!("✅ Validating input");
517 if let Err(validation_error) = validate_input(&msg.payload) {
518 tracing::warn!("❌ Input validation failed: {}", validation_error);
519 return Err(rabbitmesh::error::RabbitMeshError::Handler(format!("Validation failed: {}", validation_error)));
520 }
521 tracing::debug!("✅ Input validation successful");
522 });
523 }
524
525 if macro_attrs.iter().any(|attr| attr.starts_with("rate_limit")) {
527 steps.push(quote! {
528 tracing::debug!("🚦 Checking rate limits");
529 let rate_limit_key = msg.payload.as_object()
531 .and_then(|obj| obj.get("_auth_user"))
532 .and_then(|user| user.as_object())
533 .and_then(|user_obj| user_obj.get("sub").or(user_obj.get("user_id")))
534 .and_then(|id| id.as_str())
535 .unwrap_or("anonymous");
536
537 if let Err(rate_limit_error) = check_rate_limit(&format!("{}:{}", rate_limit_key, #_method_name), 100, 60) {
539 tracing::warn!("❌ Rate limit exceeded for {}: {}", rate_limit_key, rate_limit_error);
540 return Err(rabbitmesh::error::RabbitMeshError::Handler(rate_limit_error));
541 }
542 tracing::debug!("✅ Rate limit check passed for {}", rate_limit_key);
543 });
544 }
545
546 if macro_attrs.iter().any(|attr| matches!(attr.as_str(), "cached" | "cache_read" | "redis_cache" | "memory_cache")) {
548 steps.push(quote! {
549 tracing::debug!("📦 Checking cache");
550 let payload_hash = msg.payload.to_string().len(); let cache_key = format!("{}:{}:{}", #_service_name, #_method_name, payload_hash);
553
554 if let Some(cached_result) = get_from_cache(&cache_key, 300) {
556 tracing::debug!("✅ Cache hit for {}", cache_key);
557 } else {
560 tracing::debug!("📦 Cache miss for {}", cache_key);
561 }
562 });
563 }
564
565 if macro_attrs.contains(&"transactional".to_string()) {
567 steps.push(quote! {
568 tracing::debug!("💾 Starting transaction");
569 audit_log(format!("Transaction started for {}::{}", #_service_name, #_method_name));
572 });
573 }
574
575 if macro_attrs.iter().any(|attr| matches!(attr.as_str(), "metrics" | "trace" | "monitor" | "prometheus")) {
577 steps.push(quote! {
578 tracing::debug!("📊 Recording request metrics");
579 let request_start = std::time::Instant::now();
580 record_metric(&format!("{}_{}_requests_total", #_service_name, #_method_name), 1);
581 record_metric(&format!("{}_{}_requests_active", #_service_name, #_method_name), 1);
582 });
583 }
584
585 quote! {
586 #(#steps)*
587 }
588}
589
590fn generate_postprocessing(_service_name: &str, _method_name: &str, macro_attrs: &[String]) -> proc_macro2::TokenStream {
592 let mut steps = Vec::new();
593
594 if macro_attrs.iter().any(|attr| matches!(attr.as_str(), "cached" | "cache_write" | "redis_cache" | "memory_cache")) {
596 steps.push(quote! {
597 tracing::debug!("📦 Updating cache");
598 let payload_hash = msg.payload.to_string().len(); let cache_key = format!("{}:{}:{}", #_service_name, #_method_name, payload_hash);
601
602 set_cache(&cache_key, serde_json::json!({
605 "cached_at": std::time::SystemTime::now().duration_since(std::time::UNIX_EPOCH).unwrap().as_secs(),
606 "method": #_method_name,
607 "service": #_service_name
608 }));
609 tracing::debug!("✅ Response cached for key: {}", cache_key);
610 });
611 }
612
613 if macro_attrs.contains(&"event_publish".to_string()) {
615 steps.push(quote! {
616 tracing::debug!("📤 Publishing events");
617 let event = serde_json::json!({
619 "event_type": format!("{}_{}_completed", #_service_name, #_method_name),
620 "timestamp": std::time::SystemTime::now().duration_since(std::time::UNIX_EPOCH).unwrap().as_secs(),
621 "service": #_service_name,
622 "method": #_method_name,
623 "payload": msg.payload
624 });
625 publish_event(event);
626 tracing::debug!("✅ Event published for {}::{}", #_service_name, #_method_name);
627 });
628 }
629
630 if macro_attrs.contains(&"audit_log".to_string()) {
632 steps.push(quote! {
633 tracing::debug!("📝 Recording audit log");
634 let user_id = msg.payload.as_object()
636 .and_then(|obj| obj.get("_auth_user"))
637 .and_then(|user| user.as_object())
638 .and_then(|user_obj| user_obj.get("sub").or(user_obj.get("user_id")))
639 .and_then(|id| id.as_str())
640 .unwrap_or("anonymous");
641
642 let audit_message = format!(
643 "User {} executed {}::{} with payload size {} bytes",
644 user_id, #_service_name, #_method_name, msg.payload.to_string().len()
645 );
646 audit_log(audit_message);
647 tracing::debug!("✅ Audit log recorded for user {}", user_id);
648 });
649 }
650
651 if macro_attrs.contains(&"batch_process".to_string()) {
653 steps.push(quote! {
654 tracing::debug!("📜 Adding to batch queue");
655 let batch_item = serde_json::json!({
656 "service": #_service_name,
657 "method": #_method_name,
658 "payload": msg.payload,
659 "timestamp": std::time::SystemTime::now().duration_since(std::time::UNIX_EPOCH).unwrap().as_secs()
660 });
661
662 if add_to_batch(batch_item) {
663 tracing::info!("🚀 Batch queue full, processing batch");
664 let batch = get_batch();
665 tracing::debug!("✅ Processing batch of {} items", batch.len());
666 }
668 });
669 }
670
671 if macro_attrs.iter().any(|attr| matches!(attr.as_str(), "metrics" | "trace" | "monitor")) {
673 steps.push(quote! {
674 tracing::debug!("📊 Recording response metrics");
675 record_metric(&format!("{}_{}_requests_completed", #_service_name, #_method_name), 1);
677 record_metric(&format!("{}_{}_requests_active", #_service_name, #_method_name), 0); tracing::debug!("✅ Metrics recorded for {}::{}", #_service_name, #_method_name);
684 });
685 }
686
687 if macro_attrs.contains(&"transactional".to_string()) {
689 steps.push(quote! {
690 tracing::debug!("💾 Committing transaction");
691 audit_log(format!("Transaction completed successfully for {}::{}", #_service_name, #_method_name));
694 tracing::debug!("✅ Transaction committed for {}::{}", #_service_name, #_method_name);
695 });
696 }
697
698 quote! {
699 #(#steps)*
700 }
701}
702
703
704fn is_universal_macro_attribute(attr: &str) -> bool {
706 matches!(attr,
707 "require_auth" | "jwt_auth" | "bearer_auth" | "api_key_auth" | "oauth" |
709 "require_role" | "require_permission" | "rbac" | "abac" | "authorize" |
710 "admin_only" | "user_only" | "owner_only" | "require_ownership" |
711
712 "validate" | "sanitize" | "escape" | "csrf_protect" | "xss_protect" |
714 "sql_injection_protect" | "input_filter" | "schema_validate" |
715
716 "rate_limit" | "throttle" | "circuit_breaker" | "bulkhead" |
718 "timeout" | "retry" | "fallback" |
719
720 "cached" | "cache_read" | "cache_write" | "cache_invalidate" |
722 "redis_cache" | "memory_cache" | "distributed_cache" | "cdn_cache" |
723 "compress" | "minify" | "optimize" |
724
725 "transactional" | "read_only" | "read_write" | "isolation_level" |
727 "connection_pool" | "query_cache" | "prepared_statement" |
728 "replica_read" | "master_write" | "shard" | "partition" |
729
730 "metrics" | "trace" | "monitor" | "log" | "audit_log" |
732 "prometheus" | "jaeger" | "datadog" | "new_relic" |
733 "alert" | "notify" | "dashboard" |
734
735 "event_publish" | "event_consume" | "message_queue" | "pub_sub" |
737 "webhook" | "callback" | "notification" | "email" | "sms" |
738
739 "streaming" | "websocket" | "sse" | "real_time" |
741 "batch_process" | "async_process" | "background_job" |
742
743 "state_machine" | "workflow" | "saga" | "orchestration" |
745 "approval" | "escalation" | "delegation" |
746 "event_sourcing" | "cqrs" | "snapshot" |
747
748 "rest" | "graphql" | "grpc" | "soap" | "json_rpc" |
750 "swagger" | "openapi" | "cors" | "jsonp" |
751 "api_version" | "deprecate" | "backward_compatible" |
752
753 "test" | "mock" | "stub" | "fixture" | "benchmark" |
755 "load_test" | "stress_test" | "integration_test" |
756 "coverage" | "profiling" | "memory_leak_detection"
757 )
758}
759
760#[proc_macro_attribute]
766pub fn require_auth(_args: TokenStream, input: TokenStream) -> TokenStream {
767 input }
769
770#[proc_macro_attribute]
772pub fn require_role(_args: TokenStream, input: TokenStream) -> TokenStream {
773 input }
775
776#[proc_macro_attribute]
778pub fn require_permission(_args: TokenStream, input: TokenStream) -> TokenStream {
779 input }
781
782#[proc_macro_attribute]
784pub fn require_ownership(_args: TokenStream, input: TokenStream) -> TokenStream {
785 input }
787
788#[proc_macro_attribute]
790pub fn validate(_args: TokenStream, input: TokenStream) -> TokenStream {
791 input }
793
794#[proc_macro_attribute]
796pub fn rate_limit(_args: TokenStream, input: TokenStream) -> TokenStream {
797 input }
799
800#[proc_macro_attribute]
802pub fn cached(_args: TokenStream, input: TokenStream) -> TokenStream {
803 input }
805
806#[proc_macro_attribute]
808pub fn transactional(_args: TokenStream, input: TokenStream) -> TokenStream {
809 input }
811
812#[proc_macro_attribute]
814pub fn metrics(_args: TokenStream, input: TokenStream) -> TokenStream {
815 input }
817
818#[proc_macro_attribute]
820pub fn audit_log(_args: TokenStream, input: TokenStream) -> TokenStream {
821 input }
823
824#[proc_macro_attribute]
826pub fn event_publish(_args: TokenStream, input: TokenStream) -> TokenStream {
827 input }
829
830#[proc_macro_attribute]
832pub fn streaming(_args: TokenStream, input: TokenStream) -> TokenStream {
833 input }
835
836#[proc_macro_attribute]
838pub fn batch_process(_args: TokenStream, input: TokenStream) -> TokenStream {
839 input }
841
842#[proc_macro_attribute] pub fn jwt_auth(_args: TokenStream, input: TokenStream) -> TokenStream { input }
844#[proc_macro_attribute] pub fn bearer_auth(_args: TokenStream, input: TokenStream) -> TokenStream { input }
845#[proc_macro_attribute] pub fn api_key_auth(_args: TokenStream, input: TokenStream) -> TokenStream { input }
846#[proc_macro_attribute] pub fn oauth(_args: TokenStream, input: TokenStream) -> TokenStream { input }
847#[proc_macro_attribute] pub fn rbac(_args: TokenStream, input: TokenStream) -> TokenStream { input }
848#[proc_macro_attribute] pub fn abac(_args: TokenStream, input: TokenStream) -> TokenStream { input }
849#[proc_macro_attribute] pub fn authorize(_args: TokenStream, input: TokenStream) -> TokenStream { input }
850#[proc_macro_attribute] pub fn admin_only(_args: TokenStream, input: TokenStream) -> TokenStream { input }
851#[proc_macro_attribute] pub fn user_only(_args: TokenStream, input: TokenStream) -> TokenStream { input }
852#[proc_macro_attribute] pub fn owner_only(_args: TokenStream, input: TokenStream) -> TokenStream { input }
853#[proc_macro_attribute] pub fn sanitize(_args: TokenStream, input: TokenStream) -> TokenStream { input }
854#[proc_macro_attribute] pub fn escape(_args: TokenStream, input: TokenStream) -> TokenStream { input }
855#[proc_macro_attribute] pub fn csrf_protect(_args: TokenStream, input: TokenStream) -> TokenStream { input }
856#[proc_macro_attribute] pub fn xss_protect(_args: TokenStream, input: TokenStream) -> TokenStream { input }
857#[proc_macro_attribute] pub fn throttle(_args: TokenStream, input: TokenStream) -> TokenStream { input }
858#[proc_macro_attribute] pub fn circuit_breaker(_args: TokenStream, input: TokenStream) -> TokenStream { input }
859#[proc_macro_attribute] pub fn timeout(_args: TokenStream, input: TokenStream) -> TokenStream { input }
860#[proc_macro_attribute] pub fn retry(_args: TokenStream, input: TokenStream) -> TokenStream { input }
861#[proc_macro_attribute] pub fn fallback(_args: TokenStream, input: TokenStream) -> TokenStream { input }
862#[proc_macro_attribute] pub fn redis_cache(_args: TokenStream, input: TokenStream) -> TokenStream { input }
863#[proc_macro_attribute] pub fn memory_cache(_args: TokenStream, input: TokenStream) -> TokenStream { input }
864#[proc_macro_attribute] pub fn read_only(_args: TokenStream, input: TokenStream) -> TokenStream { input }
865#[proc_macro_attribute] pub fn read_write(_args: TokenStream, input: TokenStream) -> TokenStream { input }
866#[proc_macro_attribute] pub fn trace(_args: TokenStream, input: TokenStream) -> TokenStream { input }
867#[proc_macro_attribute] pub fn monitor(_args: TokenStream, input: TokenStream) -> TokenStream { input }
868#[proc_macro_attribute] pub fn log(_args: TokenStream, input: TokenStream) -> TokenStream { input }
869#[proc_macro_attribute] pub fn prometheus(_args: TokenStream, input: TokenStream) -> TokenStream { input }
870#[proc_macro_attribute] pub fn websocket(_args: TokenStream, input: TokenStream) -> TokenStream { input }
871#[proc_macro_attribute] pub fn real_time(_args: TokenStream, input: TokenStream) -> TokenStream { input }
872#[proc_macro_attribute] pub fn async_process(_args: TokenStream, input: TokenStream) -> TokenStream { input }
873#[proc_macro_attribute] pub fn workflow(_args: TokenStream, input: TokenStream) -> TokenStream { input }
874#[proc_macro_attribute] pub fn state_machine(_args: TokenStream, input: TokenStream) -> TokenStream { input }
875#[proc_macro_attribute] pub fn saga(_args: TokenStream, input: TokenStream) -> TokenStream { input }
876#[proc_macro_attribute] pub fn event_sourcing(_args: TokenStream, input: TokenStream) -> TokenStream { input }
877#[proc_macro_attribute] pub fn cqrs(_args: TokenStream, input: TokenStream) -> TokenStream { input }