Environment

Environment

The Environment Module in the Flood toolkit provides a powerful and flexible way to manage and customize your application's environment settings. It allows you to easily switch between different environments and define overrides using a simple file structure.

Overview

Flood provides a variety of environments you can use to test your app in. Services or Repositories defined as adapting will adapt their implementation based on the current environment. For example, instead of draining Firebase resources when testing your app, simply use the testing environment to simulate all repositories and authentication locally.

  • testing simulates all services in-memory. Restarting the app will reset everything. You can use the TestingAppComponent to define test data that will be populated every time you start the app in the testing environment.
  • device simulates all services on the device file-system. This saves authentication and repositories into the device file system, so every time you restart the app, it will persist its memory. Use the Device Files Module to inspect the device's file systems.
  • qa will prefer to use predefined emulators. For example, it will use the Local Firebase Emulator Suite for Firebase projects and your local Appwrite docker container for Appwrite projects.
  • staging and production both use online resources, such as Firebase or Appwrite.

To set the environment of your Flutter app, navigate to example/assets/config.overrides.yaml (create it if it does not exist), and set environment: [environment]. For example:

example/assets/config.overrides.yaml
environment: testing

This will set the environment of your local device to testing.

EnvironmentConfig

The EnvironmentConfig class plays a crucial role in defining how environment data is retrieved from the currently running app. It provides a set of convenient methods to access various aspects of the environment configuration.

environment returns the environment "type", all of which are listed above.

final environmentType = context.find<EnvironmentConfigCoreComponent>().environment;
// Possible options are EnvironmentType.static.testing, EnvironmentType.static.device, EnvironmentType.static.qa, EnvironmentType.static.staging, EnvironmentType.static.production, or any custom environment type you define.
 
environmentType.isOnline; // Returns whether the environment type indicates the app should use online services, such as `staging` or `production`.

With get<T>(), you can easily pull custom values from the environment, such as environment variables or values from a configuration file.

For example:

await context.find<EnvironmentConfigCoreComponent>().get<String>('custom_key'); // Returns `custom_key` from one of the config files or an environment variable.

The buildType method allows you to determine the current build type, while platform allows you to determine the platform the app is running in.

final buildType = context.find<EnvironmentConfigCoreComponent>().buildType;
if (buildType == BuildType.regular) {
  // Debug/Regular build type.
} else if (buildType == BuildType.release) {
  // Release build.
}
 
final platform = context.find<EnvironmentConfigCoreComponent>().platform;
if (platform == Platform.mobile) {
  // Mobile platform (Android/iOS)
} else if (platform == Platform.web) {
  // Web platform
} else if (platform == Platform.desktop) {
  // Desktop platform
} else if (platform == Platform.cli) {
 // CLI platform (like using Automate)
}

FileSystem

Flood recognizes that different environments have distinct ways of interacting with a file system. For example, in a Flutter app, you interact directly with the device's file system using path_provider (opens in a new tab), while in Automate, you work with the host machine's file system. To accommodate these differences, Flood provides appropriate abstractions. In the case of Flutter Web, where direct file system access is not available, Flood offers an emulated file system using local storage. The EnvironmentConfig class provides the getFileSystem() method, which allows you to retrieve the FileSystem instance suitable for the current environment. This method grants access to the storageDirectory for permanent file storage and the tempDirectory for temporary files, enabling you to work with files in a consistent manner across different environments.

/// Set some json into a `some_settings.json` file in the file-system's storage directory.
final fileSystem = context.find<EnvironmentConfigCoreComponent>().fileSystem;
await DataSource.static.crossFile(fileSystem.storageDirectory - 'some_settings.json').mapJson().set({
  'key': 'value',
});

Usage in Pond

To utilize the Environment Module effectively, you need to pass an EnvironmentConfig instance to the FloodCoreComponent. This provides the implementation for how Flood will access environment configurations.

When using Flood in a Flutter app, you'll typically use EnvironmentConfig.static.flutterAssets() to pull environment information from the assets folder and retrieve build information from the Platform class. On the other hand, when working with file-based environments, you'll use EnvironmentConfig.static.fileAssets() to pull environment information from a directory of files.

For example:

example_core/lib/pond.dart
await corePondContext.register(FloodCoreComponent(
  environmentConfig: EnvironmentConfig.static.flutterAssets(),
));