coregen-cli 3.1.6__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.
Files changed (172) hide show
  1. coregen.py +1585 -0
  2. coregen_cli-3.1.6.dist-info/METADATA +1211 -0
  3. coregen_cli-3.1.6.dist-info/RECORD +172 -0
  4. coregen_cli-3.1.6.dist-info/WHEEL +5 -0
  5. coregen_cli-3.1.6.dist-info/entry_points.txt +2 -0
  6. coregen_cli-3.1.6.dist-info/top_level.txt +2 -0
  7. generators/__init__.py +1 -0
  8. generators/assets/__init__.py +1 -0
  9. generators/assets/assets.py +30 -0
  10. generators/assets/main.py +4 -0
  11. generators/config/__init__.py +1 -0
  12. generators/config/analisy_options.py +42 -0
  13. generators/config/main.py +11 -0
  14. generators/config/pubspec.py +139 -0
  15. generators/cursor/__init__.py +3 -0
  16. generators/cursor/setup.py +87 -0
  17. generators/helpers/__init__.py +56 -0
  18. generators/helpers/component.py +1030 -0
  19. generators/helpers/config.py +255 -0
  20. generators/helpers/data_source.py +180 -0
  21. generators/helpers/domain.py +469 -0
  22. generators/helpers/feature.py +654 -0
  23. generators/helpers/navigation.py +274 -0
  24. generators/helpers/page.py +63 -0
  25. generators/helpers/project.py +33 -0
  26. generators/helpers/utils.py +338 -0
  27. generators/helpers/validation.py +364 -0
  28. generators/initializator.py +68 -0
  29. generators/main.py +81 -0
  30. generators/static/assets/logo.png +0 -0
  31. generators/static/assets/mock/auth_user.json +5 -0
  32. generators/static/assets/svgs/apple.svg +4 -0
  33. generators/static/assets/svgs/google.svg +2 -0
  34. generators/static/cursor/AGENTS.md.jinja +37 -0
  35. generators/static/cursor/agents/doc-writer.md +20 -0
  36. generators/static/cursor/agents/epic-orchestrator.md +28 -0
  37. generators/static/cursor/agents/feature-implementer.md +29 -0
  38. generators/static/cursor/agents/integration-wiring.md +30 -0
  39. generators/static/cursor/agents/layer-application.md +21 -0
  40. generators/static/cursor/agents/layer-guardian.md +21 -0
  41. generators/static/cursor/agents/layer-infrastructure.md +31 -0
  42. generators/static/cursor/agents/layer-model.md +24 -0
  43. generators/static/cursor/agents/layer-presentation.md +33 -0
  44. generators/static/cursor/docs/architecture/APIS_AND_INTEGRATION.md.jinja +42 -0
  45. generators/static/cursor/docs/architecture/CARAVAGGIO_COMPONENTS.md.jinja +317 -0
  46. generators/static/cursor/docs/architecture/DDD_LAYERS.md.jinja +32 -0
  47. generators/static/cursor/docs/architecture/FILE_TEMPLATES.md.jinja +76 -0
  48. generators/static/cursor/docs/architecture/MOCK_AND_REMOTE_DATA.md.jinja +87 -0
  49. generators/static/cursor/docs/architecture/REFERENCE_IMPLEMENTATIONS.md.jinja +48 -0
  50. generators/static/cursor/docs/architecture/WIDGETS_AND_CARAVAGGIO.md.jinja +76 -0
  51. generators/static/cursor/docs/epics/README.md +17 -0
  52. generators/static/cursor/lib/domain/AGENTS.md +23 -0
  53. generators/static/cursor/lib/features/AGENTS.md +23 -0
  54. generators/static/cursor/lib/widgets/AGENTS.md +21 -0
  55. generators/static/cursor/rules/apis-layer.mdc.jinja +21 -0
  56. generators/static/cursor/rules/application-layer.mdc.jinja +12 -0
  57. generators/static/cursor/rules/architecture-core.mdc.jinja +43 -0
  58. generators/static/cursor/rules/dart-conventions.mdc.jinja +14 -0
  59. generators/static/cursor/rules/domain-layer.mdc.jinja +24 -0
  60. generators/static/cursor/rules/login-context.mdc.jinja +16 -0
  61. generators/static/cursor/rules/presentation-layer.mdc.jinja +15 -0
  62. generators/static/cursor/rules/quality-gate.mdc.jinja +14 -0
  63. generators/static/cursor/rules/ui-caravaggio.mdc.jinja +22 -0
  64. generators/static/cursor/skills/caravaggio-ui/SKILL.md +138 -0
  65. generators/static/cursor/skills/epic-delivery/SKILL.md +74 -0
  66. generators/static/cursor/skills/epic-delivery/templates/epic-status.md +14 -0
  67. generators/static/cursor/skills/epic-delivery/templates/epic.md +36 -0
  68. generators/static/templates/apis/common/constants_template.jinja +48 -0
  69. generators/static/templates/apis/common/data_source_config_template.jinja +47 -0
  70. generators/static/templates/apis/core/api_injectable_module_template.jinja +14 -0
  71. generators/static/templates/apis/interceptors/api_logger_template.jinja +135 -0
  72. generators/static/templates/apis/interceptors/auth_interceptor_template.jinja +207 -0
  73. generators/static/templates/auth/application/auth_bloc_template.jinja +36 -0
  74. generators/static/templates/auth/application/auth_event_template.jinja +7 -0
  75. generators/static/templates/auth/application/auth_state_template.jinja +8 -0
  76. generators/static/templates/auth/infrastructure/auth_facade_module_template.jinja +16 -0
  77. generators/static/templates/auth/infrastructure/auth_facade_template.jinja +288 -0
  78. generators/static/templates/auth/infrastructure/mock_auth_facade_template.jinja +106 -0
  79. generators/static/templates/auth/model/auth_failure_template.jinja +11 -0
  80. generators/static/templates/auth/model/i_auth_facade_template.jinja +24 -0
  81. generators/static/templates/auth/model/user_template.jinja +34 -0
  82. generators/static/templates/auth/model/value_objects_template.jinja +54 -0
  83. generators/static/templates/auth/presentation/login_screen_template.jinja +24 -0
  84. generators/static/templates/auth/sign_in_form/application/sign_in_form_bloc_template.jinja +139 -0
  85. generators/static/templates/auth/sign_in_form/application/sign_in_form_event_template.jinja +15 -0
  86. generators/static/templates/auth/sign_in_form/application/sign_in_form_state_template.jinja +26 -0
  87. generators/static/templates/auth/sign_in_form/presentation/apple_form_template.jinja +16 -0
  88. generators/static/templates/auth/sign_in_form/presentation/email_password_form_template_INACTIVE.jinja +94 -0
  89. generators/static/templates/auth/sign_in_form/presentation/google_form_template.jinja +15 -0
  90. generators/static/templates/auth/sign_in_form/presentation/sign_in_form_template.jinja +381 -0
  91. generators/static/templates/component/component_bloc_template.jinja +49 -0
  92. generators/static/templates/component/component_event_template.jinja +7 -0
  93. generators/static/templates/component/component_form_bloc_template.jinja +56 -0
  94. generators/static/templates/component/component_form_event_template.jinja +7 -0
  95. generators/static/templates/component/component_form_state_template.jinja +18 -0
  96. generators/static/templates/component/component_form_widget_template.jinja +130 -0
  97. generators/static/templates/component/component_list_widget_template.jinja +95 -0
  98. generators/static/templates/component/component_state_template.jinja +9 -0
  99. generators/static/templates/component/component_widget_template.jinja +113 -0
  100. generators/static/templates/core/bloc/base_form_bloc_template.jinja +32 -0
  101. generators/static/templates/core/errors/error_localizer_template.jinja +61 -0
  102. generators/static/templates/core/infrastructure/base_mapper_template.jinja +21 -0
  103. generators/static/templates/core/infrastructure/base_repository_mixin_template.jinja +78 -0
  104. generators/static/templates/core/infrastructure/firebase_injectable_module_template.jinja +11 -0
  105. generators/static/templates/core/infrastructure/firestore_helpers_template.jinja +22 -0
  106. generators/static/templates/core/infrastructure/repository_error_handler_template.jinja +44 -0
  107. generators/static/templates/core/model/common_interfaces_template.jinja +3 -0
  108. generators/static/templates/core/model/entity_template.jinja +5 -0
  109. generators/static/templates/core/model/errors_template.jinja +15 -0
  110. generators/static/templates/core/model/failures_template.jinja +97 -0
  111. generators/static/templates/core/model/value_objects_template.jinja +135 -0
  112. generators/static/templates/core/model/value_validators_template.jinja +105 -0
  113. generators/static/templates/core/presentation/app_drawer_template.jinja +52 -0
  114. generators/static/templates/core/presentation/app_widget_template.jinja +41 -0
  115. generators/static/templates/core/presentation/bottom_nav_bar_template.jinja +32 -0
  116. generators/static/templates/domain/domain_mapper_template.jinja +39 -0
  117. generators/static/templates/domain/domain_remote_service_template.jinja +46 -0
  118. generators/static/templates/domain/domain_repository_template.jinja +90 -0
  119. generators/static/templates/domain/domain_service_module_template.jinja +23 -0
  120. generators/static/templates/domain/enum_template.jinja +3 -0
  121. generators/static/templates/domain/i_domain_service_template.jinja +18 -0
  122. generators/static/templates/domain/mock_domain_service_template.jinja +73 -0
  123. generators/static/templates/feature/feature_bloc_template.jinja +104 -0
  124. generators/static/templates/feature/feature_dto_template.jinja +26 -0
  125. generators/static/templates/feature/feature_entity_template.jinja +23 -0
  126. generators/static/templates/feature/feature_event_template.jinja +20 -0
  127. generators/static/templates/feature/feature_extensions_template.jinja +25 -0
  128. generators/static/templates/feature/feature_failure_template.jinja +11 -0
  129. generators/static/templates/feature/feature_page_template.jinja +113 -0
  130. generators/static/templates/feature/feature_repository_template.jinja +112 -0
  131. generators/static/templates/feature/feature_state_template.jinja +20 -0
  132. generators/static/templates/feature/i_feature_repository_template.jinja +21 -0
  133. generators/static/templates/feature/value_object_field_template.jinja +0 -0
  134. generators/static/templates/feature/value_object_template.jinja +0 -0
  135. generators/static/templates/feature/value_validators_template.jinja +57 -0
  136. generators/static/templates/home/home_screen_template.jinja +68 -0
  137. generators/static/templates/home/presentation/home_screen_template.jinja +52 -0
  138. generators/static/templates/home/screen_template.jinja +12 -0
  139. generators/static/templates/injection_template.jinja +8 -0
  140. generators/static/templates/logging/analytics_logging_template.jinja +42 -0
  141. generators/static/templates/logging/console_template.jinja +50 -0
  142. generators/static/templates/logging/logger_injectable_module_template.jinja +24 -0
  143. generators/static/templates/logging/logger_template.jinja +118 -0
  144. generators/static/templates/main_template.jinja +43 -0
  145. generators/static/templates/page_template.jinja +29 -0
  146. generators/static/templates/router_template.jinja +26 -0
  147. generators/static/templates/splash/presentation/splash_screen_auth_template.jinja +97 -0
  148. generators/static/templates/splash/presentation/splash_screen_template.jinja +51 -0
  149. generators/static/templates/storage/storage_repository_template.jinja +80 -0
  150. generators/static/templates/user_profile/infrastructure/user_profile_dto_template.jinja +27 -0
  151. generators/static/templates/user_profile/infrastructure/user_profile_mapper_template.jinja +43 -0
  152. generators/static/templates/user_profile/infrastructure/user_profile_repository_template.jinja +82 -0
  153. generators/static/templates/user_profile/infrastructure/user_profile_service_template.jinja +27 -0
  154. generators/static/templates/user_profile/model/i_user_profile_repository_template.jinja +34 -0
  155. generators/static/templates/user_profile/model/user_profile_failure_template.jinja +11 -0
  156. generators/static/templates/user_profile/model/user_profile_template.jinja +31 -0
  157. generators/static/templates/widgets/common/custom_scaffold_template.jinja +52 -0
  158. generators/static/templates/widgets/common/error_widget_template.jinja +22 -0
  159. generators/static/templates/widgets/common/loading_widget_template.jinja +14 -0
  160. generators/static/templates/widgets/common/unknown_state_widget_template.jinja +23 -0
  161. generators/templates/__init__.py +1 -0
  162. generators/templates/_core/core_generator.py +121 -0
  163. generators/templates/apis/apis_generator.py +50 -0
  164. generators/templates/auth/auth_generator.py +40 -0
  165. generators/templates/auth/sign_in_form_generator.py +22 -0
  166. generators/templates/copier.py +51 -0
  167. generators/templates/home/home_generator.py +26 -0
  168. generators/templates/lib/lib_generator.py +40 -0
  169. generators/templates/logging/logging_generator.py +28 -0
  170. generators/templates/main.py +75 -0
  171. generators/templates/splash/splash_generator.py +20 -0
  172. generators/templates/storage/storage_generator.py +5 -0
