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.
- coregen.py +1585 -0
- coregen_cli-3.1.6.dist-info/METADATA +1211 -0
- coregen_cli-3.1.6.dist-info/RECORD +172 -0
- coregen_cli-3.1.6.dist-info/WHEEL +5 -0
- coregen_cli-3.1.6.dist-info/entry_points.txt +2 -0
- coregen_cli-3.1.6.dist-info/top_level.txt +2 -0
- generators/__init__.py +1 -0
- generators/assets/__init__.py +1 -0
- generators/assets/assets.py +30 -0
- generators/assets/main.py +4 -0
- generators/config/__init__.py +1 -0
- generators/config/analisy_options.py +42 -0
- generators/config/main.py +11 -0
- generators/config/pubspec.py +139 -0
- generators/cursor/__init__.py +3 -0
- generators/cursor/setup.py +87 -0
- generators/helpers/__init__.py +56 -0
- generators/helpers/component.py +1030 -0
- generators/helpers/config.py +255 -0
- generators/helpers/data_source.py +180 -0
- generators/helpers/domain.py +469 -0
- generators/helpers/feature.py +654 -0
- generators/helpers/navigation.py +274 -0
- generators/helpers/page.py +63 -0
- generators/helpers/project.py +33 -0
- generators/helpers/utils.py +338 -0
- generators/helpers/validation.py +364 -0
- generators/initializator.py +68 -0
- generators/main.py +81 -0
- generators/static/assets/logo.png +0 -0
- generators/static/assets/mock/auth_user.json +5 -0
- generators/static/assets/svgs/apple.svg +4 -0
- generators/static/assets/svgs/google.svg +2 -0
- generators/static/cursor/AGENTS.md.jinja +37 -0
- generators/static/cursor/agents/doc-writer.md +20 -0
- generators/static/cursor/agents/epic-orchestrator.md +28 -0
- generators/static/cursor/agents/feature-implementer.md +29 -0
- generators/static/cursor/agents/integration-wiring.md +30 -0
- generators/static/cursor/agents/layer-application.md +21 -0
- generators/static/cursor/agents/layer-guardian.md +21 -0
- generators/static/cursor/agents/layer-infrastructure.md +31 -0
- generators/static/cursor/agents/layer-model.md +24 -0
- generators/static/cursor/agents/layer-presentation.md +33 -0
- generators/static/cursor/docs/architecture/APIS_AND_INTEGRATION.md.jinja +42 -0
- generators/static/cursor/docs/architecture/CARAVAGGIO_COMPONENTS.md.jinja +317 -0
- generators/static/cursor/docs/architecture/DDD_LAYERS.md.jinja +32 -0
- generators/static/cursor/docs/architecture/FILE_TEMPLATES.md.jinja +76 -0
- generators/static/cursor/docs/architecture/MOCK_AND_REMOTE_DATA.md.jinja +87 -0
- generators/static/cursor/docs/architecture/REFERENCE_IMPLEMENTATIONS.md.jinja +48 -0
- generators/static/cursor/docs/architecture/WIDGETS_AND_CARAVAGGIO.md.jinja +76 -0
- generators/static/cursor/docs/epics/README.md +17 -0
- generators/static/cursor/lib/domain/AGENTS.md +23 -0
- generators/static/cursor/lib/features/AGENTS.md +23 -0
- generators/static/cursor/lib/widgets/AGENTS.md +21 -0
- generators/static/cursor/rules/apis-layer.mdc.jinja +21 -0
- generators/static/cursor/rules/application-layer.mdc.jinja +12 -0
- generators/static/cursor/rules/architecture-core.mdc.jinja +43 -0
- generators/static/cursor/rules/dart-conventions.mdc.jinja +14 -0
- generators/static/cursor/rules/domain-layer.mdc.jinja +24 -0
- generators/static/cursor/rules/login-context.mdc.jinja +16 -0
- generators/static/cursor/rules/presentation-layer.mdc.jinja +15 -0
- generators/static/cursor/rules/quality-gate.mdc.jinja +14 -0
- generators/static/cursor/rules/ui-caravaggio.mdc.jinja +22 -0
- generators/static/cursor/skills/caravaggio-ui/SKILL.md +138 -0
- generators/static/cursor/skills/epic-delivery/SKILL.md +74 -0
- generators/static/cursor/skills/epic-delivery/templates/epic-status.md +14 -0
- generators/static/cursor/skills/epic-delivery/templates/epic.md +36 -0
- generators/static/templates/apis/common/constants_template.jinja +48 -0
- generators/static/templates/apis/common/data_source_config_template.jinja +47 -0
- generators/static/templates/apis/core/api_injectable_module_template.jinja +14 -0
- generators/static/templates/apis/interceptors/api_logger_template.jinja +135 -0
- generators/static/templates/apis/interceptors/auth_interceptor_template.jinja +207 -0
- generators/static/templates/auth/application/auth_bloc_template.jinja +36 -0
- generators/static/templates/auth/application/auth_event_template.jinja +7 -0
- generators/static/templates/auth/application/auth_state_template.jinja +8 -0
- generators/static/templates/auth/infrastructure/auth_facade_module_template.jinja +16 -0
- generators/static/templates/auth/infrastructure/auth_facade_template.jinja +288 -0
- generators/static/templates/auth/infrastructure/mock_auth_facade_template.jinja +106 -0
- generators/static/templates/auth/model/auth_failure_template.jinja +11 -0
- generators/static/templates/auth/model/i_auth_facade_template.jinja +24 -0
- generators/static/templates/auth/model/user_template.jinja +34 -0
- generators/static/templates/auth/model/value_objects_template.jinja +54 -0
- generators/static/templates/auth/presentation/login_screen_template.jinja +24 -0
- generators/static/templates/auth/sign_in_form/application/sign_in_form_bloc_template.jinja +139 -0
- generators/static/templates/auth/sign_in_form/application/sign_in_form_event_template.jinja +15 -0
- generators/static/templates/auth/sign_in_form/application/sign_in_form_state_template.jinja +26 -0
- generators/static/templates/auth/sign_in_form/presentation/apple_form_template.jinja +16 -0
- generators/static/templates/auth/sign_in_form/presentation/email_password_form_template_INACTIVE.jinja +94 -0
- generators/static/templates/auth/sign_in_form/presentation/google_form_template.jinja +15 -0
- generators/static/templates/auth/sign_in_form/presentation/sign_in_form_template.jinja +381 -0
- generators/static/templates/component/component_bloc_template.jinja +49 -0
- generators/static/templates/component/component_event_template.jinja +7 -0
- generators/static/templates/component/component_form_bloc_template.jinja +56 -0
- generators/static/templates/component/component_form_event_template.jinja +7 -0
- generators/static/templates/component/component_form_state_template.jinja +18 -0
- generators/static/templates/component/component_form_widget_template.jinja +130 -0
- generators/static/templates/component/component_list_widget_template.jinja +95 -0
- generators/static/templates/component/component_state_template.jinja +9 -0
- generators/static/templates/component/component_widget_template.jinja +113 -0
- generators/static/templates/core/bloc/base_form_bloc_template.jinja +32 -0
- generators/static/templates/core/errors/error_localizer_template.jinja +61 -0
- generators/static/templates/core/infrastructure/base_mapper_template.jinja +21 -0
- generators/static/templates/core/infrastructure/base_repository_mixin_template.jinja +78 -0
- generators/static/templates/core/infrastructure/firebase_injectable_module_template.jinja +11 -0
- generators/static/templates/core/infrastructure/firestore_helpers_template.jinja +22 -0
- generators/static/templates/core/infrastructure/repository_error_handler_template.jinja +44 -0
- generators/static/templates/core/model/common_interfaces_template.jinja +3 -0
- generators/static/templates/core/model/entity_template.jinja +5 -0
- generators/static/templates/core/model/errors_template.jinja +15 -0
- generators/static/templates/core/model/failures_template.jinja +97 -0
- generators/static/templates/core/model/value_objects_template.jinja +135 -0
- generators/static/templates/core/model/value_validators_template.jinja +105 -0
- generators/static/templates/core/presentation/app_drawer_template.jinja +52 -0
- generators/static/templates/core/presentation/app_widget_template.jinja +41 -0
- generators/static/templates/core/presentation/bottom_nav_bar_template.jinja +32 -0
- generators/static/templates/domain/domain_mapper_template.jinja +39 -0
- generators/static/templates/domain/domain_remote_service_template.jinja +46 -0
- generators/static/templates/domain/domain_repository_template.jinja +90 -0
- generators/static/templates/domain/domain_service_module_template.jinja +23 -0
- generators/static/templates/domain/enum_template.jinja +3 -0
- generators/static/templates/domain/i_domain_service_template.jinja +18 -0
- generators/static/templates/domain/mock_domain_service_template.jinja +73 -0
- generators/static/templates/feature/feature_bloc_template.jinja +104 -0
- generators/static/templates/feature/feature_dto_template.jinja +26 -0
- generators/static/templates/feature/feature_entity_template.jinja +23 -0
- generators/static/templates/feature/feature_event_template.jinja +20 -0
- generators/static/templates/feature/feature_extensions_template.jinja +25 -0
- generators/static/templates/feature/feature_failure_template.jinja +11 -0
- generators/static/templates/feature/feature_page_template.jinja +113 -0
- generators/static/templates/feature/feature_repository_template.jinja +112 -0
- generators/static/templates/feature/feature_state_template.jinja +20 -0
- generators/static/templates/feature/i_feature_repository_template.jinja +21 -0
- generators/static/templates/feature/value_object_field_template.jinja +0 -0
- generators/static/templates/feature/value_object_template.jinja +0 -0
- generators/static/templates/feature/value_validators_template.jinja +57 -0
- generators/static/templates/home/home_screen_template.jinja +68 -0
- generators/static/templates/home/presentation/home_screen_template.jinja +52 -0
- generators/static/templates/home/screen_template.jinja +12 -0
- generators/static/templates/injection_template.jinja +8 -0
- generators/static/templates/logging/analytics_logging_template.jinja +42 -0
- generators/static/templates/logging/console_template.jinja +50 -0
- generators/static/templates/logging/logger_injectable_module_template.jinja +24 -0
- generators/static/templates/logging/logger_template.jinja +118 -0
- generators/static/templates/main_template.jinja +43 -0
- generators/static/templates/page_template.jinja +29 -0
- generators/static/templates/router_template.jinja +26 -0
- generators/static/templates/splash/presentation/splash_screen_auth_template.jinja +97 -0
- generators/static/templates/splash/presentation/splash_screen_template.jinja +51 -0
- generators/static/templates/storage/storage_repository_template.jinja +80 -0
- generators/static/templates/user_profile/infrastructure/user_profile_dto_template.jinja +27 -0
- generators/static/templates/user_profile/infrastructure/user_profile_mapper_template.jinja +43 -0
- generators/static/templates/user_profile/infrastructure/user_profile_repository_template.jinja +82 -0
- generators/static/templates/user_profile/infrastructure/user_profile_service_template.jinja +27 -0
- generators/static/templates/user_profile/model/i_user_profile_repository_template.jinja +34 -0
- generators/static/templates/user_profile/model/user_profile_failure_template.jinja +11 -0
- generators/static/templates/user_profile/model/user_profile_template.jinja +31 -0
- generators/static/templates/widgets/common/custom_scaffold_template.jinja +52 -0
- generators/static/templates/widgets/common/error_widget_template.jinja +22 -0
- generators/static/templates/widgets/common/loading_widget_template.jinja +14 -0
- generators/static/templates/widgets/common/unknown_state_widget_template.jinja +23 -0
- generators/templates/__init__.py +1 -0
- generators/templates/_core/core_generator.py +121 -0
- generators/templates/apis/apis_generator.py +50 -0
- generators/templates/auth/auth_generator.py +40 -0
- generators/templates/auth/sign_in_form_generator.py +22 -0
- generators/templates/copier.py +51 -0
- generators/templates/home/home_generator.py +26 -0
- generators/templates/lib/lib_generator.py +40 -0
- generators/templates/logging/logging_generator.py +28 -0
- generators/templates/main.py +75 -0
- generators/templates/splash/splash_generator.py +20 -0
- generators/templates/storage/storage_generator.py +5 -0
generators/static/templates/user_profile/infrastructure/user_profile_repository_template.jinja
ADDED
|
@@ -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
|