Skip to content
Back to archipelago.banuacoder.com

Shared Packages

How to add Either, Failure and BaseUseCase to a Flutter app ​

Free Reference for core_infrastructure_package: every variable, option and package it generates. Command: archipelago generate core_infrastructure_package

Generate the core infrastructure package, return results with Either and Failure, use BaseUseCase and the logger helpers, and see what it leaves out.

What you'll learn ​

  • Generating the core infrastructure package
  • Using Either, Failure and BaseUseCase for results
  • Using the logger helpers
  • Knowing what the package does not contain

Prerequisites ​

New projects already include this brick. Other bricks build on its types.

Step 1: Generate the Core Infrastructure ​

bash
archipelago generate core_infrastructure_package

The prompts are:

  • appName: the name of your app
  • organization: your company name
  • domain: the top-level domain
  • prefix: the prefix for component names
  • isForMonorepo: leave this as true
  • includeGenerated: false keeps generated files out of git

Or use a config file:

json
{
  "appName": "MyApp",
  "organization": "MyCompany",
  "domain": "com",
  "prefix": "App",
  "isForMonorepo": true,
  "includeGenerated": false
}
bash
archipelago generate core_infrastructure_package --config core_config.json

Step 2: Understand the Generated Structure ​

The brick splits into a contract and an implementation:

text
shared/core_infrastructure_sdk/
├── core_infrastructure_api/
│   └── lib/src/
│       ├── base/            # BaseUseCase, Either
│       ├── failures/        # Failure
│       └── log/             # Log contract and LogType
└── core_infrastructure_impl/
    └── lib/src/
        ├── di/              # injector.dart, register_module.dart
        ├── log/             # Filter and printer classes
        └── utils/           # logger.dart, extensions, CoreInjectorKey

The _api package has no Flutter dependency. Feature packages depend on it for the shared result types.

Step 3: Check the Registration ​

The package declares a @microPackageInit entry point, setupCoreInfrastructureDependencies(). The app injector registers its module. RegisterModule provides a lazy Logger.

This package does not hold the feature registry. FeatureManifest, FeatureSDK and the registry live in shared/feature_sdk. See Feature Manifests and SDKs.

Step 4: Use the Result Types ​

Either has the Failure on the left and the value on the right:

dart
Future<Either<Failure, User>> getUser(String id) async { ... }

result.fold(
  (failure) => print(failure.message),
  (user) => print(user.name),
);

Failure is a plain value with message and errno. Use BaseUseCase for a repository-backed use case:

dart
class GetUserUseCase extends BaseUseCase<User, String, UserRepository> {
  GetUserUseCase({required super.repo});

  @override
  Future<Either<Failure, User>> call(String id) => repo.getUser(id);
}

BaseUseCaseNoParam covers use cases without parameters.

Step 5: Use the Logger Helpers ​

dart
logInfo('user logged in');
logError('failed to load', error, stackTrace);

The extension methods logDebug, logInfo, logWarning and logError read the Logger from DI. For the injectable Log wrapper, see app_utilities.

Key Customization Points ​

CustomizationWhere to Change
Logger look and levelRegisterModule.logger in di/register_module.dart
Failure fieldscore_infrastructure_api/lib/src/failures/failure.dart
Result helperscore_infrastructure_api/lib/src/base/either.dart

Known Limitations ​

  • RegisterModule.logger always uses PrettyPrinter with no filter. ReleaseLogFilter and SimpleLogPrinter exist but are not wired in. Wire them yourself to strip logs in release builds.
  • CoreInjectorKey declares httpClient and secureStorage keys that nothing here registers.

Next Steps ​