generateBoilerplate method
void
generateBoilerplate({})
Renders all Mustache templates into the feature directory.
Delegates per-layer presentation files to focused private helpers so each layer's templates are managed in one place, making it straightforward to add new layers without touching unrelated code.
Implementation
void generateBoilerplate({
required String featureName,
required String basePath,
required String templateBasePath,
required Context context,
required bool overwrite,
}) {
// ── Shared helpers ────────────────────────────────────────────────────
// Deduplicated list of response entities used for import generation.
// In single-response mode this is just the one feature entity.
final responseEntities = _buildResponseEntities(context);
// Common enriched methods map (adds methodNameLowerCase + response fields).
final enriched = _enrichedMethods(context.methods);
// Root context additions shared across templates.
final baseCtx = {
...context.toMap(),
'featureNameLower': featureName,
'responseEntities': responseEntities,
};
// ── Injector ──────────────────────────────────────────────────────────
renderTemplate(
'$templateBasePath/injector.mustache',
'${context.projectRoot}/lib/core/di/injector.dart',
{'projectName': context.projectName},
overwrite: overwrite,
);
// ── Model & Entity ────────────────────────────────────────────────────
if (context.isMultiResponse) {
// One entity file + one model file per named response.
for (final entity in context.entities) {
renderTemplate(
'$templateBasePath/domain/entity.mustache',
'$basePath/domain/entities/${entity.nameLower}_entity.dart',
entity.toMap(),
overwrite: overwrite,
);
renderTemplate(
'$templateBasePath/data/model.mustache',
'$basePath/data/models/${entity.nameLower}_model.dart',
{
...entity.toMap(),
'nameLowerCase': entity.nameLower,
'featureNameLower': featureName,
'projectName': context.projectName,
},
overwrite: overwrite,
);
}
} else {
// Single-response: original behaviour.
renderTemplate(
'$templateBasePath/data/model.mustache',
'$basePath/data/models/${featureName}_model.dart',
{...context.toMap(), 'featureNameLower': featureName},
overwrite: overwrite,
);
renderTemplate(
'$templateBasePath/domain/entity.mustache',
'$basePath/domain/entities/${featureName}_entity.dart',
context.toMap(),
overwrite: overwrite,
);
}
// ── Repository (abstract) ─────────────────────────────────────────────
renderTemplate(
'$templateBasePath/domain/repository.mustache',
'$basePath/domain/repositories/${featureName}_repository.dart',
{...baseCtx, 'methods': enriched},
overwrite: overwrite,
);
// ── Repository Impl ───────────────────────────────────────────────────
renderTemplate(
'$templateBasePath/data/repository_impl.mustache',
'$basePath/data/repositories/${featureName}_repository_impl.dart',
{...baseCtx, 'methods': enriched},
overwrite: overwrite,
);
// ── Remote Datasource ─────────────────────────────────────────────────
renderTemplate(
'$templateBasePath/data/remote_datasource.mustache',
'$basePath/data/datasources/${featureName}_remote_datasource.dart',
{...baseCtx, 'methods': enriched},
overwrite: overwrite,
);
// ── Use Cases ─────────────────────────────────────────────────────────
if (context.generateUseCase) {
renderTemplate(
'$templateBasePath/usecase.mustache',
'${context.projectRoot}/lib/features/shared/usecase/usecase.dart',
context.toMap(),
overwrite: overwrite,
);
for (var method in context.methods) {
renderTemplate(
'$templateBasePath/domain/usecase.mustache',
'$basePath/domain/usecases/${method.methodName.camelCaseToSnakeCase()}_usecase.dart',
{
'name': context.name,
'isList': context.isList,
'nameLowerCase': context.nameLowerCase,
'nameCamelCase': context.nameCamelCase,
'projectName': context.projectName,
'isMultiResponse': context.isMultiResponse,
...method.toMap(),
},
overwrite: overwrite,
);
}
}
// ── Presentation layer ────────────────────────────────────────────────
switch (context.config.layer) {
case PresentationLayer.bloc:
_generateBlocFiles(
featureName: featureName,
basePath: basePath,
templateBasePath: templateBasePath,
context: context,
enriched: enriched,
baseCtx: baseCtx,
overwrite: overwrite,
);
case PresentationLayer.riverpod:
_generateRiverpodFiles(
featureName: featureName,
basePath: basePath,
templateBasePath: templateBasePath,
context: context,
enriched: enriched,
baseCtx: baseCtx,
overwrite: overwrite,
);
case PresentationLayer.getx:
_generateGetXFiles(
featureName: featureName,
basePath: basePath,
templateBasePath: templateBasePath,
context: context,
enriched: enriched,
baseCtx: baseCtx,
overwrite: overwrite,
);
case null:
// Unreachable after validateSchema; here for exhaustive switch safety.
break;
}
}