generateMethodCode function
void
generateMethodCode()
Implementation
void generateMethodCode(
String feature,
String httpMethod,
String method,
String model,
bool pagination,
bool store,
String? json,
String? queryClassName,
String? queryJson,
) {
final blocFile = File('$feature/presentation/bloc/${feature}_bloc.dart');
if (!blocFile.existsSync()) {
print('โ Bloc file not found for feature: $feature');
return;
}
final eventFile = File('$feature/presentation/bloc/${feature}_event.dart');
final stateFile = File('$feature/presentation/bloc/${feature}_state.dart');
final repoFile = File('$feature/domain/repo/${feature}_repository.dart');
final repoImplFile = File('$feature/data/repo_impl/${feature}_repo_impl.dart');
final remoteFile = File('$feature/data/sources/${feature}_remote_source.dart');
final endpointFile = File('$feature/data/endpoints/${feature}_endpoints.dart');
final queryType = (queryClassName != null && queryClassName.trim().isNotEmpty)
? _capitalize(queryClassName.trim())
: 'Fetch${_capitalize(feature)}Query';
final modelType = _capitalize(model.trim().isEmpty ? '${feature}Response' : model.trim());
final methodCode = '''
Future<void> _on${_capitalize(method)}(${_capitalize(method)}Requested event, Emitter<${_capitalize(feature)}State> emit) async {
emit(state.copyWith(${method}Status: AppStatus.loading));
final response = await _${feature}Repository.$method(
queryParam: event.queryParam${httpMethod.toLowerCase() == 'post' || httpMethod.toLowerCase() == 'postmultipart' ? ', payload: event.payload' : ''}
);
response.fold(
(error) => emit(state.copyWith(${method}Status: AppStatus.failure, error: error)),
(result) async {
emit(state.copyWith(
${method}Status: AppStatus.success${store ? ', ${_inferStoreVar(method)}: result.data' : ''}${pagination ? ', ${method}NextPage: result.pagination?.currentPage ?? 0, ${method}OffSet: result.pagination?.offSet ?? 0, ${method}TotalPage: result.pagination?.totalPage ?? 0' : ''}
));
},
);
emit(state.copyWith(${method}Status: AppStatus.complete));
}
''';
// Register handler in bloc constructor
var blocContent = blocFile.readAsStringSync();
final registrationLine = 'on<${_capitalize(method)}Requested>(_on${_capitalize(method)});';
if (!blocContent.contains(registrationLine)) {
final fetchHandlerRegExp = RegExp('on<${_capitalize(feature)}Fetched>\\(.*\\);');
final match = fetchHandlerRegExp.firstMatch(blocContent);
if (match != null) {
blocContent = '${blocContent.substring(0, match.end)}\n $registrationLine${blocContent.substring(match.end)}';
}
}
if (!blocContent.contains(methodCode)) {
blocContent = '$blocContent\n$methodCode';
}
blocFile.writeAsStringSync(blocContent, flush: true);
print('โ
Method $method added and registered in ${feature}_bloc.dart');
// Also add AppStatus field for this method into the state
if (stateFile.existsSync()) {
var content = stateFile.readAsStringSync();
if (!content.contains('final AppStatus ${method}Status')) {
content = content.replaceFirst(
'final AppStatus fetchStatus;',
'final AppStatus fetchStatus;\n final AppStatus ${method}Status;${store ? '\n final dynamic ${_inferStoreVar(method)};' : ''}${pagination ? '\n final int ${method}NextPage;\n final int ${method}OffSet;\n final int ${method}TotalPage;' : ''}',
);
content = content.replaceFirst(
'const ${_capitalize(feature)}State({',
'const ${_capitalize(feature)}State({\n this.${method}Status = AppStatus.initial,${store ? '\n this.${_inferStoreVar(method)},' : ''}${pagination ? '\n this.${method}NextPage = 0,\n this.${method}OffSet = 0,\n this.${method}TotalPage = 0,' : ''}',
);
content = content.replaceFirst(
'${_capitalize(feature)}State copyWith({',
'${_capitalize(feature)}State copyWith({\n AppStatus? ${method}Status,${store ? '\n dynamic ${_inferStoreVar(method)},' : ''}${pagination ? '\n int? ${method}NextPage,\n int? ${method}OffSet,\n int? ${method}TotalPage,' : ''}',
);
content = content.replaceFirst(
'fetchStatus: fetchStatus ?? this.fetchStatus,',
'fetchStatus: fetchStatus ?? this.fetchStatus,\n ${method}Status: ${method}Status ?? this.${method}Status,${store ? '\n ${_inferStoreVar(method)}: ${_inferStoreVar(method)} ?? this.${_inferStoreVar(method)},' : ''}${pagination ? '\n ${method}NextPage: ${method}NextPage ?? this.${method}NextPage,\n ${method}OffSet: ${method}OffSet ?? this.${method}OffSet,\n ${method}TotalPage: ${method}TotalPage ?? this.${method}TotalPage,' : ''}',
);
content = content.replaceFirst(
'List<Object?> get props => <Object?>[fetchStatus,',
'List<Object?> get props => <Object?>[fetchStatus, ${method}Status,${store ? ' ${_inferStoreVar(method)},' : ''}${pagination ? ' ${method}NextPage, ${method}OffSet, ${method}TotalPage,' : ''}',
);
}
stateFile.writeAsStringSync(content, flush: true);
print('๐ง Updated ${feature}_state.dart with ${method}Status field.');
}
// Add new event for this method
if (eventFile.existsSync()) {
var content = eventFile.readAsStringSync();
final eventClass = '''
class ${_capitalize(method)}Requested extends ${_capitalize(feature)}Event {
const ${_capitalize(method)}Requested({
this.queryParam,${httpMethod.toLowerCase() == 'post' || httpMethod.toLowerCase() == 'postmultipart' ? '\n this.payload,' : ''}
});
final $queryType? queryParam;${httpMethod.toLowerCase() == 'post' || httpMethod.toLowerCase() == 'postmultipart' ? '\n final Map<String, dynamic>? payload;' : ''}
@override
List<Object?> get props => <Object?>[queryParam${httpMethod.toLowerCase() == 'post' || httpMethod.toLowerCase() == 'postmultipart' ? ', payload' : ''}];
}
''';
if (!content.contains('class ${_capitalize(method)}Requested')) {
content = '$content\n$eventClass';
eventFile.writeAsStringSync(content, flush: true);
print('๐งฉ Added ${_capitalize(method)}Requested event.');
}
}
// Append repository abstract method
if (repoFile.existsSync()) {
var content = repoFile.readAsStringSync();
final modelImport = "import '../../data/model/response/${_snake(modelType)}.dart';";
if (!content.contains(modelImport)) {
content = '$modelImport\n$content';
}
final repoMethodSig = httpMethod.toLowerCase() == 'get'
? ' Future<Either<Failure, $modelType>> $method({$queryType? queryParam});'
: ' Future<Either<Failure, $modelType>> $method({$queryType? queryParam, Map<String, dynamic>? payload});';
if (!content.contains('$method(')) {
final idx = content.lastIndexOf('}');
final updated = '${content.substring(0, idx)}\n$repoMethodSig\n${content.substring(idx)}';
repoFile.writeAsStringSync(updated, flush: true);
print('๐ Updated ${feature}_repository.dart with $method signature.');
}
}
// Append repo_impl forwarding method
if (repoImplFile.existsSync()) {
var content = repoImplFile.readAsStringSync();
final modelImport = "import '../../data/model/response/${_snake(modelType)}.dart';";
if (!content.contains(modelImport)) {
content = '$modelImport\n$content';
}
final implMethod = httpMethod.toLowerCase() == 'get'
? '''
@override
Future<Either<Failure, $modelType>> $method({
$queryType? queryParam,
}) {
return _${feature}RemoteSource.$method(queryParam: queryParam);
}
'''
: '''
@override
Future<Either<Failure, $modelType>> $method({
$queryType? queryParam,
Map<String, dynamic>? payload,
}) {
return _${feature}RemoteSource.$method(queryParam: queryParam, payload: payload);
}
''';
if (!content.contains(' $method(')) {
final idx = content.lastIndexOf('}');
final updated = '${content.substring(0, idx)}\n$implMethod${content.substring(idx)}';
repoImplFile.writeAsStringSync(updated, flush: true);
print('๐ Updated ${feature}_repo_impl.dart with $method forwarding.');
}
}
// Append remote source method using ApiClient
if (remoteFile.existsSync()) {
var content = remoteFile.readAsStringSync();
final modelImport = "import '../../data/model/response/${_snake(modelType)}.dart';";
if (!content.contains(modelImport)) {
content = '$modelImport\n$content';
}
final endpointCall = '${_capitalize(feature)}Endpoints.$method(workspaceId: workspaceId)';
final remoteMethod = () {
final header = '''
Future<Either<Failure, $modelType>> $method({
$queryType? queryParam,${httpMethod.toLowerCase() == 'post' || httpMethod.toLowerCase() == 'postmultipart' ? '\n Map<String, dynamic>? payload,' : ''}
}) async {
final workspaceId = await _secureStorageService.getWorkspaceId;
if (workspaceId == null) {
return const Left(GeneralFailure('Workspace ID not found'));
}
final apiEndpoint = $endpointCall;
''';
final tail = '''
return response.fold(
Left.new,
(result) => Right(${_camel(modelType)}FromJson(result)),
);
}
''';
switch (httpMethod.toLowerCase()) {
case 'get':
return '$header final response = await _apiClient.get<Map<String, dynamic>>(apiEndpoint, queryParams: queryParam?.toJson());\n$tail';
case 'post':
return '$header final response = await _apiClient.post<Map<String, dynamic>>(apiEndpoint, queryParams: queryParam?.toJson(), payload: payload);\n$tail';
case 'postmultipart':
return '$header final response = await _apiClient.postMultipart<Map<String, dynamic>>(apiEndpoint, queryParams: queryParam?.toJson(), payload: payload);\n$tail';
default:
return '$header final response = await _apiClient.get<Map<String, dynamic>>(apiEndpoint, queryParams: queryParam?.toJson());\n$tail';
}
}();
if (!content.contains(' $method(')) {
final idx = content.lastIndexOf('}');
final updated = '${content.substring(0, idx)}\n$remoteMethod${content.substring(idx)}';
remoteFile.writeAsStringSync(updated, flush: true);
print('๐ Updated ${feature}_remote_source.dart with ${httpMethod.toUpperCase()} $method.');
}
}
// Append endpoint stub for the method
if (endpointFile.existsSync()) {
final content = endpointFile.readAsStringSync();
final endpointStub = '''
static String $method({required String workspaceId}) => '\$_workspace/\$workspaceId/${feature}s';
''';
if (!content.contains(' $method(')) {
final idx = content.lastIndexOf('}');
final updated = '${content.substring(0, idx)}\n$endpointStub${content.substring(idx)}';
endpointFile.writeAsStringSync(updated, flush: true);
print('๐ฃ๏ธ Updated ${feature}_endpoints.dart with $method endpoint stub.');
}
}
// Create model file if needed
if (modelType.isNotEmpty) {
final modelDir = Directory('$feature/data/model/response');
if (!modelDir.existsSync()) modelDir.createSync(recursive: true);
final filePath = '$feature/data/model/response/${_snake(modelType)}.dart';
final modelFile = File(filePath);
if (!modelFile.existsSync()) {
final content = '''
import 'package:equatable/equatable.dart';
$modelType ${_camel(modelType)}FromJson(Map<String, dynamic> data) => $modelType.fromJson(data);
class $modelType extends Equatable {
const $modelType({
this.message,
this.data,
this.pagination,
});
factory $modelType.fromJson(Map<String, dynamic> json) => $modelType(
message: json['message'] as String?,
data: json['data'],
pagination: json['pagination'] != null ? Pagination.fromJson(json['pagination'] as Map<String, dynamic>) : null,
);
final String? message;
final dynamic data;
final Pagination? pagination;
$modelType copyWith({
String? message,
dynamic data,
Pagination? pagination,
}) => $modelType(
message: message ?? this.message,
data: data ?? this.data,
pagination: pagination ?? this.pagination,
);
@override
List<Object?> get props => <Object?>[message, data, pagination];
}
class Pagination extends Equatable {
const Pagination({
this.currentPage,
this.offSet,
this.totalPage,
});
factory Pagination.fromJson(Map<String, dynamic> json) => Pagination(
currentPage: json['currentPage'] as int?,
offSet: json['offSet'] as int?,
totalPage: json['totalPage'] as int?,
);
final int? currentPage;
final int? offSet;
final int? totalPage;
Pagination copyWith({
int? currentPage,
int? offSet,
int? totalPage,
}) => Pagination(
currentPage: currentPage ?? this.currentPage,
offSet: offSet ?? this.offSet,
totalPage: totalPage ?? this.totalPage,
);
@override
List<Object?> get props => <Object?>[currentPage, offSet, totalPage];
}
''';
modelFile.writeAsStringSync(content, flush: true);
print('๐ฆ Created model $modelType at $filePath');
}
}
// Append custom query class in feature_request.dart when provided
if (queryClassName != null && queryClassName.trim().isNotEmpty) {
final reqFile = File('$feature/data/model/request/${feature}_request.dart');
if (reqFile.existsSync()) {
var content = reqFile.readAsStringSync();
final className = _capitalize(queryClassName.trim());
if (!content.contains('class $className')) {
final queryClass = '''
class $className {
$className();
Map<String, dynamic> toJson() {
return <String, dynamic>{};
}
}
''';
content = '$content\n$queryClass';
reqFile.writeAsStringSync(content, flush: true);
print('๐งช Added custom query class $className in ${feature}_request.dart');
}
}
}
}