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,104 @@
1
+ /*
2
+ * BLoC (Business Logic Component) template for feature management
3
+ * Generates a fully functional BLoC with CRUD operations:
4
+ * - Load: Fetch all items from repository
5
+ * - Create: Add new item
6
+ * - Update: Modify existing item
7
+ * - Delete: Remove item
8
+ *
9
+ * Uses:
10
+ * - Freezed for immutable state/events
11
+ * - Repository pattern for data access
12
+ */
13
+
14
+ import 'package:bloc/bloc.dart';
15
+ import 'package:dartz/dartz.dart';
16
+ import 'package:freezed_annotation/freezed_annotation.dart';
17
+ import 'package:[[feature_import_prefix]]/model/[[feature_name]].dart';
18
+ import 'package:[[feature_import_prefix]]/model/[[feature_name]]_failure.dart';
19
+ import 'package:[[feature_import_prefix]]/model/i_[[feature_name]]_repository.dart';
20
+
21
+ part '[[feature_name]]_event.dart';
22
+ part '[[feature_name]]_state.dart';
23
+
24
+ part '[[feature_name]]_bloc.freezed.dart';
25
+
26
+ class [[feature_name.capitalize()]]Bloc extends Bloc<[[feature_name.capitalize()]]Event, [[feature_name.capitalize()]]State> {
27
+ final I[[feature_name.capitalize()]]Repository _repository;
28
+
29
+ [[feature_name.capitalize()]]Bloc(this._repository) : super(const [[feature_name.capitalize()]]State.initial()) {
30
+ on<LoadRequested>(_onLoadRequested);
31
+ on<CreateRequested>(_onCreateRequested);
32
+ on<UpdateRequested>(_onUpdateRequested);
33
+ on<DeleteRequested>(_onDeleteRequested);
34
+ }
35
+
36
+ Future<void> _onLoadRequested(LoadRequested event, Emitter<[[feature_name.capitalize()]]State> emit) async {
37
+ emit(const [[feature_name.capitalize()]]State.loading());
38
+ final Either<[[feature_name.capitalize()]]Failure, List<[[feature_name.capitalize()]]>> result =
39
+ await _repository.getAll();
40
+ result.fold(
41
+ ([[feature_name.capitalize()]]Failure failure) =>
42
+ emit([[feature_name.capitalize()]]State.error(failure.toString())),
43
+ (List<[[feature_name.capitalize()]]> items) =>
44
+ emit([[feature_name.capitalize()]]State.loaded(items)),
45
+ );
46
+ }
47
+
48
+ Future<void> _onCreateRequested(CreateRequested event, Emitter<[[feature_name.capitalize()]]State> emit) async {
49
+ emit(const [[feature_name.capitalize()]]State.loading());
50
+ final Either<[[feature_name.capitalize()]]Failure, Unit> result = await _repository.create(event.item);
51
+ result.fold(
52
+ ([[feature_name.capitalize()]]Failure failure) =>
53
+ emit([[feature_name.capitalize()]]State.error(failure.toString())),
54
+ (Unit _) async {
55
+ final Either<[[feature_name.capitalize()]]Failure, List<[[feature_name.capitalize()]]>> itemsResult =
56
+ await _repository.getAll();
57
+ itemsResult.fold(
58
+ ([[feature_name.capitalize()]]Failure failure) =>
59
+ emit([[feature_name.capitalize()]]State.error(failure.toString())),
60
+ (List<[[feature_name.capitalize()]]> items) =>
61
+ emit([[feature_name.capitalize()]]State.loaded(items)),
62
+ );
63
+ },
64
+ );
65
+ }
66
+
67
+ Future<void> _onUpdateRequested(UpdateRequested event, Emitter<[[feature_name.capitalize()]]State> emit) async {
68
+ emit(const [[feature_name.capitalize()]]State.loading());
69
+ final Either<[[feature_name.capitalize()]]Failure, Unit> result = await _repository.update(event.item);
70
+ result.fold(
71
+ ([[feature_name.capitalize()]]Failure failure) =>
72
+ emit([[feature_name.capitalize()]]State.error(failure.toString())),
73
+ (Unit _) async {
74
+ final Either<[[feature_name.capitalize()]]Failure, List<[[feature_name.capitalize()]]>> itemsResult =
75
+ await _repository.getAll();
76
+ itemsResult.fold(
77
+ ([[feature_name.capitalize()]]Failure failure) =>
78
+ emit([[feature_name.capitalize()]]State.error(failure.toString())),
79
+ (List<[[feature_name.capitalize()]]> items) =>
80
+ emit([[feature_name.capitalize()]]State.loaded(items)),
81
+ );
82
+ },
83
+ );
84
+ }
85
+
86
+ Future<void> _onDeleteRequested(DeleteRequested event, Emitter<[[feature_name.capitalize()]]State> emit) async {
87
+ emit(const [[feature_name.capitalize()]]State.loading());
88
+ final Either<[[feature_name.capitalize()]]Failure, Unit> result = await _repository.delete(event.id);
89
+ result.fold(
90
+ ([[feature_name.capitalize()]]Failure failure) =>
91
+ emit([[feature_name.capitalize()]]State.error(failure.toString())),
92
+ (Unit _) async {
93
+ final Either<[[feature_name.capitalize()]]Failure, List<[[feature_name.capitalize()]]>> itemsResult =
94
+ await _repository.getAll();
95
+ itemsResult.fold(
96
+ ([[feature_name.capitalize()]]Failure failure) =>
97
+ emit([[feature_name.capitalize()]]State.error(failure.toString())),
98
+ (List<[[feature_name.capitalize()]]> items) =>
99
+ emit([[feature_name.capitalize()]]State.loaded(items)),
100
+ );
101
+ },
102
+ );
103
+ }
104
+ }
@@ -0,0 +1,26 @@
1
+ /*
2
+ * Data Transfer Object (DTO) template for API communication
3
+ * Generates a serializable class for network data transfer with:
4
+ * - JSON serialization/deserialization
5
+ * - Freezed for immutability and code generation
6
+ * - Automatic fromJson/toJson methods
7
+ *
8
+ * DTOs represent the data structure expected by the API
9
+ * and are mapped to/from domain entities in repositories
10
+ */
11
+
12
+ import 'package:freezed_annotation/freezed_annotation.dart';
13
+ [[dto_imports]]
14
+
15
+ part '[[file_name]]_dto.freezed.dart';
16
+ part '[[file_name]]_dto.g.dart';
17
+
18
+ @freezed
19
+ abstract class [[feature_name]]Dto with _$[[feature_name]]Dto {
20
+ const factory [[feature_name]]Dto({
21
+ [[fields]]
22
+ }) = _[[feature_name]]Dto;
23
+
24
+ factory [[feature_name]]Dto.fromJson(Map<String, dynamic> json) =>
25
+ _$[[feature_name]]DtoFromJson(json);
26
+ }
@@ -0,0 +1,23 @@
1
+ /*
2
+ * Entity/Model template for domain objects
3
+ * Generates an immutable data class using Freezed package
4
+ * Represents core business objects with:
5
+ * - Value object integration for type safety
6
+ * - Immutable properties
7
+ * - Auto-generated equality and copyWith methods
8
+ *
9
+ * This is the domain layer model that represents business entities
10
+ */
11
+
12
+ import 'package:freezed_annotation/freezed_annotation.dart';
13
+ import 'package:[[project_name]]/core/model/value_objects.dart';
14
+ [[entity_import]]
15
+
16
+ part '[[file_name]].freezed.dart';
17
+
18
+ @freezed
19
+ abstract class [[feature_name]] with _$[[feature_name]] {
20
+ const factory [[feature_name]]({
21
+ [[fields]]
22
+ }) = _[[feature_name]];
23
+ }
@@ -0,0 +1,20 @@
1
+ /*
2
+ * BLoC events template for feature operations
3
+ * Defines immutable events using Freezed that trigger BLoC actions:
4
+ * - LoadRequested: Fetch all items
5
+ * - CreateRequested: Create new item
6
+ * - UpdateRequested: Update existing item
7
+ * - DeleteRequested: Remove item by ID
8
+ *
9
+ * Events represent user intentions and trigger state changes
10
+ */
11
+
12
+ part of '[[feature_name]]_bloc.dart';
13
+
14
+ @freezed
15
+ abstract class [[feature_name.capitalize()]]Event with _$[[feature_name.capitalize()]]Event {
16
+ const factory [[feature_name.capitalize()]]Event.loadRequested() = LoadRequested;
17
+ const factory [[feature_name.capitalize()]]Event.createRequested([[feature_name.capitalize()]] item) = CreateRequested;
18
+ const factory [[feature_name.capitalize()]]Event.updateRequested([[feature_name.capitalize()]] item) = UpdateRequested;
19
+ const factory [[feature_name.capitalize()]]Event.deleteRequested(String id) = DeleteRequested;
20
+ }
@@ -0,0 +1,25 @@
1
+ /*
2
+ * Extension methods template for data mapping
3
+ * Generates conversion methods between domain and infrastructure layers:
4
+ * - DTO to Domain: Convert API data to business objects
5
+ * - Domain to DTO: Convert business objects for API calls
6
+ *
7
+ * These extensions provide clean separation between:
8
+ * - Domain layer (business logic)
9
+ * - Infrastructure layer (API communication)
10
+ */
11
+
12
+ import 'package:[[project_name]]/[[feature_name]]/model/[[feature_name]].dart';
13
+ import 'package:[[project_name]]/[[feature_name]]/infrastructure/[[feature_name]]_dto.dart';
14
+
15
+ extension [[feature_name.capitalize()]]DtoX on [[feature_name.capitalize()]]Dto {
16
+ [[feature_name.capitalize()]] toDomain() => [[feature_name.capitalize()]](
17
+ [[dto_to_domain_fields]]
18
+ );
19
+ }
20
+
21
+ extension [[feature_name.capitalize()]]X on [[feature_name.capitalize()]] {
22
+ [[feature_name.capitalize()]]Dto toDto() => [[feature_name.capitalize()]]Dto(
23
+ [[domain_to_dto_fields]]
24
+ );
25
+ }
@@ -0,0 +1,11 @@
1
+ import 'package:freezed_annotation/freezed_annotation.dart';
2
+
3
+ part '[[file_name]]_failure.freezed.dart';
4
+
5
+ @freezed
6
+ abstract class [[feature_name]]Failure with _$[[feature_name]]Failure {
7
+ const factory [[feature_name]]Failure.unexpected() = Unexpected;
8
+ const factory [[feature_name]]Failure.insufficientPermission() = InsufficientPermission;
9
+ const factory [[feature_name]]Failure.unableToUpdate() = UnableToUpdate;
10
+ const factory [[feature_name]]Failure.notFound() = NotFound;
11
+ }
@@ -0,0 +1,113 @@
1
+ /*
2
+ * Feature page template with full CRUD UI
3
+ * Generates a complete page with:
4
+ * - BLoC integration for state management
5
+ * - List view showing all items
6
+ * - Add, edit, delete action buttons
7
+ * - Loading and error state handling
8
+ * - Navigation ready structure
9
+ *
10
+ * This provides a complete feature page with all basic operations
11
+ */
12
+
13
+ import 'package:caravaggio_ui/caravaggio_ui.dart';
14
+ import 'package:flutter/material.dart';
15
+ import 'package:flutter_bloc/flutter_bloc.dart';
16
+ import 'package:[[project_name]]/injection.dart';
17
+ import 'package:[[project_name]]/widgets/common/custom_scaffold.dart';
18
+ import 'package:[[project_name]]/widgets/common/loading_widget.dart';
19
+ import 'package:[[model_import_prefix]]/model/[[model_file_stem]].dart';
20
+ import '../application/[[feature_name]]_bloc.dart';
21
+
22
+ class [[feature_name.capitalize()]]Page extends StatelessWidget {
23
+ static const String routeName = '/[[feature_name]]';
24
+
25
+ const [[feature_name.capitalize()]]Page({super.key});
26
+
27
+ @override
28
+ Widget build(BuildContext context) {
29
+ return BlocProvider(
30
+ create: (BuildContext context) => getIt.get<[[feature_name.capitalize()]]Bloc>(),
31
+ child: Builder(
32
+ builder: (BuildContext context) {
33
+ return CustomScaffold(
34
+ title: CText.title('[[feature_name.replace("_", " ").capitalize()]]', size: TextSize.small),
35
+ showBackButton: true,
36
+ action: Row(
37
+ mainAxisSize: MainAxisSize.min,
38
+ children: <Widget>[
39
+ IconButton(
40
+ icon: const Icon(Icons.add),
41
+ onPressed: () {
42
+ // TODO: Navigate to create form
43
+ },
44
+ ),
45
+ IconButton(
46
+ icon: const Icon(Icons.refresh),
47
+ onPressed: () {
48
+ context.read<[[feature_name.capitalize()]]Bloc>().add(
49
+ const [[feature_name.capitalize()]]Event.loadRequested(),
50
+ );
51
+ },
52
+ ),
53
+ ],
54
+ ),
55
+ bodyBuilder: (BuildContext context, double topPadding) {
56
+ return BlocBuilder<[[feature_name.capitalize()]]Bloc, [[feature_name.capitalize()]]State>(
57
+ builder: (BuildContext context, [[feature_name.capitalize()]]State state) {
58
+ return switch (state) {
59
+ Initial() => Padding(
60
+ padding: EdgeInsets.only(top: topPadding),
61
+ child: const Center(child: Text('Welcome')),
62
+ ),
63
+ Loading() => Padding(
64
+ padding: EdgeInsets.only(top: topPadding),
65
+ child: const LoadingWidget(),
66
+ ),
67
+ Loaded(:final items) => ListView.builder(
68
+ padding: EdgeInsets.only(top: topPadding, left: 16, right: 16),
69
+ itemCount: items.length,
70
+ itemBuilder: (BuildContext context, int index) {
71
+ final [[model_class_pascal]] item = items[index];
72
+ return CTile.simple(
73
+ title: item.toString(),
74
+ trailing: Row(
75
+ mainAxisSize: MainAxisSize.min,
76
+ children: <Widget>[
77
+ IconButton(
78
+ icon: const Icon(Icons.edit),
79
+ onPressed: () {
80
+ // TODO: Navigate to edit form
81
+ },
82
+ ),
83
+ IconButton(
84
+ icon: const Icon(Icons.delete),
85
+ onPressed: () {
86
+ context.read<[[feature_name.capitalize()]]Bloc>().add(
87
+ [[feature_name.capitalize()]]Event.deleteRequested(item.id.getOrCrash()),
88
+ );
89
+ },
90
+ ),
91
+ ],
92
+ ),
93
+ );
94
+ },
95
+ ),
96
+ Error(:final message) => Padding(
97
+ padding: EdgeInsets.only(top: topPadding),
98
+ child: Center(child: CText.body('Errore: $message')),
99
+ ),
100
+ _ => Padding(
101
+ padding: EdgeInsets.only(top: topPadding),
102
+ child: const Center(child: Text('Stato sconosciuto')),
103
+ ),
104
+ };
105
+ },
106
+ );
107
+ },
108
+ );
109
+ },
110
+ ),
111
+ );
112
+ }
113
+ }
@@ -0,0 +1,112 @@
1
+ /*
2
+ * Repository implementation template with REST API integration
3
+ * Provides concrete implementation of repository interface with:
4
+ * - Retrofit for API calls
5
+ * - Dio HTTP client integration
6
+ * - DTO to Entity mapping
7
+ * - Error handling with Either types
8
+ * - Injectable dependency registration
9
+ *
10
+ * Includes both remote service definition and repository implementation
11
+ * with proper separation between API layer and domain layer
12
+ */
13
+
14
+ import 'package:dartz/dartz.dart';
15
+ import 'package:dio/dio.dart';
16
+ import 'package:injectable/injectable.dart';
17
+ import 'package:retrofit/retrofit.dart';
18
+ [[repo_import]]
19
+ import 'package:[[project_name]]/apis/common/constants.dart';
20
+
21
+ part '[[feature_name]]_repository.g.dart';
22
+
23
+ @module
24
+ abstract class [[feature_name.capitalize()]]RemoteModule {
25
+ @preResolve
26
+ @LazySingleton()
27
+ Future<[[feature_name.capitalize()]]RemoteService> [[feature_name]]RemoteService(Dio dio) async {
28
+ return [[feature_name.capitalize()]]RemoteService(dio, baseUrl: Constants.apiUrl);
29
+ }
30
+ }
31
+
32
+ @RestApi()
33
+ abstract class [[feature_name.capitalize()]]RemoteService {
34
+ @factoryMethod
35
+ factory [[feature_name.capitalize()]]RemoteService(Dio dio, {String baseUrl}) = _[[feature_name.capitalize()]]RemoteService;
36
+
37
+ @GET('/[[feature_name]]s')
38
+ Future<List<[[feature_name.capitalize()]]Dto>> getAllDto();
39
+
40
+ @GET('/[[feature_name]]s/{id}')
41
+ Future<[[feature_name.capitalize()]]Dto> getByIdDto(@Path('id') String id);
42
+
43
+ @POST('/[[feature_name]]s')
44
+ Future<void> createDto(@Body() [[feature_name.capitalize()]]Dto [[feature_name]]Dto);
45
+
46
+ @PUT('/[[feature_name]]s/{id}')
47
+ Future<void> updateDto(@Path('id') String id, @Body() [[feature_name.capitalize()]]Dto [[feature_name]]Dto);
48
+
49
+ @DELETE('/[[feature_name]]s/{id}')
50
+ Future<void> deleteDto(@Path('id') String id);
51
+ }
52
+
53
+ @Injectable(as: I[[feature_name.capitalize()]]Repository)
54
+ class [[feature_name.capitalize()]]Repository implements I[[feature_name.capitalize()]]Repository {
55
+ final [[feature_name.capitalize()]]RemoteService _remoteService;
56
+
57
+ [[feature_name.capitalize()]]Repository(this._remoteService);
58
+
59
+ @override
60
+ Future<Either<[[feature_name.capitalize()]]Failure, List<[[feature_name.capitalize()]]>>> getAll() async {
61
+ try {
62
+ final List<[[feature_name.capitalize()]]Dto> dtos = await _remoteService.getAllDto();
63
+ final List<[[feature_name.capitalize()]]> domain = dtos
64
+ .map(([[feature_name.capitalize()]]Dto dto) => dto.toDomain())
65
+ .toList();
66
+ return right(domain);
67
+ } on Object catch (_) {
68
+ return left(const [[feature_name.capitalize()]]Failure.unexpected());
69
+ }
70
+ }
71
+
72
+ @override
73
+ Future<Either<[[feature_name.capitalize()]]Failure, [[feature_name.capitalize()]]>> getById(String id) async {
74
+ try {
75
+ final [[feature_name.capitalize()]]Dto dto = await _remoteService.getByIdDto(id);
76
+ final [[feature_name.capitalize()]] domain = dto.toDomain();
77
+ return right(domain);
78
+ } on Object catch (_) {
79
+ return left(const [[feature_name.capitalize()]]Failure.unexpected());
80
+ }
81
+ }
82
+
83
+ @override
84
+ Future<Either<[[feature_name.capitalize()]]Failure, Unit>> create([[feature_name.capitalize()]] item) async {
85
+ try {
86
+ await _remoteService.createDto(item.toDto());
87
+ return right(unit);
88
+ } on Object catch (_) {
89
+ return left(const [[feature_name.capitalize()]]Failure.unexpected());
90
+ }
91
+ }
92
+
93
+ @override
94
+ Future<Either<[[feature_name.capitalize()]]Failure, Unit>> update([[feature_name.capitalize()]] item) async {
95
+ try {
96
+ await _remoteService.updateDto(item.id.getOrCrash(), item.toDto());
97
+ return right(unit);
98
+ } on Object catch (_) {
99
+ return left(const [[feature_name.capitalize()]]Failure.unexpected());
100
+ }
101
+ }
102
+
103
+ @override
104
+ Future<Either<[[feature_name.capitalize()]]Failure, Unit>> delete(String id) async {
105
+ try {
106
+ await _remoteService.deleteDto(id);
107
+ return right(unit);
108
+ } on Object catch (_) {
109
+ return left(const [[feature_name.capitalize()]]Failure.unexpected());
110
+ }
111
+ }
112
+ }
@@ -0,0 +1,20 @@
1
+ /*
2
+ * BLoC states template for feature UI representation
3
+ * Defines immutable states using Freezed for different UI states:
4
+ * - Initial: App just started, no data loaded
5
+ * - Loading: Data is being fetched/processed
6
+ * - Loaded: Data successfully retrieved with items list
7
+ * - Error: Something went wrong with error message
8
+ *
9
+ * States represent the current condition of the feature
10
+ */
11
+
12
+ part of '[[feature_name]]_bloc.dart';
13
+
14
+ @freezed
15
+ abstract class [[feature_name.capitalize()]]State with _$[[feature_name.capitalize()]]State {
16
+ const factory [[feature_name.capitalize()]]State.initial() = Initial;
17
+ const factory [[feature_name.capitalize()]]State.loading() = Loading;
18
+ const factory [[feature_name.capitalize()]]State.loaded(List<[[feature_name.capitalize()]]> items) = Loaded;
19
+ const factory [[feature_name.capitalize()]]State.error(String message) = Error;
20
+ }
@@ -0,0 +1,21 @@
1
+ /*
2
+ * Repository interface template for data access abstraction
3
+ * Defines the contract for data operations using:
4
+ * - Either type for error handling (Left = failure, Right = success)
5
+ * - CRUD operations (Create, Read, Update, Delete)
6
+ * - Async operations returning Futures
7
+ *
8
+ * This interface allows different implementations (API, local storage, etc.)
9
+ * while keeping the business logic independent of data source
10
+ */
11
+
12
+ import 'package:dartz/dartz.dart';
13
+ [[i_repo_import]]
14
+
15
+ abstract class I[[feature_name]]Repository {
16
+ Future<Either<[[feature_name]]Failure, List<[[feature_name]]>>> getAll();
17
+ Future<Either<[[feature_name]]Failure, [[feature_name]]>> getById(String id);
18
+ Future<Either<[[feature_name]]Failure, Unit>> create([[feature_name]] item);
19
+ Future<Either<[[feature_name]]Failure, Unit>> update([[feature_name]] item);
20
+ Future<Either<[[feature_name]]Failure, Unit>> delete(String id);
21
+ }
@@ -0,0 +1,57 @@
1
+ /*
2
+ * Value validators template for input validation
3
+ * Generates validation functions for different data types:
4
+ * - String validation (empty check and custom rules)
5
+ * - Numeric validation (int, double)
6
+ * - Boolean validation
7
+ * - DateTime validation
8
+ *
9
+ * Uses Either types for functional error handling
10
+ * Returns validation failures or valid values
11
+ */
12
+
13
+ import 'package:dartz/dartz.dart';
14
+ import 'package:[[project_name]]/core/model/failures.dart';
15
+
16
+ {% for field in field_list %}
17
+ {% if field.name != 'id' %}
18
+ {% if field.type == 'String' %}
19
+ Either<ValueFailure<String>, String> validate[[field.pascal_name]](String input) {
20
+ if (input.isEmpty) {
21
+ return left(ValueFailure.empty(failedValue: input));
22
+ }
23
+ // Additional string validations can be added here
24
+ return right(input);
25
+ }
26
+ {% elif field.type == 'int' %}
27
+ Either<ValueFailure<int>, int> validate[[field.pascal_name]](int input) {
28
+ // Additional int validations can be added here
29
+ return right(input);
30
+ }
31
+ {% elif field.type == 'double' %}
32
+ Either<ValueFailure<double>, double> validate[[field.pascal_name]](double input) {
33
+ // Additional double validations can be added here
34
+ return right(input);
35
+ }
36
+ {% elif field.type == 'bool' %}
37
+ Either<ValueFailure<bool>, bool> validate[[field.pascal_name]](bool input) {
38
+ // Boolean validation - always valid
39
+ // Additional boolean validations can be added here
40
+ return right(input);
41
+ }
42
+ {% elif field.type == 'DateTime' %}
43
+ Either<ValueFailure<DateTime>, DateTime> validate[[field.pascal_name]](DateTime input) {
44
+ // Additional datetime validations can be added here
45
+ return right(input);
46
+ }
47
+ {% else %}
48
+ Either<ValueFailure<String>, String> validate[[field.pascal_name]](String input) {
49
+ if (input.isEmpty) {
50
+ return left(ValueFailure.empty(failedValue: input));
51
+ }
52
+ // Additional string validations can be added here
53
+ return right(input);
54
+ }
55
+ {% endif %}
56
+ {% endif %}
57
+ {% endfor %}
@@ -0,0 +1,68 @@
1
+ /*
2
+ * Home screen template with navigation structure
3
+ * Generates the main application screen with:
4
+ * - Bottom navigation bar integration
5
+ * - Multiple tab screens based on configuration
6
+ * - Optional drawer support
7
+ * - StatefulWidget for navigation state management
8
+ *
9
+ * This serves as the main navigation hub for the application
10
+ * with configurable navigation items and screens
11
+ */
12
+
13
+ import 'package:caravaggio_ui/caravaggio_ui.dart';
14
+ import 'package:flutter/material.dart';
15
+ import 'package:[[project_name]]/core/presentation/bottom_nav_bar.dart';
16
+ import 'package:[[project_name]]/widgets/common/custom_scaffold.dart';
17
+ {% for nav_item in nav_items %}
18
+ import 'package:[[project_name]]/features/home/[[nav_item.name]]_screen.dart';
19
+ {% endfor %}
20
+ {% if has_drawer %}
21
+ import 'package:[[project_name]]/core/presentation/app_drawer.dart';
22
+ {% endif %}
23
+
24
+ class HomePage extends StatefulWidget {
25
+ static const String routeName = '/home';
26
+
27
+ const HomePage({super.key});
28
+
29
+ @override
30
+ State<HomePage> createState() => _HomePageState();
31
+ }
32
+
33
+ class _HomePageState extends State<HomePage> {
34
+ int _selectedIndex = 0;
35
+
36
+ final List<Widget> _pages = [
37
+ const Center(child: Text('Home Content')),
38
+ {% for nav_item in nav_items %}
39
+ const [[nav_item.name|title]]Screen(),
40
+ {% endfor %}
41
+ ];
42
+
43
+ void _onItemTapped(int index) {
44
+ setState(() {
45
+ _selectedIndex = index;
46
+ });
47
+ }
48
+
49
+ @override
50
+ Widget build(BuildContext context) {
51
+ return CustomScaffold(
52
+ title: CText.title('Home', size: TextSize.medium).bold,
53
+ showBackButton: false,
54
+ {% if has_drawer %}
55
+ drawer: const AppDrawer(),
56
+ {% endif %}
57
+ body: Column(
58
+ children: <Widget>[
59
+ Expanded(child: _pages[_selectedIndex]),
60
+ BottomNavBar(
61
+ currentIndex: _selectedIndex,
62
+ onTap: _onItemTapped,
63
+ ),
64
+ ],
65
+ ),
66
+ );
67
+ }
68
+ }
@@ -0,0 +1,52 @@
1
+ import 'package:caravaggio_ui/caravaggio_ui.dart';
2
+ import 'package:flutter/material.dart';
3
+ {% if has_login %}
4
+ import 'package:flutter_bloc/flutter_bloc.dart';
5
+ import 'package:go_router/go_router.dart';
6
+ import 'package:[[project_name]]/features/auth/application/auth_bloc.dart';
7
+ import 'package:[[project_name]]/features/auth/presentation/login_page.dart';
8
+ {% endif %}
9
+ import 'package:[[project_name]]/widgets/common/custom_scaffold.dart';
10
+
11
+ class HomePage extends StatefulWidget {
12
+ static const String routeName = '/home';
13
+
14
+ const HomePage({super.key});
15
+
16
+ @override
17
+ State<HomePage> createState() => _HomePageState();
18
+ }
19
+
20
+ class _HomePageState extends State<HomePage> {
21
+ @override
22
+ Widget build(BuildContext context) {
23
+ {% if has_login %}
24
+ return BlocListener<AuthBloc, AuthState>(
25
+ listener: (BuildContext context, AuthState state) => switch (state) {
26
+ Unauthenticated() => context.go(LoginPage.routeName),
27
+ _ => null,
28
+ },
29
+ child: CustomScaffold(
30
+ title: CText.title('Home', size: TextSize.medium).bold,
31
+ showBackButton: false,
32
+ action: CButton.icon(
33
+ icon: Icons.logout,
34
+ tooltip: 'Logout',
35
+ onPressed: () => context.read<AuthBloc>().add(const AuthEvent.signedOut()),
36
+ ),
37
+ body: const Center(
38
+ child: Text('Home Screen'),
39
+ ),
40
+ ),
41
+ );
42
+ {% else %}
43
+ return CustomScaffold(
44
+ title: CText.title('Home', size: TextSize.medium).bold,
45
+ showBackButton: false,
46
+ body: const Center(
47
+ child: Text('Home Screen'),
48
+ ),
49
+ );
50
+ {% endif %}
51
+ }
52
+ }