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,FailureandBaseUseCasefor results - Using the logger helpers
- Knowing what the package does not contain
Prerequisites
- An existing Archipelago monorepo (see Monorepo Scaffolding)
New projects already include this brick. Other bricks build on its types.
Step 1: Generate the Core Infrastructure
archipelago generate core_infrastructure_packageThe 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:
falsekeeps generated files out of git
Or use a config file:
{
"appName": "MyApp",
"organization": "MyCompany",
"domain": "com",
"prefix": "App",
"isForMonorepo": true,
"includeGenerated": false
}archipelago generate core_infrastructure_package --config core_config.jsonStep 2: Understand the Generated Structure
The brick splits into a contract and an implementation:
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, CoreInjectorKeyThe _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:
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:
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
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
| Customization | Where to Change |
|---|---|
| Logger look and level | RegisterModule.logger in di/register_module.dart |
| Failure fields | core_infrastructure_api/lib/src/failures/failure.dart |
| Result helpers | core_infrastructure_api/lib/src/base/either.dart |
Known Limitations
RegisterModule.loggeralways usesPrettyPrinterwith no filter.ReleaseLogFilterandSimpleLogPrinterexist but are not wired in. Wire them yourself to strip logs in release builds.CoreInjectorKeydeclareshttpClientandsecureStoragekeys that nothing here registers.
Next Steps
- Scaffold a new app that uses core infrastructure
- Set up the Network SDK
- Add utilities for the
Logwrapper