Skip to main content

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