envStub function

String envStub({
  1. required Map<String, String> encryptedMap,
  2. String? appKey,
  3. bool useDartDefine = false,
})

Generates the env.g.dart file content with encrypted environment variables.

encryptedMap - Map of key-value pairs with encrypted values appKey - The APP_KEY used for encryption (null if using --dart-define mode) useDartDefine - Whether to use String.fromEnvironment for APP_KEY

Implementation

String envStub({
  required Map<String, String> encryptedMap,
  String? appKey,
  bool useDartDefine = false,
}) {
  final buffer = StringBuffer();

  // Header comment
  buffer.writeln('// GENERATED CODE - DO NOT MODIFY BY HAND');
  buffer.writeln('// Generated by: metro make:env');
  buffer.writeln(
      '// **************************************************************************');
  buffer.writeln('');
  buffer.writeln("import 'dart:convert';");
  buffer.writeln('');

  // Start class
  buffer.writeln('/// Auto-generated environment configuration.');
  buffer.writeln(
      '/// Do not edit this file manually. Run `metro make:env` to regenerate.');
  buffer.writeln('class Env {');
  buffer.writeln('  Env._();');
  buffer.writeln('');

  // APP_KEY - either embedded or from dart-define
  if (useDartDefine) {
    buffer.writeln("  /// APP_KEY injected via --dart-define at build time.");
    buffer.writeln(
        "  static const String _appKey = String.fromEnvironment('APP_KEY');");
  } else {
    buffer
        .writeln('  /// APP_KEY for decryption (obfuscated at compile time).');
    buffer.writeln("  static const String _appKey = '$appKey';");
  }
  buffer.writeln('');

  // Encrypted values map
  buffer.writeln('  /// Encrypted environment values.');
  buffer.writeln('  static const Map<String, String> _encrypted = {');
  for (final entry in encryptedMap.entries) {
    buffer.writeln("    '${entry.key}': '${entry.value}',");
  }
  buffer.writeln('  };');
  buffer.writeln('');

  // Cache for decrypted values
  buffer.writeln('  /// Cache for decrypted values.');
  buffer.writeln('  static final Map<String, dynamic> _cache = {};');
  buffer.writeln('');

  // XOR decrypt method
  buffer.writeln('  /// Decrypts a base64-encoded XOR-encrypted string.');
  buffer.writeln('  static String _decrypt(String encrypted) {');
  buffer.writeln('    final encryptedBytes = base64Decode(encrypted);');
  buffer.writeln('    final keyBytes = utf8.encode(_appKey);');
  buffer.writeln('    final decryptedBytes = <int>[];');
  buffer.writeln('');
  buffer.writeln('    for (var i = 0; i < encryptedBytes.length; i++) {');
  buffer.writeln(
      '      decryptedBytes.add(encryptedBytes[i] ^ keyBytes[i % keyBytes.length]);');
  buffer.writeln('    }');
  buffer.writeln('');
  buffer.writeln('    return utf8.decode(decryptedBytes);');
  buffer.writeln('  }');
  buffer.writeln('');

  // Parse value helper
  buffer.writeln('  /// Parses a string value to the appropriate type.');
  buffer.writeln('  static dynamic _parseValue(String value) {');
  buffer.writeln("    if (value == 'null') return null;");
  buffer.writeln("    if (value.toLowerCase() == 'true') return true;");
  buffer.writeln("    if (value.toLowerCase() == 'false') return false;");
  buffer.writeln("    if (value == '\"\"') return '';");
  buffer.writeln('    return value;');
  buffer.writeln('  }');
  buffer.writeln('');

  // Get method
  buffer.writeln('  /// Gets an environment variable by key.');
  buffer.writeln('  ///');
  buffer.writeln(
      '  /// Returns the decrypted value, or [defaultValue] if the key is not found.');
  buffer.writeln('  /// Values are automatically parsed:');
  buffer.writeln("  /// - 'true'/'false' -> bool");
  buffer.writeln("  /// - 'null' -> null");
  buffer.writeln("  /// - '\"\"' -> empty string");
  buffer.writeln('  static dynamic get(String key, {dynamic defaultValue}) {');
  buffer.writeln('    // Return from cache if available');
  buffer.writeln('    if (_cache.containsKey(key)) {');
  buffer.writeln('      return _cache[key];');
  buffer.writeln('    }');
  buffer.writeln('');
  buffer.writeln('    // Check if key exists');
  buffer.writeln('    if (!_encrypted.containsKey(key)) {');
  buffer.writeln('      return defaultValue;');
  buffer.writeln('    }');
  buffer.writeln('');
  buffer.writeln('    // Decrypt and parse the value');
  buffer.writeln('    final decrypted = _decrypt(_encrypted[key]!);');
  buffer.writeln('    final parsed = _parseValue(decrypted);');
  buffer.writeln('');
  buffer.writeln('    // Cache the result');
  buffer.writeln('    _cache[key] = parsed;');
  buffer.writeln('');
  buffer.writeln('    return parsed;');
  buffer.writeln('  }');
  buffer.writeln('');

  // Contains key method
  buffer.writeln('  /// Checks if an environment variable exists.');
  buffer.writeln('  static bool containsKey(String key) {');
  buffer.writeln('    return _encrypted.containsKey(key);');
  buffer.writeln('  }');
  buffer.writeln('');

  // Get all keys method
  buffer.writeln('  /// Returns all available environment variable keys.');
  buffer.writeln('  static List<String> get keys => _encrypted.keys.toList();');

  // Close class
  buffer.writeln('}');

  return buffer.toString();
}