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