@@ -0,0 +1,82 @@
1
+ /*
2
+ * UserProfile repository implementation
3
+ * Provides concrete implementation of IUserProfileRepository
4
+ *
5
+ * NOTE: This is a skeleton implementation. Uncomment and implement
6
+ * the necessary parts to integrate with your backend API or local storage.
7
+ *
8
+ * Implementation options:
9
+ * 1. API integration: Use Retrofit/Dio to call backend endpoints
10
+ * 2. Local storage: Use Hive/SharedPreferences/SQLite for offline support
11
+ * 3. Hybrid: Combine API calls with local caching
12
+ */
13
+
14
+ import 'package:dartz/dartz.dart';
15
+ import 'package:injectable/injectable.dart';
16
+ import 'package:[[project_name]]/domain/auth/model/i_auth_facade.dart';
17
+ import 'package:[[project_name]]/domain/user_profile/model/user_profile.dart';
18
+ import 'package:[[project_name]]/domain/user_profile/model/i_user_profile_repository.dart';
19
+ import 'package:[[project_name]]/domain/user_profile/model/user_profile_failure.dart';
20
+ import 'package:[[project_name]]/domain/user_profile/infrastructure/user_profile_service.dart';
21
+
22
+ @Injectable(as: IUserProfileRepository)
23
+ class UserProfileRepository implements IUserProfileRepository {
24
+ final IAuthFacade _authFacade;
25
+ final UserProfileService _userProfileService;
26
+
27
+ UserProfileRepository(
28
+ this._authFacade,
29
+ this._userProfileService,
30
+ );
31
+
32
+ @override
33
+ Future<Either<UserProfileFailure, UserProfile>> getCurrentUserProfile() async {
34
+ // Example implementation:
35
+ // try {
36
+ // final dto = await _userProfileService.getCurrentUserProfile();
37
+ // return right(dto.toDomain());
38
+ // } catch (e) {
39
+ // return left(const UserProfileFailure.unexpected());
40
+ // }
41
+
42
+ return left(const UserProfileFailure.unexpected());
43
+ }
44
+
45
+ @override
46
+ Future<Either<UserProfileFailure, UserProfile>> updateCurrentUserProfile(UserProfile userProfile) async {
47
+ // Example implementation:
48
+ // try {
49
+ // final updateData = {
50
+ // 'name': userProfile.name.getOrCrash(),
51
+ // 'avatar_url': userProfile.avatarUrl.fold(() => null, (url) => url),
52
+ // };
53
+ // await _userProfileService.updateCurrentUserProfile(updateData);
54
+ // final dto = await _userProfileService.getCurrentUserProfile();
55
+ // return right(dto.toDomain());
56
+ // } catch (e) {
57
+ // return left(const UserProfileFailure.unableToUpdate());
58
+ // }
59
+
60
+ return left(const UserProfileFailure.unableToUpdate());
61
+ }
62
+
63
+ @override
64
+ Future<Either<UserProfileFailure, String>> uploadAvatar(String filePath) async {
65
+ // Example implementation:
66
+ // try {
67
+ // // Upload file to storage (e.g., Supabase, Firebase Storage)
68
+ // // Return the public URL of the uploaded file
69
+ // return right('https://example.com/avatar.png');
70
+ // } catch (e) {
71
+ // return left(const UserProfileFailure.unexpected());
72
+ // }
73
+
74
+ return left(const UserProfileFailure.unexpected());
75
+ }
76
+
77
+ @override
78
+ Future<Either<UserProfileFailure, void>> logout() async {
79
+ await _authFacade.signOut();
80
+ return right(unit);
81
+ }
82
+ }
@@ -0,0 +1,27 @@
1
+ import 'package:dio/dio.dart';
2
+ import 'package:injectable/injectable.dart';
3
+ import 'package:[[project_name]]/apis/common/constants.dart';
4
+ import 'package:[[project_name]]/domain/user_profile/infrastructure/user_profile_dto.dart';
5
+ import 'package:retrofit/retrofit.dart';
6
+
7
+ part 'user_profile_service.g.dart';
8
+
9
+ @module
10
+ abstract class UserProfileRemoteModule {
11
+ @lazySingleton
12
+ UserProfileService userProfileService(Dio dio) {
13
+ return UserProfileService(dio, baseUrl: Constants.dioBaseUrl);
14
+ }
15
+ }
16
+
17
+ @RestApi()
18
+ abstract class UserProfileService {
19
+ @factoryMethod
20
+ factory UserProfileService(Dio dio, {String baseUrl}) = _UserProfileService;
21
+
22
+ @GET('/get-user-profile')
23
+ Future<UserProfileDto> getCurrentUserProfile();
24
+
25
+ @PATCH('/update-user-profile')
26
+ Future<void> updateCurrentUserProfile(@Body() Map<String, dynamic> userProfileDto);
27
+ }
@@ -0,0 +1,34 @@
1
+ /*
2
+ * UserProfile repository interface
3
+ * Defines the contract for UserProfile data operations:
4
+ * - Get current user profile
5
+ * - Update current user profile
6
+ * - Upload avatar
7
+ * - Logout
8
+ * - Uses Either type for error handling (Left = UserProfileFailure, Right = success)
9
+ *
10
+ * This interface allows different implementations (API, local storage, etc.)
11
+ * while keeping the business logic independent of data source
12
+ */
13
+
14
+ import 'package:dartz/dartz.dart';
15
+ import 'package:[[project_name]]/domain/user_profile/model/user_profile.dart';
16
+ import 'package:[[project_name]]/domain/user_profile/model/user_profile_failure.dart';
17
+
18
+ abstract class IUserProfileRepository {
19
+ /// Get the current user's profile
20
+ /// Returns the UserProfile if found, otherwise returns UserProfileFailure
21
+ Future<Either<UserProfileFailure, UserProfile>> getCurrentUserProfile();
22
+
23
+ /// Update the current user's profile
24
+ /// Returns the updated UserProfile or UserProfileFailure if operation fails
25
+ Future<Either<UserProfileFailure, UserProfile>> updateCurrentUserProfile(UserProfile userProfile);
26
+
27
+ /// Upload user avatar
28
+ /// Uploads the image at filePath to storage and returns the public URL
29
+ Future<Either<UserProfileFailure, String>> uploadAvatar(String filePath);
30
+
31
+ /// Logout user
32
+ /// Returns the result of the logout operation
33
+ Future<Either<UserProfileFailure, void>> logout();
34
+ }
@@ -0,0 +1,11 @@
1
+ import 'package:freezed_annotation/freezed_annotation.dart';
2
+
3
+ part 'user_profile_failure.freezed.dart';
4
+
5
+ @freezed
6
+ abstract class UserProfileFailure with _$UserProfileFailure {
7
+ const factory UserProfileFailure.unexpected() = Unexpected;
8
+ const factory UserProfileFailure.insufficientPermission() = InsufficientPermission;
9
+ const factory UserProfileFailure.unableToUpdate() = UnableToUpdate;
10
+ const factory UserProfileFailure.notFound() = NotFound;
11
+ }
@@ -0,0 +1,31 @@
1
+ /*
2
+ * UserProfile entity template
3
+ * Represents the user profile stored in the application database
4
+ *
5
+ * This entity is separate from the authentication User entity:
6
+ * - User (auth): Used by AuthBloc and authentication flow
7
+ * - UserProfile (database): Extended profile with additional fields
8
+ *
9
+ * Both entities use the same ID (authId) to correlate them.
10
+ * The UserProfile is automatically created/updated when a user authenticates.
11
+ */
12
+
13
+ import 'package:dartz/dartz.dart';
14
+ import 'package:freezed_annotation/freezed_annotation.dart';
15
+ import 'package:[[project_name]]/domain/auth/model/value_objects.dart';
16
+ import 'package:[[project_name]]/core/model/entity.dart';
17
+ import 'package:[[project_name]]/core/model/value_objects.dart';
18
+
19
+ part 'user_profile.freezed.dart';
20
+
21
+ @freezed
22
+ abstract class UserProfile with _$UserProfile implements IEntity {
23
+ const factory UserProfile({
24
+ required UniqueId id,
25
+ required StringSingleLine name,
26
+ required EmailAddress emailAddress,
27
+ required Option<String> avatarUrl,
28
+ required DateTime createdAt,
29
+ required DateTime updatedAt,
30
+ }) = _UserProfile;
31
+ }
@@ -0,0 +1,52 @@
1
+ import 'package:caravaggio_ui/caravaggio_ui.dart';
2
+ import 'package:flutter/material.dart';
3
+
4
+ /// App-level scaffold wrapping [CScaffold] with project defaults.
5
+ class CustomScaffold extends StatelessWidget {
6
+ const CustomScaffold({
7
+ super.key,
8
+ this.body,
9
+ this.bodyBuilder,
10
+ this.title,
11
+ this.action,
12
+ this.leading,
13
+ this.drawer,
14
+ this.scrollController,
15
+ this.showBackButton = true,
16
+ this.hideTitleOnScroll = true,
17
+ this.titleAlignment = Alignment.centerLeft,
18
+ this.onBackPressed,
19
+ });
20
+
21
+ final Widget? body;
22
+ final Widget Function(BuildContext context, double topPadding)? bodyBuilder;
23
+ final Widget? title;
24
+ final Widget? action;
25
+ final Widget? leading;
26
+ final Widget? drawer;
27
+ final ScrollController? scrollController;
28
+ final bool showBackButton;
29
+ final bool hideTitleOnScroll;
30
+ final Alignment titleAlignment;
31
+ final VoidCallback? onBackPressed;
32
+
33
+ /// Returns the top padding from the nearest [CustomScaffold] / [CScaffold].
34
+ static double? topPaddingOf(BuildContext context) => CScaffold.topPaddingOf(context);
35
+
36
+ @override
37
+ Widget build(BuildContext context) {
38
+ return CScaffold(
39
+ body: body,
40
+ bodyBuilder: bodyBuilder,
41
+ title: title,
42
+ action: action,
43
+ leading: leading,
44
+ drawer: drawer,
45
+ scrollController: scrollController,
46
+ showBackButton: showBackButton,
47
+ hideTitleOnScroll: hideTitleOnScroll,
48
+ titleAlignment: titleAlignment,
49
+ onBackPressed: onBackPressed,
50
+ );
51
+ }
52
+ }
@@ -0,0 +1,22 @@
1
+ import 'package:caravaggio_ui/caravaggio_ui.dart';
2
+ import 'package:flutter/material.dart' hide ErrorWidget;
3
+
4
+ /// Messaggio di errore già localizzato o pronto per la UI.
5
+ class ErrorWidget extends StatelessWidget {
6
+ const ErrorWidget({super.key, required this.message});
7
+
8
+ final String message;
9
+
10
+ @override
11
+ Widget build(BuildContext context) {
12
+ return Center(
13
+ child: Padding(
14
+ padding: const EdgeInsets.all(16),
15
+ child: CText.body(
16
+ message,
17
+ textAlign: TextAlign.center,
18
+ ),
19
+ ),
20
+ );
21
+ }
22
+ }
@@ -0,0 +1,14 @@
1
+ import 'package:caravaggio_ui/caravaggio_ui.dart';
2
+ import 'package:flutter/material.dart';
3
+
4
+ /// Indicatore di caricamento condiviso (wrapper su [CLoader]).
5
+ class LoadingWidget extends StatelessWidget {
6
+ const LoadingWidget({super.key});
7
+
8
+ @override
9
+ Widget build(BuildContext context) {
10
+ return Center(
11
+ child: CLoader.bouncing(),
12
+ );
13
+ }
14
+ }
@@ -0,0 +1,23 @@
1
+ import 'package:caravaggio_ui/caravaggio_ui.dart';
2
+ import 'package:flutter/material.dart';
3
+
4
+ /// Stato del BLoC non previsto dal widget (fallback).
5
+ class UnknownStateWidget extends StatelessWidget {
6
+ const UnknownStateWidget({super.key, this.hint});
7
+
8
+ /// Testo opzionale per debug o supporto.
9
+ final String? hint;
10
+
11
+ @override
12
+ Widget build(BuildContext context) {
13
+ return Center(
14
+ child: Padding(
15
+ padding: const EdgeInsets.all(16),
16
+ child: CText.body(
17
+ hint ?? 'Stato non gestito',
18
+ textAlign: TextAlign.center,
19
+ ),
20
+ ),
21
+ );
22
+ }
23
+ }
@@ -0,0 +1 @@
1
+ from .main import generate_files
@@ -0,0 +1,121 @@
1
+ from pathlib import Path
2
+ from ..copier import generate_file
3
+
4
+
5
+ def infer_has_login(lib_path: Path) -> bool:
6
+ """Detect whether the project includes generated auth/sign-in (``coregen create --login``).
7
+
8
+ Used when regenerating ``error_localizer.dart`` outside of ``create`` (e.g. ``add-domain``),
9
+ so ``localizeAuthFailure`` is preserved.
10
+ """
11
+ return (
12
+ lib_path / "features" / "auth" / "sign_in_form" / "presentation" / "sign_in_form.dart"
13
+ ).exists()
14
+
15
+
16
+ def generate_files(project_name: str, lib_path: Path, has_login: bool):
17
+ generate_app_widget(project_name, lib_path, has_login)
18
+ generate_model(project_name, lib_path)
19
+ generate_infrastructure(project_name, lib_path)
20
+ generate_error_localizer(project_name, lib_path, domain_folder="domain", has_login=has_login)
21
+ generate_common_widgets(project_name, lib_path)
22
+
23
+
24
+ def generate_common_widgets(project_name: str, lib_path: Path) -> None:
25
+ """Write shared UI widgets under lib/widgets/common/ (new project create)."""
26
+ generate_file(project_name, lib_path, "widgets/common/custom_scaffold_template.jinja", "widgets/common/custom_scaffold.dart")
27
+ generate_file(project_name, lib_path, "widgets/common/loading_widget_template.jinja", "widgets/common/loading_widget.dart")
28
+ generate_file(project_name, lib_path, "widgets/common/error_widget_template.jinja", "widgets/common/error_widget.dart")
29
+ generate_file(project_name, lib_path, "widgets/common/unknown_state_widget_template.jinja", "widgets/common/unknown_state_widget.dart")
30
+
31
+
32
+ def ensure_common_widgets(project_name: str, lib_path: Path) -> None:
33
+ """Ensure lib/widgets/common exists (e.g. add-component on older projects)."""
34
+ if (lib_path / "widgets" / "common" / "loading_widget.dart").exists():
35
+ return
36
+ generate_common_widgets(project_name, lib_path)
37
+
38
+ def generate_model(project_name: str, lib_path: Path):
39
+ generate_common_interfaces(project_name, lib_path)
40
+ generate_entity(project_name, lib_path)
41
+ generate_errors(project_name, lib_path)
42
+ generate_failures(project_name, lib_path)
43
+ generate_value_objects(project_name, lib_path)
44
+ generate_value_validators(project_name, lib_path)
45
+
46
+ def generate_infrastructure(project_name: str, lib_path: Path):
47
+ generate_file(project_name, lib_path, "core/infrastructure/base_mapper_template.jinja", "core/infrastructure/base_mapper.dart")
48
+ generate_file(project_name, lib_path, "core/infrastructure/repository_error_handler_template.jinja", "core/infrastructure/repository_error_handler.dart")
49
+ generate_file(project_name, lib_path, "core/infrastructure/base_repository_mixin_template.jinja", "core/infrastructure/base_repository_mixin.dart")
50
+
51
+
52
+ def generate_error_localizer(project_name: str, lib_path: Path, domain_folder: str = "domain", has_login: bool = False):
53
+ """Generate error_localizer.dart with a localize method per domain failure.
54
+
55
+ Scans ``lib_path / domain_folder`` for domain models that have a
56
+ corresponding ``*_failure.dart`` file and builds the template context
57
+ so the error localizer contains one method per domain failure.
58
+
59
+ ``localizeAuthFailure`` is emitted when login UI was generated (``has_login``)
60
+ **or** when ``domain/auth/model/auth_failure.dart`` exists, so sign-in code
61
+ can localize errors even on projects created without ``--login``.
62
+ """
63
+ from generators.helpers.feature import find_domain_models_with_class_names
64
+
65
+ auth_failure_path = lib_path / domain_folder / "auth" / "model" / "auth_failure.dart"
66
+ include_auth_failure_localizer = bool(has_login or auth_failure_path.is_file())
67
+
68
+ domain_failures = []
69
+ models = find_domain_models_with_class_names(lib_path, domain_folder) if lib_path.exists() else {}
70
+
71
+ for file_stem, info in sorted(models.items()):
72
+ failure_file = lib_path / domain_folder / info['folder'] / "model" / f"{file_stem}_failure.dart"
73
+ if not failure_file.exists():
74
+ continue
75
+
76
+ class_name = info['class_name']
77
+ failure_class = f"{class_name}Failure"
78
+ # Dedicated AuthFailure block below; skip generic template for entity stem "auth".
79
+ if include_auth_failure_localizer and file_stem == "auth" and failure_class == "AuthFailure":
80
+ continue
81
+ alias = f"{file_stem}_failure"
82
+ import_path = f"{project_name}/{domain_folder}/{info['folder']}/model/{file_stem}_failure.dart"
83
+
84
+ domain_failures.append({
85
+ "import_path": import_path,
86
+ "alias": alias,
87
+ "failure_class": failure_class,
88
+ "class_name": class_name,
89
+ })
90
+
91
+ generate_file(
92
+ project_name, lib_path,
93
+ "core/errors/error_localizer_template.jinja",
94
+ "core/errors/error_localizer.dart",
95
+ {"domain_failures": domain_failures, "has_login": include_auth_failure_localizer},
96
+ )
97
+
98
+
99
+ def generate_app_widget(project_name: str, lib_path: Path, has_login: bool):
100
+ """Generate app widget file using Jinja template"""
101
+ generate_file(project_name, lib_path, "core/presentation/app_widget_template.jinja", "core/presentation/app_widget.dart", {
102
+ "has_login": has_login
103
+ })
104
+
105
+ def generate_common_interfaces(project_name: str, lib_path: Path):
106
+ generate_file(project_name, lib_path, "core/model/common_interfaces_template.jinja", "core/model/common_interfaces.dart")
107
+
108
+ def generate_entity(project_name: str, lib_path: Path):
109
+ generate_file(project_name, lib_path, "core/model/entity_template.jinja", "core/model/entity.dart")
110
+
111
+ def generate_errors(project_name: str, lib_path: Path):
112
+ generate_file(project_name, lib_path, "core/model/errors_template.jinja", "core/model/errors.dart")
113
+
114
+ def generate_failures(project_name: str, lib_path: Path):
115
+ generate_file(project_name, lib_path, "core/model/failures_template.jinja", "core/model/failures.dart")
116
+
117
+ def generate_value_objects(project_name: str, lib_path: Path):
118
+ generate_file(project_name, lib_path, "core/model/value_objects_template.jinja", "core/model/value_objects.dart")
119
+
120
+ def generate_value_validators(project_name: str, lib_path: Path):
121
+ generate_file(project_name, lib_path, "core/model/value_validators_template.jinja", "core/model/value_validators.dart")
@@ -0,0 +1,50 @@
1
+ from pathlib import Path
2
+ from ..copier import generate_file
3
+ from generators.helpers.data_source import regenerate_data_source_config
4
+
5
+
6
+ def generate_files(project_name: str, lib_path: Path, has_login: bool = False):
7
+ generate_common(project_name, lib_path, has_login=has_login)
8
+ generate_core(project_name, lib_path)
9
+ generate_interceptors(project_name, lib_path, has_login=has_login)
10
+
11
+
12
+ def generate_common(project_name: str, lib_path: Path, has_login: bool = False):
13
+ generate_constants(project_name, lib_path)
14
+ regenerate_data_source_config(
15
+ project_name,
16
+ lib_path,
17
+ domain_folder="domain",
18
+ has_login=has_login,
19
+ )
20
+
21
+
22
+ def generate_core(project_name: str, lib_path: Path):
23
+ generate_api_injectable_module(project_name, lib_path)
24
+
25
+
26
+ def generate_interceptors(project_name: str, lib_path: Path, has_login: bool = False):
27
+ generate_api_logger(project_name, lib_path)
28
+ generate_auth_interceptor(project_name, lib_path, has_login=has_login)
29
+
30
+
31
+ def generate_constants(project_name: str, lib_path: Path):
32
+ generate_file(project_name, lib_path, "apis/common/constants_template.jinja", "apis/common/constants.dart")
33
+
34
+
35
+ def generate_api_injectable_module(project_name: str, lib_path: Path):
36
+ generate_file(project_name, lib_path, "apis/core/api_injectable_module_template.jinja", "apis/core/api_injectable_module.dart")
37
+
38
+
39
+ def generate_api_logger(project_name: str, lib_path: Path):
40
+ generate_file(project_name, lib_path, "apis/interceptors/api_logger_template.jinja", "apis/interceptors/api_logger.dart")
41
+
42
+
43
+ def generate_auth_interceptor(project_name: str, lib_path: Path, has_login: bool = False):
44
+ generate_file(
45
+ project_name,
46
+ lib_path,
47
+ "apis/interceptors/auth_interceptor_template.jinja",
48
+ "apis/interceptors/auth_interceptor.dart",
49
+ {"has_login": has_login},
50
+ )
@@ -0,0 +1,40 @@
1
+ from pathlib import Path
2
+ from ..copier import generate_file
3
+
4
+ def generate_files(project_name: str, lib_path: Path):
5
+ generate_presentation(project_name, lib_path)
6
+ generate_model(project_name, lib_path)
7
+ generate_application(project_name, lib_path)
8
+ generate_infrastructure(project_name, lib_path)
9
+ generate_user_profile(project_name, lib_path)
10
+
11
+ def generate_presentation(project_name: str, lib_path: Path):
12
+ generate_file(project_name, lib_path, "auth/presentation/login_screen_template.jinja", "features/auth/presentation/login_page.dart")
13
+
14
+ def generate_model(project_name: str, lib_path: Path):
15
+ generate_file(project_name, lib_path, "auth/model/auth_failure_template.jinja", "domain/auth/model/auth_failure.dart")
16
+ generate_file(project_name, lib_path, "auth/model/i_auth_facade_template.jinja", "domain/auth/model/i_auth_facade.dart")
17
+ generate_file(project_name, lib_path, "auth/model/user_template.jinja", "domain/auth/model/user.dart")
18
+ generate_file(project_name, lib_path, "auth/model/value_objects_template.jinja", "domain/auth/model/value_objects.dart")
19
+
20
+ def generate_application(project_name: str, lib_path: Path):
21
+ generate_file(project_name, lib_path, "auth/application/auth_bloc_template.jinja", "features/auth/application/auth_bloc.dart")
22
+ generate_file(project_name, lib_path, "auth/application/auth_event_template.jinja", "features/auth/application/auth_event.dart")
23
+ generate_file(project_name, lib_path, "auth/application/auth_state_template.jinja", "features/auth/application/auth_state.dart")
24
+
25
+ def generate_infrastructure(project_name: str, lib_path: Path):
26
+ generate_file(project_name, lib_path, "auth/infrastructure/auth_facade_template.jinja", "domain/auth/infrastructure/auth_facade.dart")
27
+ generate_file(project_name, lib_path, "auth/infrastructure/mock_auth_facade_template.jinja", "domain/auth/infrastructure/mock_auth_facade.dart")
28
+ generate_file(project_name, lib_path, "auth/infrastructure/auth_facade_module_template.jinja", "domain/auth/infrastructure/auth_facade_module.dart")
29
+
30
+ def generate_user_profile(project_name: str, lib_path: Path):
31
+ """Generate user_profile domain as a separate domain entity."""
32
+ # Model layer
33
+ generate_file(project_name, lib_path, "user_profile/model/user_profile_template.jinja", "domain/user_profile/model/user_profile.dart")
34
+ generate_file(project_name, lib_path, "user_profile/model/user_profile_failure_template.jinja", "domain/user_profile/model/user_profile_failure.dart")
35
+ generate_file(project_name, lib_path, "user_profile/model/i_user_profile_repository_template.jinja", "domain/user_profile/model/i_user_profile_repository.dart")
36
+ # Infrastructure layer
37
+ generate_file(project_name, lib_path, "user_profile/infrastructure/user_profile_dto_template.jinja", "domain/user_profile/infrastructure/user_profile_dto.dart")
38
+ generate_file(project_name, lib_path, "user_profile/infrastructure/user_profile_mapper_template.jinja", "domain/user_profile/infrastructure/user_profile_mapper.dart")
39
+ generate_file(project_name, lib_path, "user_profile/infrastructure/user_profile_repository_template.jinja", "domain/user_profile/infrastructure/user_profile_repository.dart")
40
+ generate_file(project_name, lib_path, "user_profile/infrastructure/user_profile_service_template.jinja", "domain/user_profile/infrastructure/user_profile_service.dart")
@@ -0,0 +1,22 @@
1
+ from pathlib import Path
2
+ from ..copier import generate_file
3
+
4
+ def generate_files(project_name: str, lib_path: Path):
5
+ generate_presentation(project_name, lib_path)
6
+ generate_model(project_name, lib_path)
7
+ generate_application(project_name, lib_path)
8
+ generate_infrastructure(project_name, lib_path)
9
+
10
+ def generate_presentation(project_name: str, lib_path: Path):
11
+ generate_file(project_name, lib_path, "auth/sign_in_form/presentation/sign_in_form_template.jinja", "features/auth/sign_in_form/presentation/sign_in_form.dart")
12
+
13
+ def generate_model(project_name: str, lib_path: Path):
14
+ pass
15
+
16
+ def generate_application(project_name: str, lib_path: Path):
17
+ generate_file(project_name, lib_path, "auth/sign_in_form/application/sign_in_form_bloc_template.jinja", "features/auth/sign_in_form/application/sign_in_form_bloc.dart")
18
+ generate_file(project_name, lib_path, "auth/sign_in_form/application/sign_in_form_event_template.jinja", "features/auth/sign_in_form/application/sign_in_form_event.dart")
19
+ generate_file(project_name, lib_path, "auth/sign_in_form/application/sign_in_form_state_template.jinja", "features/auth/sign_in_form/application/sign_in_form_state.dart")
20
+
21
+ def generate_infrastructure(project_name: str, lib_path: Path):
22
+ pass
@@ -0,0 +1,51 @@
1
+ from pathlib import Path
2
+ from jinja2 import Template
3
+
4
+
5
+ BASE_DIR = Path(__file__).parent
6
+ TEMPLATE_DIR = BASE_DIR.parent / "static" / "templates"
7
+
8
+ def hex_to_dart_color(hex_color: str) -> str:
9
+ """
10
+ Convert hex color string to Dart Color object.
11
+
12
+ Args:
13
+ hex_color: Hex color string (e.g., "#2196F3" or "2196F3")
14
+
15
+ Returns:
16
+ Dart Color string (e.g., "Color(0xFF2196F3)")
17
+ """
18
+ # Remove # if present
19
+ hex_color = hex_color.lstrip('#')
20
+
21
+ # Ensure it's 6 characters
22
+ if len(hex_color) != 6:
23
+ # Default to blue if invalid
24
+ hex_color = "2196F3"
25
+
26
+ # Convert to uppercase for consistency
27
+ hex_color = hex_color.upper()
28
+
29
+ # Return Dart Color format
30
+ return f"Color(0xFF{hex_color})"
31
+
32
+ def generate_file(project_name: str, lib_path: Path, template_name: str, output_path: str, args: dict = None):
33
+ template_content = (TEMPLATE_DIR / template_name).read_text()
34
+
35
+ # Use custom delimiters to avoid conflicts with Dart string interpolation
36
+ template = Template(template_content, variable_start_string='[[', variable_end_string=']]')
37
+
38
+ # Prepare variables for substitution
39
+ template_vars = {"project_name": project_name, "feature_name": args.get("feature_name", "") if args else ""}
40
+ if args:
41
+ template_vars.update(args)
42
+
43
+ # Add special variables for complex expressions
44
+ template_vars.update({
45
+ "err_response_statusMessage": "err.response?.statusMessage",
46
+ })
47
+
48
+ content = template.render(**template_vars)
49
+ output_file = lib_path / output_path
50
+ output_file.parent.mkdir(parents=True, exist_ok=True)
51
+ output_file.write_text(content)
@@ -0,0 +1,26 @@
1
+ from pathlib import Path
2
+ from ..copier import generate_file
3
+
4
+ def generate_files(project_name: str, lib_path: Path, has_login: bool = False):
5
+ generate_presentation(project_name, lib_path, has_login)
6
+ generate_model(project_name, lib_path)
7
+ generate_application(project_name, lib_path)
8
+ generate_infrastructure(project_name, lib_path)
9
+
10
+ def generate_presentation(project_name: str, lib_path: Path, has_login: bool = False):
11
+ generate_file(
12
+ project_name,
13
+ lib_path,
14
+ "home/presentation/home_screen_template.jinja",
15
+ "features/home/home_page.dart",
16
+ {"has_login": has_login},
17
+ )
18
+
19
+ def generate_model(project_name: str, lib_path: Path):
20
+ pass
21
+
22
+ def generate_application(project_name: str, lib_path: Path):
23
+ pass
24
+
25
+ def generate_infrastructure(project_name: str, lib_path: Path):
26
+ pass