fast-clean-architecture 1.0.0__py3-none-any.whl → 1.1.0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- fast_clean_architecture/__init__.py +3 -4
- fast_clean_architecture/analytics.py +260 -0
- fast_clean_architecture/cli.py +555 -43
- fast_clean_architecture/config.py +47 -23
- fast_clean_architecture/error_tracking.py +201 -0
- fast_clean_architecture/exceptions.py +432 -12
- fast_clean_architecture/generators/__init__.py +11 -1
- fast_clean_architecture/generators/component_generator.py +407 -103
- fast_clean_architecture/generators/config_updater.py +186 -38
- fast_clean_architecture/generators/generator_factory.py +223 -0
- fast_clean_architecture/generators/package_generator.py +9 -7
- fast_clean_architecture/generators/template_validator.py +109 -9
- fast_clean_architecture/generators/validation_config.py +5 -3
- fast_clean_architecture/generators/validation_metrics.py +10 -6
- fast_clean_architecture/health.py +169 -0
- fast_clean_architecture/logging_config.py +52 -0
- fast_clean_architecture/metrics.py +108 -0
- fast_clean_architecture/protocols.py +406 -0
- fast_clean_architecture/templates/external.py.j2 +109 -32
- fast_clean_architecture/utils.py +50 -31
- fast_clean_architecture/validation.py +302 -0
- {fast_clean_architecture-1.0.0.dist-info → fast_clean_architecture-1.1.0.dist-info}/METADATA +31 -21
- fast_clean_architecture-1.1.0.dist-info/RECORD +38 -0
- fast_clean_architecture-1.0.0.dist-info/RECORD +0 -30
- {fast_clean_architecture-1.0.0.dist-info → fast_clean_architecture-1.1.0.dist-info}/WHEEL +0 -0
- {fast_clean_architecture-1.0.0.dist-info → fast_clean_architecture-1.1.0.dist-info}/entry_points.txt +0 -0
- {fast_clean_architecture-1.0.0.dist-info → fast_clean_architecture-1.1.0.dist-info}/licenses/LICENSE +0 -0
fast_clean_architecture/cli.py
CHANGED
@@ -1,31 +1,98 @@
|
|
1
1
|
"""Command-line interface for fast-clean-architecture."""
|
2
2
|
|
3
|
+
import os
|
3
4
|
import sys
|
4
5
|
from pathlib import Path
|
5
|
-
from typing import Optional
|
6
|
+
from typing import List, NoReturn, Optional, Union, cast
|
6
7
|
|
7
8
|
import typer
|
8
9
|
from rich.console import Console
|
9
|
-
from rich.table import Table
|
10
10
|
from rich.panel import Panel
|
11
|
-
from rich.
|
11
|
+
from rich.progress import Progress, SpinnerColumn, TextColumn
|
12
|
+
from rich.prompt import Confirm, Prompt
|
12
13
|
from rich.syntax import Syntax
|
14
|
+
from rich.table import Table
|
15
|
+
from rich.text import Text
|
13
16
|
|
17
|
+
from .analytics import log_usage_summary, track_command_usage, track_component_creation
|
14
18
|
from .config import Config
|
15
|
-
from .
|
16
|
-
from .
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
from .
|
21
|
-
|
22
|
-
|
23
|
-
|
19
|
+
from .error_tracking import log_error_summary, track_error
|
20
|
+
from .exceptions import FastCleanArchitectureError, ValidationError
|
21
|
+
from .generators import ConfigUpdater, PackageGenerator
|
22
|
+
from .generators.generator_factory import create_generator_factory
|
23
|
+
from .health import log_startup_health
|
24
|
+
from .logging_config import configure_logging, get_logger
|
25
|
+
from .utils import sanitize_name, validate_name, validate_python_identifier
|
26
|
+
|
27
|
+
# Configure structured logging
|
28
|
+
configure_logging()
|
29
|
+
logger = get_logger(__name__)
|
30
|
+
|
31
|
+
# Log startup health
|
32
|
+
log_startup_health()
|
24
33
|
|
25
34
|
# Create the main Typer app
|
26
35
|
app = typer.Typer(
|
27
36
|
name="fca-scaffold",
|
28
|
-
help="Fast Clean Architecture scaffolding tool for FastAPI projects
|
37
|
+
help="""[bold blue]Fast Clean Architecture[/bold blue] is a scaffolding tool for FastAPI projects.
|
38
|
+
|
39
|
+
[bold]Quick Start:[/bold]
|
40
|
+
1. Initialize a new project
|
41
|
+
[cyan]fca-scaffold init[/cyan]
|
42
|
+
|
43
|
+
2. Create a system context
|
44
|
+
[cyan]fca-scaffold create-system-context admin[/cyan]
|
45
|
+
|
46
|
+
3. Create a module in the admin system
|
47
|
+
[cyan]fca-scaffold create-module admin auth[/cyan]
|
48
|
+
|
49
|
+
4. Create a component (e.g., entities, services, repositories)
|
50
|
+
[cyan]fca-scaffold create-component admin/auth/domain/entities Admin[/cyan]
|
51
|
+
|
52
|
+
[bold]Definitions:[/bold]
|
53
|
+
[yellow]System:[/yellow]
|
54
|
+
A bounded context representing a major business domain.
|
55
|
+
Examples: user_management, payment_processing
|
56
|
+
|
57
|
+
[yellow]Module:[/yellow]
|
58
|
+
A functional area within a system that groups related components.
|
59
|
+
Examples: auth, billing, notifications
|
60
|
+
|
61
|
+
[yellow]Component:[/yellow]
|
62
|
+
Individual code artifacts within Clean Architecture layers:
|
63
|
+
|
64
|
+
[dim]Domain:[/dim]
|
65
|
+
- entities
|
66
|
+
- repositories
|
67
|
+
- value_objects
|
68
|
+
|
69
|
+
[dim]Application:[/dim]
|
70
|
+
- services
|
71
|
+
- commands
|
72
|
+
- queries
|
73
|
+
|
74
|
+
[dim]Infrastructure:[/dim]
|
75
|
+
- models
|
76
|
+
- repositories
|
77
|
+
- external
|
78
|
+
|
79
|
+
[dim]Presentation:[/dim]
|
80
|
+
- api
|
81
|
+
- schemas
|
82
|
+
|
83
|
+
[bold]Get help for any command:[/bold]
|
84
|
+
[cyan]fca-scaffold [COMMAND] --help[/cyan]
|
85
|
+
|
86
|
+
[bold]Examples:[/bold]
|
87
|
+
Initialize a project with a description:
|
88
|
+
[dim]fca-scaffold init my-project --description "My FastAPI project"[/dim]
|
89
|
+
|
90
|
+
Check scaffold status:
|
91
|
+
[dim]fca-scaffold status[/dim]
|
92
|
+
|
93
|
+
Show current config:
|
94
|
+
[dim]fca-scaffold config show[/dim]
|
95
|
+
""",
|
29
96
|
rich_markup_mode="rich",
|
30
97
|
)
|
31
98
|
|
@@ -44,7 +111,7 @@ FORCE_OPTION = typer.Option(
|
|
44
111
|
)
|
45
112
|
VERBOSE_OPTION = typer.Option(False, "--verbose", "-v", help="Enable verbose output")
|
46
113
|
CONFIG_PATH_OPTION = typer.Option(
|
47
|
-
"
|
114
|
+
"fca_config.yaml", "--config", "-c", help="Path to configuration file"
|
48
115
|
)
|
49
116
|
|
50
117
|
|
@@ -61,7 +128,7 @@ def get_config_path(config_file: str) -> Path:
|
|
61
128
|
return config_path
|
62
129
|
|
63
130
|
|
64
|
-
def handle_error(error: Exception, verbose: bool = False) ->
|
131
|
+
def handle_error(error: Exception, verbose: bool = False) -> NoReturn:
|
65
132
|
"""Handle and display errors consistently."""
|
66
133
|
if isinstance(error, FastCleanArchitectureError):
|
67
134
|
console.print(f"[red]Error:[/red] {error}")
|
@@ -76,16 +143,34 @@ def handle_error(error: Exception, verbose: bool = False) -> None:
|
|
76
143
|
|
77
144
|
@app.command()
|
78
145
|
def init(
|
79
|
-
name: Optional[str] = typer.Argument(
|
146
|
+
name: Optional[str] = typer.Argument(
|
147
|
+
None, help="Project name (will be sanitized for Python compatibility)"
|
148
|
+
),
|
80
149
|
description: Optional[str] = typer.Option(
|
81
|
-
None, "--description", "--desc", help="Project description"
|
150
|
+
None, "--description", "--desc", help="Project description for documentation"
|
151
|
+
),
|
152
|
+
version: Optional[str] = typer.Option(
|
153
|
+
"0.1.0", "--version", help="Initial project version (semantic versioning)"
|
82
154
|
),
|
83
|
-
version: Optional[str] = typer.Option("0.1.0", "--version", help="Project version"),
|
84
155
|
config_file: str = CONFIG_PATH_OPTION,
|
85
156
|
force: bool = FORCE_OPTION,
|
86
157
|
verbose: bool = VERBOSE_OPTION,
|
87
158
|
) -> None:
|
88
|
-
"""Initialize a new Fast Clean Architecture project.
|
159
|
+
"""Initialize a new Fast Clean Architecture project.
|
160
|
+
|
161
|
+
Creates a new FCA project with configuration file and basic directory structure.
|
162
|
+
If no name is provided, you'll be prompted to enter one.
|
163
|
+
|
164
|
+
[bold]Examples:[/bold]
|
165
|
+
[cyan]fca-scaffold init[/cyan] # Interactive mode
|
166
|
+
[cyan]fca-scaffold init my-api[/cyan] # With project name
|
167
|
+
[cyan]fca-scaffold init my-api --desc "User management API"[/cyan] # With description
|
168
|
+
[cyan]fca-scaffold init my-api --version 1.0.0 --force[/cyan] # Overwrite existing
|
169
|
+
|
170
|
+
[bold]What it creates:[/bold]
|
171
|
+
• [dim]fca_config.yaml[/dim] - Project configuration file
|
172
|
+
• [dim]systems/[/dim] - Directory for system contexts
|
173
|
+
"""
|
89
174
|
try:
|
90
175
|
project_root = get_project_root()
|
91
176
|
config_path = get_config_path(config_file)
|
@@ -139,16 +224,35 @@ def init(
|
|
139
224
|
|
140
225
|
@app.command()
|
141
226
|
def create_system_context(
|
142
|
-
name: str = typer.Argument(
|
227
|
+
name: str = typer.Argument(
|
228
|
+
..., help="System context name (e.g., admin, customer, settings)"
|
229
|
+
),
|
143
230
|
description: Optional[str] = typer.Option(
|
144
|
-
None, "--description", "--desc", help="
|
231
|
+
None, "--description", "--desc", help="Description of what this system handles"
|
145
232
|
),
|
146
233
|
config_file: str = CONFIG_PATH_OPTION,
|
147
234
|
dry_run: bool = DRY_RUN_OPTION,
|
148
235
|
force: bool = FORCE_OPTION,
|
149
236
|
verbose: bool = VERBOSE_OPTION,
|
150
237
|
) -> None:
|
151
|
-
"""Create a new system context.
|
238
|
+
"""Create a new system context.
|
239
|
+
|
240
|
+
A system context represents a bounded context in your domain, containing related
|
241
|
+
business functionality or aimed at different operational context such as admin, customer, settings. Each system can contain multiple modules.
|
242
|
+
|
243
|
+
[bold]Examples:[/bold]
|
244
|
+
[cyan]fca-scaffold create-system-context admin[/cyan]
|
245
|
+
[cyan]fca-scaffold create-system-context customer --desc "Customer System"[/cyan]
|
246
|
+
[cyan]fca-scaffold create-system-context settings --dry-run[/cyan] # Preview only
|
247
|
+
|
248
|
+
[bold]What it creates:[/bold]
|
249
|
+
• [dim]systems/[SYSTEM_NAME]/[/dim] - System directory
|
250
|
+
• [dim]systems/[SYSTEM_NAME]/__init__.py[/dim] - Python package file
|
251
|
+
• Updates [dim]fca_config.yaml[/dim] with system information
|
252
|
+
|
253
|
+
[bold]Next steps:[/bold]
|
254
|
+
Create modules with: [cyan]fca-scaffold create-module [SYSTEM_NAME] [MODULE_NAME][/cyan]
|
255
|
+
"""
|
152
256
|
try:
|
153
257
|
project_root = get_project_root()
|
154
258
|
config_path = get_config_path(config_file)
|
@@ -183,17 +287,41 @@ def create_system_context(
|
|
183
287
|
|
184
288
|
@app.command()
|
185
289
|
def create_module(
|
186
|
-
system_name: str = typer.Argument(..., help="
|
187
|
-
module_name: str = typer.Argument(
|
290
|
+
system_name: str = typer.Argument(..., help="Existing system context name"),
|
291
|
+
module_name: str = typer.Argument(
|
292
|
+
..., help="Module name (e.g., authentication, user_profile)"
|
293
|
+
),
|
188
294
|
description: Optional[str] = typer.Option(
|
189
|
-
None, "--description", "--desc", help="
|
295
|
+
None, "--description", "--desc", help="Description of module functionality"
|
190
296
|
),
|
191
297
|
config_file: str = CONFIG_PATH_OPTION,
|
192
298
|
dry_run: bool = DRY_RUN_OPTION,
|
193
299
|
force: bool = FORCE_OPTION,
|
194
300
|
verbose: bool = VERBOSE_OPTION,
|
195
301
|
) -> None:
|
196
|
-
"""Create a new module within a system context.
|
302
|
+
"""Create a new module within a system context.
|
303
|
+
|
304
|
+
Modules organize related functionality within a system context, following
|
305
|
+
Clean Architecture layers (domain, application, infrastructure, presentation).
|
306
|
+
|
307
|
+
[bold]Examples:[/bold]
|
308
|
+
[cyan]fca-scaffold create-module admin authentication[/cyan]
|
309
|
+
[cyan]fca-scaffold create-module customer payment_processing --desc "Payment processing logic"[/cyan]
|
310
|
+
[cyan]fca-scaffold create-module settings notification_settings --dry-run[/cyan] # Preview only
|
311
|
+
|
312
|
+
[bold]What it creates:[/bold]
|
313
|
+
• [dim]systems/[SYSTEM_NAME]/modules/[MODULE_NAME]/[/dim] - Module directory
|
314
|
+
• [dim]systems/[SYSTEM_NAME]/modules/[MODULE_NAME]/__init__.py[/dim] - Package file
|
315
|
+
• [dim]systems/[SYSTEM_NAME]/modules/[MODULE_NAME]/[MODULE_NAME]_module_api.py[/dim] - Module API file
|
316
|
+
• [dim]systems/[SYSTEM_NAME]/modules/[MODULE_NAME]/domain/[/dim] - Domain layer
|
317
|
+
• [dim]systems/[SYSTEM_NAME]/modules/[MODULE_NAME]/application/[/dim] - Application layer
|
318
|
+
• [dim]systems/[SYSTEM_NAME]/modules/[MODULE_NAME]/infrastructure/[/dim] - Infrastructure layer
|
319
|
+
• [dim]systems/[SYSTEM_NAME]/modules/[MODULE_NAME]/presentation/[/dim] - Presentation layer
|
320
|
+
• Updates [dim]fca_config.yaml[/dim] with module information
|
321
|
+
|
322
|
+
[bold]Next steps:[/bold]
|
323
|
+
Create components with: [cyan]fca-scaffold create-component [SYSTEM_NAME]/[MODULE_NAME]/[LAYER]/[TYPE] [COMPONENT_NAME][/cyan]
|
324
|
+
"""
|
197
325
|
try:
|
198
326
|
project_root = get_project_root()
|
199
327
|
config_path = get_config_path(config_file)
|
@@ -234,9 +362,12 @@ def create_module(
|
|
234
362
|
@app.command()
|
235
363
|
def create_component(
|
236
364
|
location: str = typer.Argument(
|
237
|
-
...,
|
365
|
+
...,
|
366
|
+
help="Component location: system/module/layer/type (e.g., user_management/auth/domain/entities)",
|
367
|
+
),
|
368
|
+
name: str = typer.Argument(
|
369
|
+
..., help="Component name (e.g., User, AuthService, UserRepository)"
|
238
370
|
),
|
239
|
-
name: str = typer.Argument(..., help="Component name"),
|
240
371
|
config_file: str = CONFIG_PATH_OPTION,
|
241
372
|
dry_run: bool = DRY_RUN_OPTION,
|
242
373
|
force: bool = FORCE_OPTION,
|
@@ -244,10 +375,54 @@ def create_component(
|
|
244
375
|
) -> None:
|
245
376
|
"""Create a new component.
|
246
377
|
|
247
|
-
|
248
|
-
|
378
|
+
Creates components following Clean Architecture patterns. Components are generated
|
379
|
+
from templates and placed in the appropriate layer directory.
|
380
|
+
|
381
|
+
[bold]Location format:[/bold] [cyan]system_name/module_name/layer/component_type[/cyan]
|
382
|
+
|
383
|
+
[bold]Available layers and component types:[/bold]
|
384
|
+
[yellow]domain/[/yellow]
|
385
|
+
• [cyan]entities[/cyan] - Domain entities (business objects)
|
386
|
+
• [cyan]value_objects[/cyan] - Value objects (immutable data)
|
387
|
+
• [cyan]repositories[/cyan] - Repository interfaces
|
388
|
+
• [cyan]services[/cyan] - Domain services
|
389
|
+
|
390
|
+
[yellow]application/[/yellow]
|
391
|
+
• [cyan]commands[/cyan] - Command handlers (CQRS)
|
392
|
+
• [cyan]queries[/cyan] - Query handlers (CQRS)
|
393
|
+
• [cyan]services[/cyan] - Application services
|
394
|
+
|
395
|
+
[yellow]infrastructure/[/yellow]
|
396
|
+
• [cyan]models[/cyan] - Database models and schemas
|
397
|
+
• [cyan]repositories[/cyan] - Repository implementations
|
398
|
+
• [cyan]external[/cyan] - External service adapters
|
399
|
+
|
400
|
+
[yellow]presentation/[/yellow]
|
401
|
+
• [cyan]api[/cyan] - API endpoints/controllers
|
402
|
+
• [cyan]schemas[/cyan] - Request/response schemas
|
403
|
+
|
404
|
+
[bold]Examples:[/bold]
|
405
|
+
[cyan]fca-scaffold create-component admin/auth/domain/entities User[/cyan]
|
406
|
+
[cyan]fca-scaffold create-component admin/auth/application/commands CreateUser[/cyan]
|
407
|
+
[cyan]fca-scaffold create-component customer/payment_processing/infrastructure/repositories PaymentProcessingRepository[/cyan]
|
408
|
+
[cyan]fca-scaffold create-component settings/notification_settings/presentation/api NotificationSettingsAPI[/cyan]
|
409
|
+
|
410
|
+
[bold]What it creates:[/bold]
|
411
|
+
• Python file with component implementation
|
412
|
+
• Imports and dependencies based on component type
|
413
|
+
• Updates [dim]fca_config.yaml[/dim] with component information
|
249
414
|
"""
|
250
415
|
try:
|
416
|
+
# Log CLI command start
|
417
|
+
logger.info(
|
418
|
+
"CLI create_component command started",
|
419
|
+
operation="cli_create_component",
|
420
|
+
location=location,
|
421
|
+
name=name,
|
422
|
+
dry_run=dry_run,
|
423
|
+
force=force,
|
424
|
+
)
|
425
|
+
|
251
426
|
project_root = get_project_root()
|
252
427
|
config_path = get_config_path(config_file)
|
253
428
|
|
@@ -274,12 +449,18 @@ def create_component(
|
|
274
449
|
):
|
275
450
|
raise ValidationError("Invalid names provided")
|
276
451
|
|
277
|
-
# Initialize generators
|
452
|
+
# Initialize generators using factory pattern
|
278
453
|
config_updater = ConfigUpdater(config_path, console)
|
279
|
-
|
454
|
+
generator_factory = create_generator_factory(config_updater.config, console)
|
455
|
+
component_generator = generator_factory.create_generator("component")
|
456
|
+
|
457
|
+
# Cast to ComponentGeneratorProtocol for type safety
|
458
|
+
from .generators import ComponentGeneratorProtocol
|
459
|
+
|
460
|
+
component_gen = cast(ComponentGeneratorProtocol, component_generator)
|
280
461
|
|
281
462
|
# Create component
|
282
|
-
file_path =
|
463
|
+
file_path = component_gen.create_component(
|
283
464
|
base_path=project_root,
|
284
465
|
system_name=sanitized_system,
|
285
466
|
module_name=sanitized_module,
|
@@ -305,19 +486,87 @@ def create_component(
|
|
305
486
|
f"[green]✅ Component '{sanitized_name}' created at {location}![/green]"
|
306
487
|
)
|
307
488
|
|
489
|
+
# Log successful completion
|
490
|
+
logger.info(
|
491
|
+
"CLI create_component command completed successfully",
|
492
|
+
operation="cli_create_component",
|
493
|
+
component_name=sanitized_name,
|
494
|
+
location=location,
|
495
|
+
file_path=str(file_path) if not dry_run else None,
|
496
|
+
)
|
497
|
+
|
498
|
+
# Track component creation for analytics
|
499
|
+
if not dry_run:
|
500
|
+
track_component_creation(
|
501
|
+
system_name=sanitized_system,
|
502
|
+
module_name=sanitized_module,
|
503
|
+
layer=layer,
|
504
|
+
component_type=component_type,
|
505
|
+
component_name=sanitized_name,
|
506
|
+
)
|
507
|
+
|
308
508
|
except Exception as e:
|
509
|
+
# Log CLI error and track it
|
510
|
+
logger.error(
|
511
|
+
"CLI create_component command failed",
|
512
|
+
operation="cli_create_component",
|
513
|
+
error=str(e),
|
514
|
+
error_type=type(e).__name__,
|
515
|
+
location=location,
|
516
|
+
name=name,
|
517
|
+
)
|
518
|
+
|
519
|
+
# Track the error for analytics
|
520
|
+
track_error(
|
521
|
+
error=e,
|
522
|
+
context={
|
523
|
+
"command": "create_component",
|
524
|
+
"location": location,
|
525
|
+
"name": name,
|
526
|
+
"dry_run": dry_run,
|
527
|
+
"force": force,
|
528
|
+
},
|
529
|
+
operation="cli_create_component",
|
530
|
+
)
|
531
|
+
|
309
532
|
handle_error(e, verbose)
|
310
533
|
|
311
534
|
|
312
535
|
@app.command()
|
313
536
|
def batch_create(
|
314
|
-
spec_file: str = typer.Argument(
|
537
|
+
spec_file: str = typer.Argument(
|
538
|
+
..., help="Path to YAML specification file (see examples/components_spec.yaml)"
|
539
|
+
),
|
315
540
|
config_file: str = CONFIG_PATH_OPTION,
|
316
541
|
dry_run: bool = DRY_RUN_OPTION,
|
317
542
|
force: bool = FORCE_OPTION,
|
318
543
|
verbose: bool = VERBOSE_OPTION,
|
319
544
|
) -> None:
|
320
|
-
"""Create multiple components from a YAML specification file.
|
545
|
+
"""Create multiple components from a YAML specification file.
|
546
|
+
|
547
|
+
Batch creation allows you to define multiple systems, modules, and components
|
548
|
+
in a single YAML file and create them all at once.
|
549
|
+
|
550
|
+
[bold]Examples:[/bold]
|
551
|
+
[cyan]fca-scaffold batch-create components_spec.yaml[/cyan]
|
552
|
+
[cyan]fca-scaffold batch-create my-spec.yaml --dry-run[/cyan] # Preview only
|
553
|
+
|
554
|
+
[bold]Specification file format:[/bold]
|
555
|
+
[dim]systems:[/dim]
|
556
|
+
[dim] - name: admin[/dim]
|
557
|
+
[dim] modules:[/dim]
|
558
|
+
[dim] - name: authentication[/dim]
|
559
|
+
[dim] components:[/dim]
|
560
|
+
[dim] domain:[/dim]
|
561
|
+
[dim] entities: [AdminUser, AdminRole][/dim]
|
562
|
+
[dim] value_objects: [AdminEmail, AdminPassword][/dim]
|
563
|
+
[dim] repositories: [AdminUserRepository][/dim]
|
564
|
+
[dim] application:[/dim]
|
565
|
+
[dim] commands: [CreateAdminUser, UpdateAdminUser][/dim]
|
566
|
+
|
567
|
+
[bold]See also:[/bold]
|
568
|
+
Check [cyan]examples/components_spec.yaml[/cyan] for a complete example
|
569
|
+
"""
|
321
570
|
try:
|
322
571
|
import yaml
|
323
572
|
|
@@ -332,9 +581,10 @@ def batch_create(
|
|
332
581
|
with open(spec_path, "r", encoding="utf-8") as f:
|
333
582
|
spec = yaml.safe_load(f)
|
334
583
|
|
335
|
-
# Initialize generators
|
584
|
+
# Initialize generators using factory pattern
|
336
585
|
config_updater = ConfigUpdater(config_path, console)
|
337
|
-
|
586
|
+
generator_factory = create_generator_factory(config_updater.config, console)
|
587
|
+
component_generator = generator_factory.create_generator("component")
|
338
588
|
|
339
589
|
# Process specification
|
340
590
|
for system_spec in spec.get("systems", []):
|
@@ -344,8 +594,13 @@ def batch_create(
|
|
344
594
|
module_name = module_spec["name"]
|
345
595
|
components_spec = module_spec.get("components", {})
|
346
596
|
|
597
|
+
# Cast to ComponentGeneratorProtocol for type safety
|
598
|
+
from .protocols import ComponentGeneratorProtocol
|
599
|
+
|
600
|
+
component_gen = cast(ComponentGeneratorProtocol, component_generator)
|
601
|
+
|
347
602
|
# Create components
|
348
|
-
|
603
|
+
component_gen.create_multiple_components(
|
349
604
|
base_path=project_root,
|
350
605
|
system_name=system_name,
|
351
606
|
module_name=module_name,
|
@@ -365,7 +620,22 @@ def status(
|
|
365
620
|
config_file: str = CONFIG_PATH_OPTION,
|
366
621
|
verbose: bool = VERBOSE_OPTION,
|
367
622
|
) -> None:
|
368
|
-
"""Show project status and configuration summary.
|
623
|
+
"""Show project status and configuration summary.
|
624
|
+
|
625
|
+
Displays an overview of your FCA project including systems, modules,
|
626
|
+
and recent activity. Useful for understanding project structure.
|
627
|
+
|
628
|
+
[bold]Examples:[/bold]
|
629
|
+
[cyan]fca-scaffold status[/cyan] # Show project overview
|
630
|
+
[cyan]fca-scaffold status --verbose[/cyan] # Detailed information
|
631
|
+
[cyan]fca-scaffold status -c my-config.yaml[/cyan] # Custom config file
|
632
|
+
|
633
|
+
[bold]Information shown:[/bold]
|
634
|
+
• Project name, version, and timestamps
|
635
|
+
• Systems and module counts
|
636
|
+
• Recent creation/update dates
|
637
|
+
• Configuration file location
|
638
|
+
"""
|
369
639
|
try:
|
370
640
|
config_path = get_config_path(config_file)
|
371
641
|
|
@@ -417,11 +687,31 @@ def status(
|
|
417
687
|
|
418
688
|
@app.command()
|
419
689
|
def config(
|
420
|
-
action: str = typer.Argument(..., help="Action: show, edit, validate"),
|
690
|
+
action: str = typer.Argument(..., help="Action to perform: show, edit, validate"),
|
421
691
|
config_file: str = CONFIG_PATH_OPTION,
|
422
692
|
verbose: bool = VERBOSE_OPTION,
|
423
693
|
) -> None:
|
424
|
-
"""Manage project configuration.
|
694
|
+
"""Manage project configuration.
|
695
|
+
|
696
|
+
Provides tools to view, edit, and validate your FCA project configuration.
|
697
|
+
The configuration file tracks all systems, modules, and components.
|
698
|
+
|
699
|
+
[bold]Available actions:[/bold]
|
700
|
+
[cyan]show[/cyan] - Display configuration file contents with syntax highlighting
|
701
|
+
[cyan]edit[/cyan] - Get instructions for editing the configuration
|
702
|
+
[cyan]validate[/cyan] - Check if configuration file is valid YAML and structure
|
703
|
+
|
704
|
+
[bold]Examples:[/bold]
|
705
|
+
[cyan]fca-scaffold config show[/cyan] # View current config
|
706
|
+
[cyan]fca-scaffold config validate[/cyan] # Check config validity
|
707
|
+
[cyan]fca-scaffold config show -c my-config.yaml[/cyan] # Custom config file
|
708
|
+
|
709
|
+
[bold]Configuration structure:[/bold]
|
710
|
+
• [dim]project[/dim] - Project metadata (name, version, description)
|
711
|
+
• [dim]systems[/dim] - System contexts and their modules
|
712
|
+
• [dim]components[/dim] - Generated components and their locations
|
713
|
+
• [dim]timestamps[/dim] - Creation and modification dates
|
714
|
+
"""
|
425
715
|
try:
|
426
716
|
config_path = get_config_path(config_file)
|
427
717
|
|
@@ -461,10 +751,100 @@ def config(
|
|
461
751
|
handle_error(e, verbose)
|
462
752
|
|
463
753
|
|
754
|
+
@app.command()
|
755
|
+
def help_guide() -> None:
|
756
|
+
"""Show comprehensive help and quick reference guide.
|
757
|
+
|
758
|
+
Displays a detailed guide covering all commands, common workflows,
|
759
|
+
and best practices for using Fast Clean Architecture.
|
760
|
+
|
761
|
+
[bold]Example:[/bold]
|
762
|
+
[cyan]fca-scaffold help-guide[/cyan]
|
763
|
+
|
764
|
+
[bold]Covers:[/bold]
|
765
|
+
• Complete workflow from project init to component creation
|
766
|
+
• Command reference with examples
|
767
|
+
• Clean Architecture layer explanations
|
768
|
+
• Best practices and tips
|
769
|
+
"""
|
770
|
+
console.print(
|
771
|
+
Panel.fit(
|
772
|
+
"[bold blue]Fast Clean Architecture - Complete Guide[/bold blue]\n\n"
|
773
|
+
"[bold yellow]📖 Key Definitions:[/bold yellow]\n\n"
|
774
|
+
"[yellow]System:[/yellow]\n"
|
775
|
+
" A bounded context representing a major business domain.\n"
|
776
|
+
" Examples: admin, customer, settings\n\n"
|
777
|
+
"[yellow]Module:[/yellow]\n"
|
778
|
+
" A functional area within a system that groups related components.\n"
|
779
|
+
" Examples: auth, billing, notifications, reporting\n\n"
|
780
|
+
"[yellow]Component:[/yellow]\n"
|
781
|
+
" Individual code artifacts within Clean Architecture layers:\n\n"
|
782
|
+
" [dim]Domain:[/dim]\n"
|
783
|
+
" - entities\n"
|
784
|
+
" - repositories\n"
|
785
|
+
" - value_objects\n\n"
|
786
|
+
" [dim]Application:[/dim]\n"
|
787
|
+
" - services\n"
|
788
|
+
" - commands\n"
|
789
|
+
" - queries\n\n"
|
790
|
+
" [dim]Infrastructure:[/dim]\n"
|
791
|
+
" - models\n"
|
792
|
+
" - repositories\n"
|
793
|
+
" - external\n\n"
|
794
|
+
" [dim]Presentation:[/dim]\n"
|
795
|
+
" - api\n"
|
796
|
+
" - schemas\n\n"
|
797
|
+
"[bold yellow]🚀 Quick Start Workflow:[/bold yellow]\n"
|
798
|
+
"1. [cyan]fca-scaffold init my-project[/cyan] - Initialize project\n"
|
799
|
+
"2. [cyan]fca-scaffold create-system-context admin[/cyan] - Create system\n"
|
800
|
+
"3. [cyan]fca-scaffold create-module admin auth[/cyan] - Create module\n"
|
801
|
+
"4. [cyan]fca-scaffold create-component admin/auth/domain/entities AdminUser[/cyan] - Create any component type\n\n"
|
802
|
+
"[bold yellow]📋 Available Commands:[/bold yellow]\n"
|
803
|
+
"• [cyan]init[/cyan] - Initialize new project\n"
|
804
|
+
"• [cyan]create-system-context[/cyan] - Create system (bounded context)\n"
|
805
|
+
"• [cyan]create-module[/cyan] - Create module within system\n"
|
806
|
+
"• [cyan]create-component[/cyan] - Create individual components (entities, services, repositories, etc.)\n"
|
807
|
+
"• [cyan]batch-create[/cyan] - Create multiple components from YAML\n"
|
808
|
+
"• [cyan]status[/cyan] - Show project overview\n"
|
809
|
+
"• [cyan]config[/cyan] - Manage configuration\n"
|
810
|
+
"• [cyan]version[/cyan] - Show version info\n\n"
|
811
|
+
"[bold yellow]🏗️ Clean Architecture Layers & Components:[/bold yellow]\n"
|
812
|
+
"• [yellow]domain/[/yellow] - Business logic\n"
|
813
|
+
" ◦ entities, repositories, value_objects\n"
|
814
|
+
"• [yellow]application/[/yellow] - Use cases\n"
|
815
|
+
" ◦ services, commands, queries\n"
|
816
|
+
"• [yellow]infrastructure/[/yellow] - External concerns\n"
|
817
|
+
" ◦ models, repositories, external\n"
|
818
|
+
"• [yellow]presentation/[/yellow] - User interface\n"
|
819
|
+
" ◦ api, schemas\n\n"
|
820
|
+
"[bold yellow]💡 Pro Tips:[/bold yellow]\n"
|
821
|
+
"• Use [cyan]--dry-run[/cyan] to preview changes\n"
|
822
|
+
"• Use [cyan]--help[/cyan] with any command for detailed info\n"
|
823
|
+
"• Check [cyan]fca-scaffold status[/cyan] to see project structure\n"
|
824
|
+
"• Validate config with [cyan]fca-scaffold config validate[/cyan]\n\n"
|
825
|
+
"[bold yellow]📖 For detailed help on any command:[/bold yellow]\n"
|
826
|
+
"[cyan]fca-scaffold [COMMAND] --help[/cyan]",
|
827
|
+
title="📚 Fast Clean Architecture - Help Guide",
|
828
|
+
)
|
829
|
+
)
|
830
|
+
|
831
|
+
|
464
832
|
@app.command()
|
465
833
|
def version() -> None:
|
466
|
-
"""Show version information.
|
467
|
-
|
834
|
+
"""Show version information.
|
835
|
+
|
836
|
+
Displays the current version of Fast Clean Architecture scaffolding tool
|
837
|
+
along with author information.
|
838
|
+
|
839
|
+
[bold]Example:[/bold]
|
840
|
+
[cyan]fca-scaffold version[/cyan]
|
841
|
+
|
842
|
+
[bold]Useful for:[/bold]
|
843
|
+
• Checking which version you're running
|
844
|
+
• Bug reports and support requests
|
845
|
+
• Ensuring compatibility with documentation
|
846
|
+
"""
|
847
|
+
from . import __author__, __version__
|
468
848
|
|
469
849
|
console.print(
|
470
850
|
Panel.fit(
|
@@ -476,5 +856,137 @@ def version() -> None:
|
|
476
856
|
)
|
477
857
|
|
478
858
|
|
859
|
+
@app.command()
|
860
|
+
def system_status(
|
861
|
+
verbose: bool = VERBOSE_OPTION,
|
862
|
+
) -> None:
|
863
|
+
"""Show system status, health, and usage analytics.
|
864
|
+
|
865
|
+
Displays comprehensive information about:
|
866
|
+
- System health and resource usage
|
867
|
+
- Error tracking summary
|
868
|
+
- Usage analytics and productivity metrics
|
869
|
+
|
870
|
+
[bold]Examples:[/bold]
|
871
|
+
[cyan]fca-scaffold system-status[/cyan]
|
872
|
+
[cyan]fca-scaffold system-status --verbose[/cyan]
|
873
|
+
"""
|
874
|
+
try:
|
875
|
+
from .analytics import get_analytics
|
876
|
+
from .error_tracking import get_error_tracker
|
877
|
+
from .health import get_health_monitor
|
878
|
+
|
879
|
+
console.print("\n[bold blue]📊 Fast Clean Architecture Status[/bold blue]\n")
|
880
|
+
|
881
|
+
# Health Status
|
882
|
+
console.print("[bold yellow]🏥 System Health[/bold yellow]")
|
883
|
+
health_monitor = get_health_monitor()
|
884
|
+
health_data = health_monitor.get_system_health()
|
885
|
+
|
886
|
+
if "error" in health_data:
|
887
|
+
console.print(f"[red]❌ Health check failed: {health_data['error']}[/red]")
|
888
|
+
else:
|
889
|
+
process_data = health_data.get("process", {})
|
890
|
+
system_data = health_data.get("system", {})
|
891
|
+
|
892
|
+
console.print(
|
893
|
+
f" • Memory Usage: {process_data.get('memory_rss_mb', 0):.1f} MB ({process_data.get('memory_percent', 0):.1f}%)"
|
894
|
+
)
|
895
|
+
console.print(f" • CPU Usage: {process_data.get('cpu_percent', 0):.1f}%")
|
896
|
+
console.print(
|
897
|
+
f" • System Memory: {system_data.get('memory_used_percent', 0):.1f}% used"
|
898
|
+
)
|
899
|
+
console.print(
|
900
|
+
f" • Disk Space: {system_data.get('disk_used_percent', 0):.1f}% used"
|
901
|
+
)
|
902
|
+
console.print(
|
903
|
+
f" • Uptime: {health_data.get('uptime_seconds', 0):.1f} seconds"
|
904
|
+
)
|
905
|
+
|
906
|
+
# Error Tracking
|
907
|
+
console.print("\n[bold yellow]🐛 Error Tracking[/bold yellow]")
|
908
|
+
error_tracker = get_error_tracker()
|
909
|
+
error_summary = error_tracker.get_error_summary()
|
910
|
+
|
911
|
+
console.print(f" • Total Errors: {error_summary.get('total_errors', 0)}")
|
912
|
+
console.print(f" • Unique Errors: {error_summary.get('unique_errors', 0)}")
|
913
|
+
|
914
|
+
if error_summary.get("most_common_errors"):
|
915
|
+
console.print(" • Most Common Errors:")
|
916
|
+
for error_info in error_summary["most_common_errors"][:3]:
|
917
|
+
console.print(
|
918
|
+
f" - {error_info['signature']}: {error_info['count']} times"
|
919
|
+
)
|
920
|
+
|
921
|
+
# Usage Analytics
|
922
|
+
console.print("\n[bold yellow]📈 Usage Analytics[/bold yellow]")
|
923
|
+
analytics = get_analytics()
|
924
|
+
usage_summary = analytics.get_usage_summary()
|
925
|
+
productivity = analytics.get_productivity_metrics()
|
926
|
+
|
927
|
+
session_data = usage_summary.get("session", {})
|
928
|
+
console.print(
|
929
|
+
f" • Session Duration: {session_data.get('duration_seconds', 0):.1f} seconds"
|
930
|
+
)
|
931
|
+
console.print(f" • Total Commands: {session_data.get('total_commands', 0)}")
|
932
|
+
console.print(
|
933
|
+
f" • Components Created: {productivity.get('components_created', 0)}"
|
934
|
+
)
|
935
|
+
console.print(
|
936
|
+
f" • Components/Hour: {productivity.get('components_per_hour', 0):.1f}"
|
937
|
+
)
|
938
|
+
|
939
|
+
if usage_summary.get("commands"):
|
940
|
+
console.print(" • Command Usage:")
|
941
|
+
for command, count in list(usage_summary["commands"].items())[:3]:
|
942
|
+
console.print(f" - {command}: {count} times")
|
943
|
+
|
944
|
+
if usage_summary.get("component_types"):
|
945
|
+
console.print(" • Popular Component Types:")
|
946
|
+
for comp_type, count in list(usage_summary["component_types"].items())[:3]:
|
947
|
+
console.print(f" - {comp_type}: {count} times")
|
948
|
+
|
949
|
+
if verbose:
|
950
|
+
# Show detailed information
|
951
|
+
console.print("\n[bold yellow]🔍 Detailed Information[/bold yellow]")
|
952
|
+
|
953
|
+
if usage_summary.get("layers"):
|
954
|
+
console.print(" • Layer Usage:")
|
955
|
+
for layer, count in usage_summary["layers"].items():
|
956
|
+
console.print(f" - {layer}: {count} times")
|
957
|
+
|
958
|
+
if usage_summary.get("systems"):
|
959
|
+
console.print(" • System Usage:")
|
960
|
+
for system, count in usage_summary["systems"].items():
|
961
|
+
console.print(f" - {system}: {count} times")
|
962
|
+
|
963
|
+
if usage_summary.get("performance"):
|
964
|
+
console.print(" • Performance Metrics:")
|
965
|
+
for command, perf in usage_summary["performance"].items():
|
966
|
+
console.print(
|
967
|
+
f" - {command}: avg {perf['average_ms']}ms (min: {perf['min_ms']}ms, max: {perf['max_ms']}ms)"
|
968
|
+
)
|
969
|
+
|
970
|
+
console.print("\n[green]✅ Status check completed[/green]")
|
971
|
+
|
972
|
+
# Log the status check
|
973
|
+
logger.info(
|
974
|
+
"System status command executed",
|
975
|
+
operation="cli_system_status",
|
976
|
+
verbose=verbose,
|
977
|
+
)
|
978
|
+
|
979
|
+
except Exception as e:
|
980
|
+
logger.error(
|
981
|
+
"System status command failed",
|
982
|
+
operation="cli_system_status",
|
983
|
+
error=str(e),
|
984
|
+
error_type=type(e).__name__,
|
985
|
+
)
|
986
|
+
handle_error(e, verbose)
|
987
|
+
|
988
|
+
|
479
989
|
if __name__ == "__main__":
|
990
|
+
# Ensure logging is configured
|
991
|
+
configure_logging()
|
480
992
|
app()
|