allframe_forge/
scaffolding.rs

1//! Project scaffolding utilities
2//!
3//! This module handles the creation of directories and files
4//! for new AllFrame projects following Clean Architecture principles.
5//!
6//! The scaffolding creates a complete project structure with:
7//! - Domain layer (business logic, no dependencies)
8//! - Application layer (use case orchestration)
9//! - Infrastructure layer (external implementations)
10//! - Presentation layer (HTTP/API handlers)
11//!
12//! ## Archetypes
13//!
14//! Different archetypes have different directory structures:
15//!
16//! ### Basic
17//! Simple Clean Architecture project with greeter example.
18//!
19//! ### Gateway
20//! API Gateway service with gRPC, including:
21//! - Protocol buffer definitions
22//! - HTTP client for external APIs
23//! - Rate limiting and caching
24//! - Authentication (HMAC, API Key, etc.)
25
26use std::{fs, path::Path};
27
28use anyhow::Result;
29
30use crate::config::ProjectConfig;
31use crate::templates::{self, acl, bff, consumer, gateway, producer, saga, scheduled, websocket};
32
33/// Create the Clean Architecture directory structure
34///
35/// Creates all necessary directories for a Clean Architecture project:
36/// - `src/` - Source code root
37/// - `src/domain/` - Domain layer (entities, repositories)
38/// - `src/application/` - Application layer (services)
39/// - `src/infrastructure/` - Infrastructure layer (repository implementations)
40/// - `src/presentation/` - Presentation layer (HTTP handlers)
41/// - `tests/` - Integration tests
42///
43/// # Arguments
44/// * `project_path` - Root path where the project directories will be created
45///
46/// # Errors
47/// Returns an error if any directory creation fails
48pub fn create_directory_structure(project_path: &Path) -> Result<()> {
49    let dirs = vec![
50        "src",
51        "src/domain",
52        "src/application",
53        "src/infrastructure",
54        "src/presentation",
55        "tests",
56    ];
57
58    for dir in dirs {
59        fs::create_dir_all(project_path.join(dir))?;
60    }
61
62    Ok(())
63}
64
65/// Generate all project files with Clean Architecture structure
66///
67/// Creates all necessary files for a complete AllFrame project:
68///
69/// ## Root Files
70/// - `Cargo.toml` - Project manifest with dependencies
71/// - `src/main.rs` - Application entry point with tokio runtime
72/// - `.gitignore` - Git ignore rules for Rust projects
73/// - `README.md` - Project documentation
74///
75/// ## Domain Layer
76/// - `src/domain/mod.rs` - Domain module exports
77/// - `src/domain/greeter.rs` - Greeter trait definition
78///
79/// ## Application Layer
80/// - `src/application/mod.rs` - Application module exports
81/// - `src/application/greeting_service.rs` - Greeting service
82///
83/// ## Infrastructure Layer
84/// - `src/infrastructure/mod.rs` - Infrastructure module exports
85/// - `src/infrastructure/console_greeter.rs` - Console greeter implementation
86///
87/// ## Presentation Layer
88/// - `src/presentation/mod.rs` - Presentation module (placeholder)
89///
90/// # Arguments
91/// * `project_path` - Root path where files will be created
92/// * `project_name` - Name of the project (used in Cargo.toml and README)
93///
94/// # Errors
95/// Returns an error if any file write operation fails
96pub fn generate_files(project_path: &Path, project_name: &str) -> Result<()> {
97    // Root files
98    fs::write(
99        project_path.join("Cargo.toml"),
100        templates::cargo_toml(project_name),
101    )?;
102    fs::write(project_path.join("src/main.rs"), templates::main_rs())?;
103    fs::write(project_path.join(".gitignore"), templates::gitignore())?;
104    fs::write(
105        project_path.join("README.md"),
106        templates::readme(project_name),
107    )?;
108
109    // Domain layer
110    fs::write(
111        project_path.join("src/domain/mod.rs"),
112        templates::domain_mod(),
113    )?;
114    fs::write(
115        project_path.join("src/domain/greeter.rs"),
116        templates::domain_greeter(),
117    )?;
118
119    // Application layer
120    fs::write(
121        project_path.join("src/application/mod.rs"),
122        templates::application_mod(),
123    )?;
124    fs::write(
125        project_path.join("src/application/greeting_service.rs"),
126        templates::application_greeting_service(),
127    )?;
128
129    // Infrastructure layer
130    fs::write(
131        project_path.join("src/infrastructure/mod.rs"),
132        templates::infrastructure_mod(),
133    )?;
134    fs::write(
135        project_path.join("src/infrastructure/console_greeter.rs"),
136        templates::infrastructure_console_greeter(),
137    )?;
138
139    // Presentation layer
140    fs::write(
141        project_path.join("src/presentation/mod.rs"),
142        templates::presentation_mod(),
143    )?;
144
145    Ok(())
146}
147
148/// Create the Gateway Architecture directory structure
149///
150/// Creates all necessary directories for a Gateway service:
151/// - `src/` - Source code root
152/// - `src/domain/` - Domain layer (entities, repository traits)
153/// - `src/application/` - Application layer (services, use cases)
154/// - `src/infrastructure/` - Infrastructure layer (HTTP client, cache, auth)
155/// - `src/presentation/` - Presentation layer (gRPC handlers)
156/// - `proto/` - Protocol buffer definitions
157/// - `tests/` - Integration tests
158///
159/// # Arguments
160/// * `project_path` - Root path where the project directories will be created
161///
162/// # Errors
163/// Returns an error if any directory creation fails
164pub fn create_gateway_structure(project_path: &Path) -> Result<()> {
165    let dirs = vec![
166        "src",
167        "src/domain",
168        "src/application",
169        "src/infrastructure",
170        "src/presentation",
171        "proto",
172        "tests",
173    ];
174
175    for dir in dirs {
176        fs::create_dir_all(project_path.join(dir))?;
177    }
178
179    Ok(())
180}
181
182/// Generate all gateway project files
183///
184/// Creates all necessary files for a complete Gateway service:
185///
186/// ## Root Files
187/// - `Cargo.toml` - Project manifest with gateway dependencies
188/// - `build.rs` - Proto compilation build script
189/// - `src/main.rs` - Application entry point with gRPC server
190/// - `README.md` - Project documentation
191/// - `Dockerfile` - Container build file
192/// - `.gitignore` - Git ignore rules
193///
194/// ## Protocol Buffers
195/// - `proto/{service}.proto` - gRPC service definition
196///
197/// ## Domain Layer
198/// - `src/domain/mod.rs` - Domain module exports
199/// - `src/domain/entities.rs` - Domain entities
200/// - `src/domain/repository.rs` - Repository trait
201///
202/// ## Application Layer
203/// - `src/application/mod.rs` - Application module exports
204/// - `src/application/service.rs` - Gateway service implementation
205///
206/// ## Infrastructure Layer
207/// - `src/infrastructure/mod.rs` - Infrastructure module exports
208/// - `src/infrastructure/http_client.rs` - External API HTTP client
209/// - `src/infrastructure/auth.rs` - Authentication implementations
210/// - `src/infrastructure/cache.rs` - Caching implementation
211/// - `src/infrastructure/rate_limiter.rs` - Rate limiting
212///
213/// ## Presentation Layer
214/// - `src/presentation/mod.rs` - Presentation module exports
215/// - `src/presentation/grpc.rs` - gRPC service handlers
216///
217/// ## Configuration
218/// - `src/config.rs` - Service configuration
219/// - `src/error.rs` - Error types
220///
221/// # Arguments
222/// * `project_path` - Root path where files will be created
223/// * `config` - Project configuration
224///
225/// # Errors
226/// Returns an error if any file write operation fails
227pub fn generate_gateway_files(project_path: &Path, config: &ProjectConfig) -> Result<()> {
228    // Root files
229    fs::write(
230        project_path.join("Cargo.toml"),
231        gateway::cargo_toml(config),
232    )?;
233    fs::write(project_path.join("build.rs"), gateway::build_rs(config))?;
234    fs::write(project_path.join("src/main.rs"), gateway::main_rs(config))?;
235    fs::write(project_path.join(".gitignore"), templates::gitignore())?;
236    fs::write(project_path.join("README.md"), gateway::readme(config))?;
237    fs::write(project_path.join("Dockerfile"), gateway::dockerfile(config))?;
238
239    // Protocol buffers
240    let gateway_config = config.gateway.as_ref().expect("Gateway config required");
241    fs::write(
242        project_path.join(format!("proto/{}.proto", gateway_config.service_name)),
243        gateway::proto_file(config),
244    )?;
245
246    // Configuration files
247    fs::write(project_path.join("src/config.rs"), gateway::config_rs(config))?;
248    fs::write(project_path.join("src/error.rs"), gateway::error_rs(config))?;
249
250    // Domain layer
251    fs::write(
252        project_path.join("src/domain/mod.rs"),
253        gateway::domain_mod(config),
254    )?;
255    fs::write(
256        project_path.join("src/domain/entities.rs"),
257        gateway::domain_entities(config),
258    )?;
259    fs::write(
260        project_path.join("src/domain/repository.rs"),
261        gateway::domain_repository(config),
262    )?;
263
264    // Application layer
265    fs::write(
266        project_path.join("src/application/mod.rs"),
267        gateway::application_mod(config),
268    )?;
269    fs::write(
270        project_path.join("src/application/service.rs"),
271        gateway::application_service(config),
272    )?;
273
274    // Infrastructure layer
275    fs::write(
276        project_path.join("src/infrastructure/mod.rs"),
277        gateway::infrastructure_mod(config),
278    )?;
279    fs::write(
280        project_path.join("src/infrastructure/http_client.rs"),
281        gateway::infrastructure_http_client(config),
282    )?;
283    fs::write(
284        project_path.join("src/infrastructure/auth.rs"),
285        gateway::infrastructure_auth(config),
286    )?;
287    fs::write(
288        project_path.join("src/infrastructure/cache.rs"),
289        gateway::infrastructure_cache(config),
290    )?;
291    fs::write(
292        project_path.join("src/infrastructure/rate_limiter.rs"),
293        gateway::infrastructure_rate_limiter(config),
294    )?;
295
296    // Presentation layer
297    fs::write(
298        project_path.join("src/presentation/mod.rs"),
299        gateway::presentation_mod(config),
300    )?;
301    fs::write(
302        project_path.join("src/presentation/grpc.rs"),
303        gateway::presentation_grpc(config),
304    )?;
305
306    Ok(())
307}
308
309/// Create the Consumer Architecture directory structure
310///
311/// Creates all necessary directories for a Consumer (event handler) service:
312/// - `src/` - Source code root
313/// - `src/domain/` - Domain layer (events, handlers)
314/// - `src/application/` - Application layer (consumer orchestration)
315/// - `src/infrastructure/` - Infrastructure layer (broker, idempotency, health)
316/// - `tests/` - Integration tests
317///
318/// # Arguments
319/// * `project_path` - Root path where the project directories will be created
320///
321/// # Errors
322/// Returns an error if any directory creation fails
323pub fn create_consumer_structure(project_path: &Path) -> Result<()> {
324    let dirs = vec![
325        "src",
326        "src/domain",
327        "src/application",
328        "src/infrastructure",
329        "tests",
330    ];
331
332    for dir in dirs {
333        fs::create_dir_all(project_path.join(dir))?;
334    }
335
336    Ok(())
337}
338
339/// Generate all consumer project files
340///
341/// Creates all necessary files for a complete Consumer service:
342///
343/// ## Root Files
344/// - `Cargo.toml` - Project manifest with consumer dependencies
345/// - `src/main.rs` - Application entry point with consumer setup
346/// - `README.md` - Project documentation
347/// - `Dockerfile` - Container build file
348/// - `.gitignore` - Git ignore rules
349///
350/// ## Domain Layer
351/// - `src/domain/mod.rs` - Domain module exports
352/// - `src/domain/events.rs` - Event definitions with envelope pattern
353/// - `src/domain/handlers.rs` - Event handler traits and registry
354///
355/// ## Application Layer
356/// - `src/application/mod.rs` - Application module exports
357/// - `src/application/consumer.rs` - Consumer orchestration with retry/idempotency
358///
359/// ## Infrastructure Layer
360/// - `src/infrastructure/mod.rs` - Infrastructure module exports
361/// - `src/infrastructure/broker.rs` - Message broker implementation (Kafka)
362/// - `src/infrastructure/idempotency.rs` - Idempotency store
363/// - `src/infrastructure/health.rs` - Health check server
364///
365/// ## Configuration
366/// - `src/config.rs` - Service configuration
367/// - `src/error.rs` - Error types
368///
369/// # Arguments
370/// * `project_path` - Root path where files will be created
371/// * `config` - Project configuration
372///
373/// # Errors
374/// Returns an error if any file write operation fails
375pub fn generate_consumer_files(project_path: &Path, config: &ProjectConfig) -> Result<()> {
376    // Root files
377    fs::write(
378        project_path.join("Cargo.toml"),
379        consumer::cargo_toml(config),
380    )?;
381    fs::write(project_path.join("src/main.rs"), consumer::main_rs(config))?;
382    fs::write(project_path.join(".gitignore"), templates::gitignore())?;
383    fs::write(project_path.join("README.md"), consumer::readme(config))?;
384    fs::write(project_path.join("Dockerfile"), consumer::dockerfile(config))?;
385
386    // Configuration files
387    fs::write(
388        project_path.join("src/config.rs"),
389        consumer::config_rs(config),
390    )?;
391    fs::write(project_path.join("src/error.rs"), consumer::error_rs(config))?;
392
393    // Domain layer
394    fs::write(
395        project_path.join("src/domain/mod.rs"),
396        consumer::domain_mod(config),
397    )?;
398    fs::write(
399        project_path.join("src/domain/events.rs"),
400        consumer::domain_events(config),
401    )?;
402    fs::write(
403        project_path.join("src/domain/handlers.rs"),
404        consumer::domain_handlers(config),
405    )?;
406
407    // Application layer
408    fs::write(
409        project_path.join("src/application/mod.rs"),
410        consumer::application_mod(config),
411    )?;
412    fs::write(
413        project_path.join("src/application/consumer.rs"),
414        consumer::application_consumer(config),
415    )?;
416
417    // Infrastructure layer
418    fs::write(
419        project_path.join("src/infrastructure/mod.rs"),
420        consumer::infrastructure_mod(config),
421    )?;
422    fs::write(
423        project_path.join("src/infrastructure/broker.rs"),
424        consumer::infrastructure_broker(config),
425    )?;
426    fs::write(
427        project_path.join("src/infrastructure/idempotency.rs"),
428        consumer::infrastructure_idempotency(config),
429    )?;
430    fs::write(
431        project_path.join("src/infrastructure/health.rs"),
432        consumer::infrastructure_health(config),
433    )?;
434
435    Ok(())
436}
437
438/// Create the Producer Architecture directory structure
439///
440/// Creates all necessary directories for a Producer (event publisher) service:
441/// - `src/` - Source code root
442/// - `src/domain/` - Domain layer (entities, events, repository)
443/// - `src/application/` - Application layer (service, outbox)
444/// - `src/infrastructure/` - Infrastructure layer (repository, outbox, publisher)
445/// - `src/presentation/` - Presentation layer (HTTP handlers)
446/// - `tests/` - Integration tests
447///
448/// # Arguments
449/// * `project_path` - Root path where the project directories will be created
450///
451/// # Errors
452/// Returns an error if any directory creation fails
453pub fn create_producer_structure(project_path: &Path) -> Result<()> {
454    let dirs = vec![
455        "src",
456        "src/domain",
457        "src/application",
458        "src/infrastructure",
459        "src/presentation",
460        "tests",
461    ];
462
463    for dir in dirs {
464        fs::create_dir_all(project_path.join(dir))?;
465    }
466
467    Ok(())
468}
469
470/// Generate all producer project files
471///
472/// Creates all necessary files for a complete Producer service:
473///
474/// ## Root Files
475/// - `Cargo.toml` - Project manifest with producer dependencies
476/// - `src/main.rs` - Application entry point with API server and outbox processor
477/// - `README.md` - Project documentation
478/// - `Dockerfile` - Container build file
479/// - `.gitignore` - Git ignore rules
480///
481/// ## Domain Layer
482/// - `src/domain/mod.rs` - Domain module exports
483/// - `src/domain/entities.rs` - Domain entities
484/// - `src/domain/events.rs` - Event definitions with envelope pattern
485/// - `src/domain/repository.rs` - Repository trait
486///
487/// ## Application Layer
488/// - `src/application/mod.rs` - Application module exports
489/// - `src/application/service.rs` - Application service with event publishing
490/// - `src/application/outbox.rs` - Outbox trait
491///
492/// ## Infrastructure Layer
493/// - `src/infrastructure/mod.rs` - Infrastructure module exports
494/// - `src/infrastructure/repository.rs` - PostgreSQL repository
495/// - `src/infrastructure/outbox.rs` - PostgreSQL outbox
496/// - `src/infrastructure/publisher.rs` - Kafka event publisher
497/// - `src/infrastructure/outbox_processor.rs` - Outbox processor
498/// - `src/infrastructure/health.rs` - Health check server
499///
500/// ## Presentation Layer
501/// - `src/presentation/mod.rs` - Presentation module exports
502/// - `src/presentation/handlers.rs` - HTTP API handlers
503///
504/// ## Configuration
505/// - `src/config.rs` - Service configuration
506/// - `src/error.rs` - Error types
507///
508/// # Arguments
509/// * `project_path` - Root path where files will be created
510/// * `config` - Project configuration
511///
512/// # Errors
513/// Returns an error if any file write operation fails
514pub fn generate_producer_files(project_path: &Path, config: &ProjectConfig) -> Result<()> {
515    // Root files
516    fs::write(
517        project_path.join("Cargo.toml"),
518        producer::cargo_toml(config),
519    )?;
520    fs::write(project_path.join("src/main.rs"), producer::main_rs(config))?;
521    fs::write(project_path.join(".gitignore"), templates::gitignore())?;
522    fs::write(project_path.join("README.md"), producer::readme(config))?;
523    fs::write(project_path.join("Dockerfile"), producer::dockerfile(config))?;
524
525    // Configuration files
526    fs::write(
527        project_path.join("src/config.rs"),
528        producer::config_rs(config),
529    )?;
530    fs::write(project_path.join("src/error.rs"), producer::error_rs(config))?;
531
532    // Domain layer
533    fs::write(
534        project_path.join("src/domain/mod.rs"),
535        producer::domain_mod(config),
536    )?;
537    fs::write(
538        project_path.join("src/domain/entities.rs"),
539        producer::domain_entities(config),
540    )?;
541    fs::write(
542        project_path.join("src/domain/events.rs"),
543        producer::domain_events(config),
544    )?;
545    fs::write(
546        project_path.join("src/domain/repository.rs"),
547        producer::domain_repository(config),
548    )?;
549
550    // Application layer
551    fs::write(
552        project_path.join("src/application/mod.rs"),
553        producer::application_mod(config),
554    )?;
555    fs::write(
556        project_path.join("src/application/service.rs"),
557        producer::application_service(config),
558    )?;
559    fs::write(
560        project_path.join("src/application/outbox.rs"),
561        producer::application_outbox(config),
562    )?;
563
564    // Infrastructure layer
565    fs::write(
566        project_path.join("src/infrastructure/mod.rs"),
567        producer::infrastructure_mod(config),
568    )?;
569    fs::write(
570        project_path.join("src/infrastructure/repository.rs"),
571        producer::infrastructure_repository(config),
572    )?;
573    fs::write(
574        project_path.join("src/infrastructure/outbox.rs"),
575        producer::infrastructure_outbox(config),
576    )?;
577    fs::write(
578        project_path.join("src/infrastructure/publisher.rs"),
579        producer::infrastructure_publisher(config),
580    )?;
581    fs::write(
582        project_path.join("src/infrastructure/outbox_processor.rs"),
583        producer::infrastructure_outbox_processor(config),
584    )?;
585    fs::write(
586        project_path.join("src/infrastructure/health.rs"),
587        producer::infrastructure_health(config),
588    )?;
589
590    // Presentation layer
591    fs::write(
592        project_path.join("src/presentation/mod.rs"),
593        producer::presentation_mod(config),
594    )?;
595    fs::write(
596        project_path.join("src/presentation/handlers.rs"),
597        producer::presentation_handlers(config),
598    )?;
599
600    Ok(())
601}
602
603/// Create the BFF (Backend for Frontend) Architecture directory structure
604///
605/// Creates all necessary directories for a BFF service:
606/// - `src/` - Source code root
607/// - `src/domain/` - Domain layer (models, aggregates)
608/// - `src/application/` - Application layer (aggregator service)
609/// - `src/infrastructure/` - Infrastructure layer (clients, cache, health)
610/// - `src/presentation/` - Presentation layer (REST handlers, GraphQL)
611/// - `tests/` - Integration tests
612///
613/// # Arguments
614/// * `project_path` - Root path where the project directories will be created
615///
616/// # Errors
617/// Returns an error if any directory creation fails
618pub fn create_bff_structure(project_path: &Path) -> Result<()> {
619    let dirs = vec![
620        "src",
621        "src/domain",
622        "src/application",
623        "src/infrastructure",
624        "src/presentation",
625        "tests",
626    ];
627
628    for dir in dirs {
629        fs::create_dir_all(project_path.join(dir))?;
630    }
631
632    Ok(())
633}
634
635/// Generate all BFF project files
636///
637/// Creates all necessary files for a complete BFF service:
638///
639/// ## Root Files
640/// - `Cargo.toml` - Project manifest with BFF dependencies
641/// - `src/main.rs` - Application entry point with API server
642/// - `README.md` - Project documentation
643/// - `Dockerfile` - Container build file
644/// - `.gitignore` - Git ignore rules
645///
646/// ## Domain Layer
647/// - `src/domain/mod.rs` - Domain module exports
648/// - `src/domain/models.rs` - Domain models
649/// - `src/domain/aggregates.rs` - Aggregate types for frontend views
650///
651/// ## Application Layer
652/// - `src/application/mod.rs` - Application module exports
653/// - `src/application/aggregator.rs` - Aggregator service
654///
655/// ## Infrastructure Layer
656/// - `src/infrastructure/mod.rs` - Infrastructure module exports
657/// - `src/infrastructure/clients.rs` - Backend HTTP clients
658/// - `src/infrastructure/cache.rs` - Cache service
659/// - `src/infrastructure/health.rs` - Health check server
660///
661/// ## Presentation Layer
662/// - `src/presentation/mod.rs` - Presentation module exports
663/// - `src/presentation/handlers.rs` - REST API handlers
664/// - `src/presentation/graphql.rs` - GraphQL API (if enabled)
665///
666/// ## Configuration
667/// - `src/config.rs` - Service configuration
668/// - `src/error.rs` - Error types
669///
670/// # Arguments
671/// * `project_path` - Root path where files will be created
672/// * `config` - Project configuration
673///
674/// # Errors
675/// Returns an error if any file write operation fails
676pub fn generate_bff_files(project_path: &Path, config: &ProjectConfig) -> Result<()> {
677    let bff_config = config.bff.as_ref().expect("BFF config required");
678
679    // Root files
680    fs::write(project_path.join("Cargo.toml"), bff::cargo_toml(config))?;
681    fs::write(project_path.join("src/main.rs"), bff::main_rs(config))?;
682    fs::write(project_path.join(".gitignore"), templates::gitignore())?;
683    fs::write(project_path.join("README.md"), bff::readme(config))?;
684    fs::write(project_path.join("Dockerfile"), bff::dockerfile(config))?;
685
686    // Configuration files
687    fs::write(project_path.join("src/config.rs"), bff::config_rs(config))?;
688    fs::write(project_path.join("src/error.rs"), bff::error_rs(config))?;
689
690    // Domain layer
691    fs::write(
692        project_path.join("src/domain/mod.rs"),
693        bff::domain_mod(config),
694    )?;
695    fs::write(
696        project_path.join("src/domain/models.rs"),
697        bff::domain_models(config),
698    )?;
699    fs::write(
700        project_path.join("src/domain/aggregates.rs"),
701        bff::domain_aggregates(config),
702    )?;
703
704    // Application layer
705    fs::write(
706        project_path.join("src/application/mod.rs"),
707        bff::application_mod(config),
708    )?;
709    fs::write(
710        project_path.join("src/application/aggregator.rs"),
711        bff::application_aggregator(config),
712    )?;
713
714    // Infrastructure layer
715    fs::write(
716        project_path.join("src/infrastructure/mod.rs"),
717        bff::infrastructure_mod(config),
718    )?;
719    fs::write(
720        project_path.join("src/infrastructure/clients.rs"),
721        bff::infrastructure_clients(config),
722    )?;
723    fs::write(
724        project_path.join("src/infrastructure/cache.rs"),
725        bff::infrastructure_cache(config),
726    )?;
727    fs::write(
728        project_path.join("src/infrastructure/health.rs"),
729        bff::infrastructure_health(config),
730    )?;
731
732    // Presentation layer
733    fs::write(
734        project_path.join("src/presentation/mod.rs"),
735        bff::presentation_mod(config),
736    )?;
737    fs::write(
738        project_path.join("src/presentation/handlers.rs"),
739        bff::presentation_handlers(config),
740    )?;
741
742    // GraphQL (if enabled)
743    if bff_config.graphql_enabled {
744        fs::write(
745            project_path.join("src/presentation/graphql.rs"),
746            bff::presentation_graphql(config),
747        )?;
748    }
749
750    Ok(())
751}
752
753/// Create the Scheduled Jobs Architecture directory structure
754///
755/// Creates all necessary directories for a Scheduled Jobs service:
756/// - `src/` - Source code root
757/// - `src/domain/` - Domain layer (job definitions)
758/// - `src/application/` - Application layer (scheduler)
759/// - `src/infrastructure/` - Infrastructure layer (health checks)
760/// - `tests/` - Integration tests
761///
762/// # Arguments
763/// * `project_path` - Root path where the project directories will be created
764///
765/// # Errors
766/// Returns an error if any directory creation fails
767pub fn create_scheduled_structure(project_path: &Path) -> Result<()> {
768    let dirs = vec![
769        "src",
770        "src/domain",
771        "src/application",
772        "src/infrastructure",
773        "tests",
774    ];
775
776    for dir in dirs {
777        fs::create_dir_all(project_path.join(dir))?;
778    }
779
780    Ok(())
781}
782
783/// Generate all scheduled jobs project files
784///
785/// Creates all necessary files for a complete Scheduled Jobs service:
786///
787/// ## Root Files
788/// - `Cargo.toml` - Project manifest with scheduler dependencies
789/// - `src/main.rs` - Application entry point with scheduler setup
790/// - `README.md` - Project documentation
791/// - `Dockerfile` - Container build file
792/// - `.gitignore` - Git ignore rules
793///
794/// ## Domain Layer
795/// - `src/domain/mod.rs` - Domain module exports
796/// - `src/domain/jobs.rs` - Job trait and context definitions
797///
798/// ## Application Layer
799/// - `src/application/mod.rs` - Application module exports
800/// - `src/application/scheduler.rs` - Job scheduler and job implementations
801///
802/// ## Infrastructure Layer
803/// - `src/infrastructure/mod.rs` - Infrastructure module exports
804/// - `src/infrastructure/health.rs` - Health check server
805///
806/// ## Configuration
807/// - `src/config.rs` - Service configuration
808/// - `src/error.rs` - Error types
809///
810/// # Arguments
811/// * `project_path` - Root path where files will be created
812/// * `config` - Project configuration
813///
814/// # Errors
815/// Returns an error if any file write operation fails
816pub fn generate_scheduled_files(project_path: &Path, config: &ProjectConfig) -> Result<()> {
817    // Root files
818    fs::write(
819        project_path.join("Cargo.toml"),
820        scheduled::cargo_toml(config),
821    )?;
822    fs::write(project_path.join("src/main.rs"), scheduled::main_rs(config))?;
823    fs::write(project_path.join(".gitignore"), templates::gitignore())?;
824    fs::write(project_path.join("README.md"), scheduled::readme(config))?;
825    fs::write(project_path.join("Dockerfile"), scheduled::dockerfile(config))?;
826
827    // Configuration files
828    fs::write(
829        project_path.join("src/config.rs"),
830        scheduled::config_rs(config),
831    )?;
832    fs::write(project_path.join("src/error.rs"), scheduled::error_rs(config))?;
833
834    // Domain layer
835    fs::write(
836        project_path.join("src/domain/mod.rs"),
837        scheduled::domain_mod(config),
838    )?;
839    fs::write(
840        project_path.join("src/domain/jobs.rs"),
841        scheduled::domain_jobs(config),
842    )?;
843
844    // Application layer
845    fs::write(
846        project_path.join("src/application/mod.rs"),
847        scheduled::application_mod(config),
848    )?;
849    fs::write(
850        project_path.join("src/application/scheduler.rs"),
851        scheduled::application_scheduler(config),
852    )?;
853
854    // Infrastructure layer
855    fs::write(
856        project_path.join("src/infrastructure/mod.rs"),
857        scheduled::infrastructure_mod(config),
858    )?;
859    fs::write(
860        project_path.join("src/infrastructure/health.rs"),
861        scheduled::infrastructure_health(config),
862    )?;
863
864    Ok(())
865}
866
867/// Create the WebSocket Gateway Architecture directory structure
868///
869/// Creates all necessary directories for a WebSocket Gateway service:
870/// - `src/` - Source code root
871/// - `src/domain/` - Domain layer (messages, connections)
872/// - `src/application/` - Application layer (hub)
873/// - `src/infrastructure/` - Infrastructure layer (health checks)
874/// - `src/presentation/` - Presentation layer (WebSocket handlers)
875/// - `tests/` - Integration tests
876///
877/// # Arguments
878/// * `project_path` - Root path where the project directories will be created
879///
880/// # Errors
881/// Returns an error if any directory creation fails
882pub fn create_websocket_structure(project_path: &Path) -> Result<()> {
883    let dirs = vec![
884        "src",
885        "src/domain",
886        "src/application",
887        "src/infrastructure",
888        "src/presentation",
889        "tests",
890    ];
891
892    for dir in dirs {
893        fs::create_dir_all(project_path.join(dir))?;
894    }
895
896    Ok(())
897}
898
899/// Generate all WebSocket Gateway project files
900///
901/// Creates all necessary files for a complete WebSocket Gateway service:
902///
903/// ## Root Files
904/// - `Cargo.toml` - Project manifest with WebSocket dependencies
905/// - `src/main.rs` - Application entry point with WebSocket server
906/// - `README.md` - Project documentation
907/// - `Dockerfile` - Container build file
908/// - `.gitignore` - Git ignore rules
909///
910/// ## Domain Layer
911/// - `src/domain/mod.rs` - Domain module exports
912/// - `src/domain/messages.rs` - WebSocket message types
913/// - `src/domain/connection.rs` - Connection management
914///
915/// ## Application Layer
916/// - `src/application/mod.rs` - Application module exports
917/// - `src/application/hub.rs` - WebSocket hub
918///
919/// ## Infrastructure Layer
920/// - `src/infrastructure/mod.rs` - Infrastructure module exports
921/// - `src/infrastructure/health.rs` - Health check server
922///
923/// ## Presentation Layer
924/// - `src/presentation/mod.rs` - Presentation module exports
925/// - `src/presentation/handlers.rs` - WebSocket handlers
926///
927/// ## Configuration
928/// - `src/config.rs` - Service configuration
929/// - `src/error.rs` - Error types
930///
931/// # Arguments
932/// * `project_path` - Root path where files will be created
933/// * `config` - Project configuration
934///
935/// # Errors
936/// Returns an error if any file write operation fails
937pub fn generate_websocket_files(project_path: &Path, config: &ProjectConfig) -> Result<()> {
938    // Root files
939    fs::write(
940        project_path.join("Cargo.toml"),
941        websocket::cargo_toml(config),
942    )?;
943    fs::write(project_path.join("src/main.rs"), websocket::main_rs(config))?;
944    fs::write(project_path.join(".gitignore"), templates::gitignore())?;
945    fs::write(project_path.join("README.md"), websocket::readme(config))?;
946    fs::write(project_path.join("Dockerfile"), websocket::dockerfile(config))?;
947
948    // Configuration files
949    fs::write(
950        project_path.join("src/config.rs"),
951        websocket::config_rs(config),
952    )?;
953    fs::write(project_path.join("src/error.rs"), websocket::error_rs(config))?;
954
955    // Domain layer
956    fs::write(
957        project_path.join("src/domain/mod.rs"),
958        websocket::domain_mod(config),
959    )?;
960    fs::write(
961        project_path.join("src/domain/messages.rs"),
962        websocket::domain_messages(config),
963    )?;
964    fs::write(
965        project_path.join("src/domain/connection.rs"),
966        websocket::domain_connection(config),
967    )?;
968
969    // Application layer
970    fs::write(
971        project_path.join("src/application/mod.rs"),
972        websocket::application_mod(config),
973    )?;
974    fs::write(
975        project_path.join("src/application/hub.rs"),
976        websocket::application_hub(config),
977    )?;
978
979    // Infrastructure layer
980    fs::write(
981        project_path.join("src/infrastructure/mod.rs"),
982        websocket::infrastructure_mod(config),
983    )?;
984    fs::write(
985        project_path.join("src/infrastructure/health.rs"),
986        websocket::infrastructure_health(config),
987    )?;
988
989    // Presentation layer
990    fs::write(
991        project_path.join("src/presentation/mod.rs"),
992        websocket::presentation_mod(config),
993    )?;
994    fs::write(
995        project_path.join("src/presentation/handlers.rs"),
996        websocket::presentation_handlers(config),
997    )?;
998
999    Ok(())
1000}
1001
1002/// Create the Saga Orchestrator Architecture directory structure
1003pub fn create_saga_structure(project_path: &Path) -> Result<()> {
1004    let dirs = vec![
1005        "src",
1006        "src/domain",
1007        "src/application",
1008        "src/infrastructure",
1009        "src/presentation",
1010        "tests",
1011    ];
1012
1013    for dir in dirs {
1014        fs::create_dir_all(project_path.join(dir))?;
1015    }
1016
1017    Ok(())
1018}
1019
1020/// Generate all Saga Orchestrator project files
1021pub fn generate_saga_files(project_path: &Path, config: &ProjectConfig) -> Result<()> {
1022    // Root files
1023    fs::write(project_path.join("Cargo.toml"), saga::cargo_toml(config))?;
1024    fs::write(project_path.join("src/main.rs"), saga::main_rs(config))?;
1025    fs::write(project_path.join(".gitignore"), templates::gitignore())?;
1026    fs::write(project_path.join("README.md"), saga::readme(config))?;
1027    fs::write(project_path.join("Dockerfile"), saga::dockerfile(config))?;
1028
1029    // Configuration files
1030    fs::write(project_path.join("src/config.rs"), saga::config_rs(config))?;
1031    fs::write(project_path.join("src/error.rs"), saga::error_rs(config))?;
1032
1033    // Domain layer
1034    fs::write(
1035        project_path.join("src/domain/mod.rs"),
1036        saga::domain_mod(config),
1037    )?;
1038    fs::write(
1039        project_path.join("src/domain/saga.rs"),
1040        saga::domain_saga(config),
1041    )?;
1042    fs::write(
1043        project_path.join("src/domain/step.rs"),
1044        saga::domain_step(config),
1045    )?;
1046
1047    // Application layer
1048    fs::write(
1049        project_path.join("src/application/mod.rs"),
1050        saga::application_mod(config),
1051    )?;
1052    fs::write(
1053        project_path.join("src/application/orchestrator.rs"),
1054        saga::application_orchestrator(config),
1055    )?;
1056    fs::write(
1057        project_path.join("src/application/steps.rs"),
1058        saga::application_steps(config),
1059    )?;
1060
1061    // Infrastructure layer
1062    fs::write(
1063        project_path.join("src/infrastructure/mod.rs"),
1064        saga::infrastructure_mod(config),
1065    )?;
1066    fs::write(
1067        project_path.join("src/infrastructure/health.rs"),
1068        saga::infrastructure_health(config),
1069    )?;
1070
1071    // Presentation layer
1072    fs::write(
1073        project_path.join("src/presentation/mod.rs"),
1074        saga::presentation_mod(config),
1075    )?;
1076    fs::write(
1077        project_path.join("src/presentation/handlers.rs"),
1078        saga::presentation_handlers(config),
1079    )?;
1080
1081    Ok(())
1082}
1083
1084/// Create the Anti-Corruption Layer Architecture directory structure
1085///
1086/// Creates all necessary directories for an ACL service:
1087/// - `src/` - Source code root
1088/// - `src/domain/` - Domain layer (legacy models, modern models, transformer traits)
1089/// - `src/application/` - Application layer (translator service)
1090/// - `src/infrastructure/` - Infrastructure layer (legacy client, health checks)
1091/// - `src/presentation/` - Presentation layer (HTTP handlers)
1092/// - `tests/` - Integration tests
1093///
1094/// # Arguments
1095/// * `project_path` - Root path where the project directories will be created
1096///
1097/// # Errors
1098/// Returns an error if any directory creation fails
1099pub fn create_acl_structure(project_path: &Path) -> Result<()> {
1100    let dirs = vec![
1101        "src",
1102        "src/domain",
1103        "src/application",
1104        "src/infrastructure",
1105        "src/presentation",
1106        "tests",
1107    ];
1108
1109    for dir in dirs {
1110        fs::create_dir_all(project_path.join(dir))?;
1111    }
1112
1113    Ok(())
1114}
1115
1116/// Generate all Anti-Corruption Layer project files
1117///
1118/// Creates all necessary files for a complete ACL service:
1119///
1120/// ## Root Files
1121/// - `Cargo.toml` - Project manifest with ACL dependencies
1122/// - `src/main.rs` - Application entry point with HTTP server
1123/// - `README.md` - Project documentation
1124/// - `Dockerfile` - Container build file
1125/// - `.gitignore` - Git ignore rules
1126///
1127/// ## Domain Layer
1128/// - `src/domain/mod.rs` - Domain module exports
1129/// - `src/domain/legacy.rs` - Legacy system models
1130/// - `src/domain/modern.rs` - Modern domain models
1131/// - `src/domain/transformer.rs` - Transformer trait for bidirectional conversion
1132///
1133/// ## Application Layer
1134/// - `src/application/mod.rs` - Application module exports
1135/// - `src/application/translator.rs` - Translation service
1136///
1137/// ## Infrastructure Layer
1138/// - `src/infrastructure/mod.rs` - Infrastructure module exports
1139/// - `src/infrastructure/legacy_client.rs` - Legacy system HTTP client
1140/// - `src/infrastructure/health.rs` - Health check server
1141///
1142/// ## Presentation Layer
1143/// - `src/presentation/mod.rs` - Presentation module exports
1144/// - `src/presentation/handlers.rs` - HTTP API handlers
1145///
1146/// ## Configuration
1147/// - `src/config.rs` - Service configuration
1148/// - `src/error.rs` - Error types
1149///
1150/// # Arguments
1151/// * `project_path` - Root path where files will be created
1152/// * `config` - Project configuration
1153///
1154/// # Errors
1155/// Returns an error if any file write operation fails
1156pub fn generate_acl_files(project_path: &Path, config: &ProjectConfig) -> Result<()> {
1157    // Root files
1158    fs::write(project_path.join("Cargo.toml"), acl::cargo_toml(config))?;
1159    fs::write(project_path.join("src/main.rs"), acl::main_rs(config))?;
1160    fs::write(project_path.join(".gitignore"), templates::gitignore())?;
1161    fs::write(project_path.join("README.md"), acl::readme(config))?;
1162    fs::write(project_path.join("Dockerfile"), acl::dockerfile(config))?;
1163
1164    // Configuration files
1165    fs::write(project_path.join("src/config.rs"), acl::config_rs(config))?;
1166    fs::write(project_path.join("src/error.rs"), acl::error_rs(config))?;
1167
1168    // Domain layer
1169    fs::write(
1170        project_path.join("src/domain/mod.rs"),
1171        acl::domain_mod(config),
1172    )?;
1173    fs::write(
1174        project_path.join("src/domain/legacy.rs"),
1175        acl::domain_legacy(config),
1176    )?;
1177    fs::write(
1178        project_path.join("src/domain/modern.rs"),
1179        acl::domain_modern(config),
1180    )?;
1181    fs::write(
1182        project_path.join("src/domain/transformer.rs"),
1183        acl::domain_transformer(config),
1184    )?;
1185
1186    // Application layer
1187    fs::write(
1188        project_path.join("src/application/mod.rs"),
1189        acl::application_mod(config),
1190    )?;
1191    fs::write(
1192        project_path.join("src/application/translator.rs"),
1193        acl::application_translator(config),
1194    )?;
1195
1196    // Infrastructure layer
1197    fs::write(
1198        project_path.join("src/infrastructure/mod.rs"),
1199        acl::infrastructure_mod(config),
1200    )?;
1201    fs::write(
1202        project_path.join("src/infrastructure/legacy_client.rs"),
1203        acl::infrastructure_legacy_client(config),
1204    )?;
1205    fs::write(
1206        project_path.join("src/infrastructure/health.rs"),
1207        acl::infrastructure_health(config),
1208    )?;
1209
1210    // Presentation layer
1211    fs::write(
1212        project_path.join("src/presentation/mod.rs"),
1213        acl::presentation_mod(config),
1214    )?;
1215    fs::write(
1216        project_path.join("src/presentation/handlers.rs"),
1217        acl::presentation_handlers(config),
1218    )?;
1219
1220    Ok(())
1221}