Skip to content

Instantly share code, notes, and snippets.

@JaveedIshaq
Created December 16, 2024 14:22
Show Gist options
  • Save JaveedIshaq/7b4485d715d8787e57608f8eb17c9c80 to your computer and use it in GitHub Desktop.
Save JaveedIshaq/7b4485d715d8787e57608f8eb17c9c80 to your computer and use it in GitHub Desktop.
command-to-generate-feature-flutter
#!/bin/bash
# Check if feature name is provided
if [ -z "$1" ]; then
echo "Please provide a feature name"
echo "Usage: ./generate_feature.sh <feature_name>"
exit 1
fi
# Convert feature name to lowercase and get capitalized version
FEATURE_NAME=$(echo "$1" | tr '[:upper:]' '[:lower:]')
FEATURE_NAME_CAP="$(tr '[:lower:]' '[:upper:]' <<< ${FEATURE_NAME:0:1})${FEATURE_NAME:1}"
BASE_DIR="lib/features/$FEATURE_NAME"
# Create complete directory structure
mkdir -p "$BASE_DIR"/{domain/{entities,repositories},infrastructure/{data_sources,repositories},presentation/{cubit,screens,views,widgets}}
# Create domain repository
cat > "$BASE_DIR/domain/repositories/${FEATURE_NAME}_repository.dart" << EOL
abstract class ${FEATURE_NAME_CAP}Repository {
// Sample function
// Future<Either<MVRError, UserProfileDto>> getUserProfileData();
/// getUserProfileData
///
/// This function is used to get User Profile Data
/// * [Either<MVRError, UserProfileDto>] : Return a list of city dto if success, otherwise return a MVRError
}
EOL
# Create remote data source
cat > "$BASE_DIR/infrastructure/data_sources/${FEATURE_NAME}_remote_data_source.dart" << EOL
import 'package:injectable/injectable.dart';
import 'package:mobile/app/core/network/network.dart';
@lazySingleton
class ${FEATURE_NAME_CAP}RemoteDataSource {
final Network _network;
${FEATURE_NAME_CAP}RemoteDataSource(this._network);
// example function
// Future<UserProfileDto> getProfileData() async {
// final response = await _network.get("user/profile", {});
// return UserProfileDto.fromJson(response.data as Map<String, dynamic>);
// }
}
EOL
# Create repository implementation
cat > "$BASE_DIR/infrastructure/repositories/${FEATURE_NAME}_repository.dart" << EOL
import 'package:injectable/injectable.dart';
import 'package:mobile/features/${FEATURE_NAME}/domain/repositories/${FEATURE_NAME}_repository.dart';
import 'package:mobile/features/${FEATURE_NAME}/infrastructure/data_sources/${FEATURE_NAME}_remote_data_source.dart';
@LazySingleton(as: ${FEATURE_NAME_CAP}Repository)
class ${FEATURE_NAME_CAP}RepositoryImpl implements ${FEATURE_NAME_CAP}Repository {
final ${FEATURE_NAME_CAP}RemoteDataSource _remoteDataSource;
const ${FEATURE_NAME_CAP}RepositoryImpl(this._remoteDataSource);
// sample function
// @override
// Future<Either<MVRError, UserProfileDto>> getUserProfileData() async {
// try {
// final response = await _remoteDataSource.getProfileData();
// return right(response);
// } on DioException catch (e, t) {
// return left(MVRError.fromNetwork(
// message: e.message,
// error: e,
// trace: t,
// ));
// } catch (e, t) {
// return left(MVRError.fromUnknown(
// error: e,
// trace: t,
// ));
// }
// }
}
EOL
# Create state file
cat > "$BASE_DIR/presentation/cubit/${FEATURE_NAME}_state.dart" << EOL
part of '${FEATURE_NAME}_cubit.dart';
class ${FEATURE_NAME_CAP}State extends BaseState {
const ${FEATURE_NAME_CAP}State({
this.submitStatus = RequestStatus.initial,
this.message,
});
final String? message;
@override
final RequestStatus submitStatus;
factory ${FEATURE_NAME_CAP}State.initial() => const ${FEATURE_NAME_CAP}State();
@override
List<Object?> get props => [submitStatus];
@override
String toString() => 'HomeState(status: \$submitStatus, message: \$message)';
@override
${FEATURE_NAME_CAP}State copyWith({
RequestStatus? submitStatus,
String? message,
}) {
return ${FEATURE_NAME_CAP}State(
submitStatus: submitStatus ?? this.submitStatus,
message: message ?? this.message,
);
}
}
EOL
# Create cubit file
cat > "$BASE_DIR/presentation/cubit/${FEATURE_NAME}_cubit.dart" << EOL
import 'package:mobile/app/core/cubit/cubit.dart';
import 'package:mobile/features/${FEATURE_NAME}/domain/repositories/${FEATURE_NAME}_repository.dart';
part '${FEATURE_NAME}_state.dart';
@lazySingleton
class ${FEATURE_NAME_CAP}Cubit extends BaseCubit<${FEATURE_NAME_CAP}State> {
${FEATURE_NAME_CAP}Cubit(this._${FEATURE_NAME}Repository) : super(${FEATURE_NAME_CAP}State.initial());
final ${FEATURE_NAME_CAP}Repository _${FEATURE_NAME}Repository;
// Sample function in cubit
// Future<void> onGetUserProfileData() async {
// final result = await _${FEATURE_NAME}Repository.getUserProfileData();
// result.fold(
// // l mean left it is error
// (l) => emit(
// state.copyWith(submitStatus: RequestStatus.failure, message: l.message),
// ),
// // r mean right it is success
// (result) {
// state.copyWith(
// submitStatus: RequestStatus.failure,
// message: result.message,
// profileData: result.data.toEntity(),
// );
// },
// );
// }
}
EOL
# Create screen file
cat > "$BASE_DIR/presentation/screens/${FEATURE_NAME}_screen.dart" << EOL
import 'package:flutter/material.dart';
class ${FEATURE_NAME_CAP}Screen extends StatelessWidget {
const ${FEATURE_NAME_CAP}Screen({super.key});
@override
Widget build(BuildContext context) {
return Container();
}
}
EOL
# Create view file
cat > "$BASE_DIR/presentation/views/${FEATURE_NAME}_view.dart" << EOL
import 'package:flutter/material.dart';
class ${FEATURE_NAME_CAP}View extends StatelessWidget {
const ${FEATURE_NAME_CAP}View({super.key});
@override
Widget build(BuildContext context) {
return Container();
}
}
EOL
echo "Feature '$FEATURE_NAME' has been generated with the following structure:"
echo "Domain"
echo " ├─ Entities"
echo " └─ Repositories"
echo "Infrastructure"
echo " ├─ Data Sources"
echo " └─ Repositories"
echo "Presentation"
echo " ├─ Cubit"
echo " ├─ Screens"
echo " ├─ Views"
echo " └─ Widgets"
echo ""
echo "Generated in: $BASE_DIR"
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment