Skip to content
CARP Docs
Ask AISystemLightDark
On this page

Environment and servers

Override --dart-define launch arguments and switch servers at runtime with DebugEnv.

Copy MarkdownOpen inOpen in GitHubView as MarkdownOpen in Scira AIOpen in ChatGPTOpen in ClaudeOpen in Cursor

CARP apps select their environment with String.fromEnvironment (--dart-define), which is fixed at build time. DebugEnv adds a runtime override layer, persisted in SharedPreferences, so a tester can point the app at a different server, change the deployment mode or debug level, and flip feature flags without rebuilding.

How it works

  1. Initialize early (debug only)

    In your debug-only setup, load the persisted overrides before anything reads configuration: call await DebugEnv().initialize() (optionally passing your existing SharedPreferences), then install the hook with debugLaunchOverride = DebugEnv().overrideOf.

  2. Register the arguments

    DebugEnv().registerAll([...]) tells the Environment tool which arguments exist and how to edit them.

  3. Read through the hook

    Replace String.fromEnvironment('x') reads with debugLaunchOverride?.call('x') ?? const String.fromEnvironment('x').

  4. Apply or restart

    After editing, Apply runs your onApply hook to reconfigure the app live, and Restart relaunches the app so the new values are read from scratch.

See the Quickstart for the complete setup.

Reading values

Warning

Because the package is meant to be a dev_dependency, your production code must not call DebugEnv directly. Read through the app-local debugLaunchOverride hook instead (see Production builds). Use DebugEnv itself only inside the debug-only setup file, where the hook is installed with debugLaunchOverride = DebugEnv().overrideOf.

// In production-reachable code (BLoC, backend): read via the hook.
final mode = debugLaunchOverride?.call('deployment-mode')
    ?? const String.fromEnvironment('deployment-mode', defaultValue: 'production');
final timeout = int.tryParse(debugLaunchOverride?.call('api-timeout') ?? '') ?? 30;

Once initialize() has completed, DebugEnv reads are synchronous, so you can use them inside constructors. They are convenient inside debug-only code:

DebugEnv().string('deployment-mode', fallback: 'production');
DebugEnv().integer('api-timeout', fallback: 30);
DebugEnv().boolean('analytics-enabled', fallback: false);

CARP example: switch the CAWS server

Read the host through the hook in your CarpBackend, and expose a reconfigure() method that re-points every CAWS service:

String get host {
  final override = debugLaunchOverride?.call('server-host') ?? '';
  return override.isNotEmpty ? override : uris[deploymentMode]!;
}
Uri get uri => Uri(scheme: 'https', host: host);

Future<void> reconfigure() async {
  _readDeploymentModeDebugLevel();              // re-read launch args
  await CarpAuthService().configure(authProperties);
  CarpService().configure(app);
  CarpParticipationService().configureFrom(CarpService());
  CarpDeploymentService().configureFrom(CarpService());
  CarpDataStreamService().configureFrom(CarpService());
}

Wire it up with onApply: () => bloc.backend.reconfigure().

Warning

Authentication tokens are server-specific. After switching servers, sign in again. The Restart action gives the cleanest slate.

EnvEntry reference

Each registered argument is described by an EnvEntry. Its type decides which editor the Environment tool renders.

PropertyTypeRequiredDefaultDescription
keyStringYes—The --dart-define name and the storage and lookup key, for example deployment-mode.
labelStringYes—Label shown in the Environment tool.
typeEnvValueTypeNotexttext, enumeration, toggle or integer.
optionsList<String>No—Allowed values when type is enumeration, rendered as a dropdown.
fallbackStringNo—The compile-time default, typically String.fromEnvironment(...). Shown when no override is set, and used by Revert to default.
groupStringNo—Optional heading for visual grouping, for example Server or Logging.
descriptionStringNo—Optional explanatory text shown under the editor.

Editor types

enumerationtextintegertoggle
EnvEntry(key: 'deployment-mode', label: 'Deployment mode',
    type: EnvValueType.enumeration, options: ['production', 'test', 'dev'],
    fallback: 'production');
EnvEntry(key: 'server-host', label: 'App server host'); // free-form
EnvEntry(key: 'api-timeout', label: 'API timeout (s)',
    type: EnvValueType.integer, fallback: '30');
EnvEntry(key: 'analytics-enabled', label: 'Analytics',
    type: EnvValueType.toggle, fallback: 'false');

Managing overrides programmatically

DebugEnv().hasOverride('server-host');           // bool
DebugEnv().overrideOf('server-host');            // String? (raw override)
await DebugEnv().setOverride('server-host', 'dev.carp.dk');
await DebugEnv().clearOverride('server-host');   // revert to default
await DebugEnv().clearAll();                      // revert everything

Note

Overrides are stored in SharedPreferences under the carp_debug_env. prefix. The Shared Preferences tool hides these keys, so they are managed only from the Environment tool; editing them in the Shared Preferences tool would not update the in-memory state.

Quick links

Page · DocumentationCARP DocumentationPage · DocumentationIntroductionPage · DocumentationQuickstartPage · DocumentationTerminologyPage · DocumentationArchitecture