A better/safer way to handle environment variables in Flutter.

Overview

Envify

A better and probably safer way to handle environment variables in Flutter.

To read why this is better/safer in details, skip to the motivation section.


Table of Contents


Overview

For a .env file like this,

KEY=VALUE

and a class like this,

part 'env.g.dart';

@Envify()
abstract class Env {
    static const key = _Env.key;
}

envify will generate the part file which contains the _Env class with value for KEY loaded from the .env file.

Now you can use the Env.key,

print(Env.key); // "VALUE"

Installation

Add both envify and envify_generator as dependencies,

dependencies:
  envify: any

dev_dependencies:
  envify_generator: any
  build_runner: any

If you already don't have build_runner, you need to add it too.


Usage

Add a .env file at the root of the project. Syntax and rules for the file can be viewed at dotenv rules. Define API for generation at lib/env/env.dart (you can use any file at any path but I would recommend using this so that you don't forget to add this file to .gitignore later).

Don't forget to add both .env file and env.g.dart to .gitignore! Otherwise, you might expose your environment variables.

// env/env.dart

import 'package:envify/envify.dart';
part 'env.g.dart';

@Envify()
abstract class Env {
    static const key = _Env.key;
}

Then run the generator,

# dart
pub run build_runner build
# flutter
flutter pub run build_runner build

API Documentation

Change .env file path

You can change the file to get the data to generate for, in the @Envify annotation. By this API, it is also possible to have multiple environment variables classes for multiple occasions.

@Envify(path: '.env.development')
abstract class DevEnv {}

@Envify(path: '.env.production')
abstract class ProdEnv {}

Change generated class name

By default, the generated class will be named as the name of the annotated class with a _ prefixed. You can change it using the name field. Note that the _ will always be prefixed.

@Envify(name: 'Secrets')
abstract class Env {
   static const key = _Secrets.key;
}

Motivation

I needed to use environment variables in a recent Flutter project, and the option available was flutter_dotenv which is a package tweaked over the dotenv package. Because the dotenv package only handles the environment variables only during a process, the flutter_dotenv package hack its way by exporting the .env file into the assets and loading the file during the app runtime.

But there were some problems with this approach that I noticed,

  1. The asset directory can be accessed directly through unzipping the APK, thus easily exposing the environment variables,

  2. The loading of the environment variables takes time, This is ok in a dart process because it will only load the first time during the process's lifetime, but in this case, it will load every time you open the app.

  3. Because the variables were loaded on the runtime, you can't access them as constant expressions for source code generation, For example, you won't be able to use them with tools like json_serializable and retrofit which require constant value configurations via annotations.

Envify solves all the presented issues by using code generation.


Features

  • Envify will generate code for the user defined set of keys with the values from the environment variables file which is .env by default. Since the generated code is part of the source, it will be passed through the obfuscating/compiling process during compile time making it harder to reverse engineer.

  • Envify will only generate fields that the user has passed making it handy to use with shared environment variables between multiple projects.

  • Changing between multiple environment files like .env.production and .env.development is also easier because the user can configure which file to load environment variables from via the @Envify annotation.

  • Users can also pass optional field types during the definition, which envify will use to cast the values of generated fields. But since it's not appropriate to store large values except strings in the .env file, only literal types like int, double, num, bool, and String can be parsed. If type is optional or else, String will be used as default.

  • The generated fields will be constant expressions that can be used within source code generation and every other place user needed.


Acknowledgement

To make this project possible, I had to learn about code generation which I did not know anything about. To learn, I had to read source codes of large code generator projects like json_serializable and many others. So certain parts like how the tests are written, and how the API is structured are influenced by those projects. The parser used in the generator comes from the dotenv package.

Also, using a class as an abstraction layer instead of directly accessing the generated code is a design decision I made so that the error when the env.g.dart part file is not generated, won't spread out through the project. Now even when the part file is not generated yet, the error only stays in the env.dart file.


License

MIT © Frenco Jobs

Comments
  • Update analyzer to ^4.0.0 to wotk with Flutter 3.0

    Update analyzer to ^4.0.0 to wotk with Flutter 3.0

    In order to work with Flutter 3, we'd need to upgrade analyzer to ^4.0.0.

    Seeing that this package looks somewhat abandoned 😭, I've created my own updated fork here.

    If you need it, use this in your pubspec.yaml

    dependencies:
      envify: # ^2.0.2
          git:
            url: https://github.com/techouse/envify.git
            ref: main
            path: envify
    
    dev_dependencies:
      envify_generator: # ^2.0.2
          git:
            url: https://github.com/techouse/envify.git
            ref: main
            path: envify_generator
    
    opened by techouse 5
  • Envify Generator fails due to dependency issue with crypto

    Envify Generator fails due to dependency issue with crypto

    Hi

    I am getting following error when I try to install this package.

    Because every version of envify_generator depends on analyzer ^0.40.4 which depends on crypto ^2.0.0, every version of envify_generator requires crypto ^2.0.0. And because google_fonts 2.0.0 depends on crypto ^3.0.0 and no versions of google_fonts match >2.0.0 <3.0.0, envify_generator is incompatible with google_fonts ^2.0.0. So, because salary_extras depends on both google_fonts ^2.0.0 and envify_generator 1.1.0, version solving failed. pub get failed (1; So, because salary_extras depends on both google_fonts ^2.0.0 and envify_generator 1.1.0, version solving failed.)

    bug 
    opened by sharfaz 5
  • How to automatically get the “current settings”?

    How to automatically get the “current settings”?

    Hi!

    I want to have parameters in my Flutter app that are different between debug and production. In my Spring Boot Java application, I get this automatically: I got two set of config files and pass in “debug/production” as a profile name into my application. Then Spring Boot automatically picks the right config file.

    How do I achieve this with your package in Flutter? You gave this example:

    @Envify(path: '.env.development')
    abstract class DevEnv {}
    
    @Envify(path: '.env.production')
    abstract class ProdEnv {}
    

    So I assume that I need to configure these two different “parameter classes”. Then my code needs to manually pick the right one, based on whether I’m in debug or production. Correct?

    Regards, Karsten Silz

    opened by ksilz 5
  • part files not generating variables

    part files not generating variables

    When running the generator flutter pub run build_runner build the part files are not generating any errors. The command ran successfully with no variables.

    I have two .env files: .env.production .env.development

    As well as a folder lib/env/

    The 4 files in the lib/env/ are: dev_env.dart prod_env.dart dev_env.g.dart prod_env.g.dart

    After running the generator both of the part files that are generated are empty.

    I added 3 environment variables to each .env file NAME=testingdev KIND=testingdev NUMBER=10

    The result is:

    // GENERATED CODE - DO NOT MODIFY BY HAND
    
    part of 'dev_env.dart';
    
    // **************************************************************************
    // EnvifyGenerator
    // **************************************************************************
    
    class _DevEnv {}
    

    [✓] Flutter (Channel stable, 2.2.3, on macOS 11.6 20G165 darwin-x64, locale en-US) • Flutter version 2.2.3 at /Users/mrice/Development/flutter • Framework revision f4abaa0735 (4 months ago), 2021-07-01 12:46:11 -0700 • Engine revision 241c87ad80 • Dart version 2.13.4

    [✓] Android toolchain - develop for Android devices (Android SDK version 31.0.0-rc5) • Android SDK at /Users/mrice/Library/Android/sdk • Platform android-31, build-tools 31.0.0-rc5 • ANDROID_HOME = /Users/mrice/Library/Android/sdk • Java binary at: /Applications/Android Studio.app/Contents/jre/jdk/Contents/Home/bin/java • Java version OpenJDK Runtime Environment (build 11.0.10+0-b96-7281165) • All Android licenses accepted.

    [✓] Xcode - develop for iOS and macOS • Xcode at /Applications/Xcode.app/Contents/Developer • Xcode 13.0, Build version 13A233 • CocoaPods version 1.10.1

    [✓] Chrome - develop for the web • Chrome at /Applications/Google Chrome.app/Contents/MacOS/Google Chrome

    [✓] Android Studio (version 2020.3) • Android Studio at /Applications/Android Studio.app/Contents • Flutter plugin can be installed from: 🔨 https://plugins.jetbrains.com/plugin/9212-flutter • Dart plugin can be installed from: 🔨 https://plugins.jetbrains.com/plugin/6351-dart • Java version OpenJDK Runtime Environment (build 11.0.10+0-b96-7281165)

    [✓] Connected device (1 available) • Chrome (web) • chrome • web-javascript • Google Chrome 94.0.4606.81

    • No issues found!

    opened by matthewrice345 2
  • Dep upgrade / Null-safety conversion for generator

    Dep upgrade / Null-safety conversion for generator

    Because build_runner >=1.12.0 depends on build >=2.0.0 <2.1.0 and every version of envify_generator depends on build ^1.5.0, build_runner >=1.12.0 is incompatible with envify_generator.
    
    opened by JEuler 2
  • Problem with dependency flutter_test:

    Problem with dependency flutter_test:

    Hi there. When integrating this library to my project I am facing the following problem:

    Running "flutter pub get" in app_template...
    Because envify_generator >=1.1.0 depends on path ^1.8.0-nullsafety.3 and every version of flutter_test from sdk depends on path 1.8.0-nullsafety.1, envify_generator >=1.1.0 is incompatible with flutter_test from sdk.

    Is there a workaround which solves this issue?

    dev_dependencies:
      flutter_driver:
        sdk: flutter
      flutter_test:
        sdk: flutter
      auto_route_generator: ^0.6.10
      build_runner: null
      freezed: ^0.12.2
      injectable_generator: ^1.0.6
      json_serializable: ^3.5.0
      lint: ^1.3.0
      test: ^1.16.0-nullsafety
    
    

    Next to that I also faced this issue. Right now I am using the follwoing environment:

    environment:
      sdk: ">=2.7.0 <3.0.0"
    
    

    The current Dart SDK version is 2.10.4. Because app_template depends on envify >=2.0.0 which requires SDK version >=2.12.0-0 <3.0.0, version solving failed. pub get failed (1; Because app_template depends on envify >=2.0.0 which requires SDK version >=2.12.0-0 <3.0.0, version solving failed.) exit code 1

    Regards, Marcel

    opened by pauli2406 2
  • upgrading dependencies

    upgrading dependencies

    envify is no longer compatible with other builder packages like

    • json_serializable
    • built_value
    • freezed
    Because freezed >=0.14.3 depends on analyzer ^2.0.0 and envify_generator >=2.0.0 depends on analyzer ^1.2.0, version solving failed.
    
    opened by SunlightBro 1
  • support for `.env` files bundled in assets (needed for web support)

    support for `.env` files bundled in assets (needed for web support)

    Currently, it uses dart:io (no web support) to read the .env files. https://github.com/frencojobs/envify/blob/efceeb56f8e20a5690d9b7ce0164153cb891cf55/envify_generator/lib/src/load_envs.dart#L14

    During research for package, I was reading at flutter_dotenv, and it allows to use .env files specified in pubspec.yaml under assets.

    Will Envify include support using assets files? (I believe this is the only way for cross-platform build, such as web).

    opened by calvintam236 1
  • Allow builders options for envify, to exclude files during `build_runner`

    Allow builders options for envify, to exclude files during `build_runner`

    envify should most of the time only need to generate one file, but it tries to run on every file , (for example if your using json_serializable in the same project)

    Output
    ...
    [INFO] Heartbeat:6.6s elapsed, 17/26 actions completed.
    [FINE] envify_generator:envify on lib/utils/union.dart:Running EnvifyGenerator
    [FINE] envify_generator:envify on lib/api/model/build_information.dart:Running EnvifyGenerator
    [FINE] envify_generator:envify on lib/api/model/azure_subscription.dart:Running EnvifyGenerator
    [FINE] envify_generator:envify on lib/api/model/destination.dart:Running EnvifyGenerator
    [FINE] envify_generator:envify on lib/api/model/basic_release_details.dart:Running EnvifyGenerator
    [FINE] envify_generator:envify on lib/api/model/owner.dart:Running EnvifyGenerator
    [FINE] envify_generator:envify on lib/api/model/app.dart:Running EnvifyGenerator
    [FINE] envify_generator:envify on lib/api/model/release_details.dart:Running EnvifyGenerator
    [INFO] Heartbeat:12.3s elapsed, 25/26 actions completed.
    [FINE] envify_generator:envify on lib/state/app_state.dart:Running EnvifyGenerator
    

    While checking and comparing with other builder packages I saw that it is possible to set options in build.yaml so I tried it also with envify like so:

    build.yaml
    targets:
      $default:
        builders:
          json_serializable:
            enabled: true
            generate_for:
              exclude:
                - lib
              include:
                - lib/api/model/*
                - lib/state/app_state.dart
            options:
              explicit_to_json: true
          envify:
            enabled: true
            generate_for:
              exclude:
                - lib
              include:
                - lib/utils/env.dart
    

    But this only shows the following Warning, and still tries to run envify generator over every file.

    pub run build_runner build --delete-conflicting-outputs --verbose
    [INFO] Entrypoint:Generating build script...
    [INFO] Entrypoint:Generating build script completed, took 631ms
    [INFO] Bootstrap:Precompiling build script......
    [INFO] Bootstrap:Precompiling build script... completed, took 4.7s
    [WARNING] ApplyBuilders:
    Configuring `envify:envify` in target `exampler:example` but this is not a known Builder
    
    opened by SunlightBro 1
  • Generator is not get the complete key value

    Generator is not get the complete key value

    Hello,

    Thank you for make this package is really useful.

    I'm facing an issue, in my .env file I have the following

    API_URL=http://localhost:5050/path/to/api

    and the generator is only generate part of this:

    // GENERATED CODE - DO NOT MODIFY BY HAND
    
    part of 'env.dart';
    
    // **************************************************************************
    // EnvifyGenerator
    // **************************************************************************
    
    class _Env {
      static const api_url = 'http://localhost:5050';
    }
    
    opened by lucianefalcao 1
  • Updates and Obfuscation

    Updates and Obfuscation

    This PR is based off on @techouse's updates which

    • updates Flutter to 3.x
    • updates dependencies

    Additionally to these changes, I added an option to further obfuscate values from the env file. Documentation is missing, but it should be kind of self-explanatory. When inspecting the final .so-library (tested on Android), I noticed that Strings can be found very easily using, e.g., the strings command. My approach uses separate randomly generated keys that are used in an XOR operation with the corresponding values in order to obfuscate them and circumvent finding the values using strings.

    NO! I am not saying, this can be used to make every value undetectable in your final distributable binary... But if you want a adversary to have a bad time reading out your values, here you go :o)

    Edit: You can use this fork using

    dependencies:
      envify:
          git:
            url: https://github.com/ThexXTURBOXx/envify.git
            ref: dev
            path: envify
    
    dev_dependencies:
      envify_generator:
          git:
            url: https://github.com/ThexXTURBOXx/envify.git
            ref: dev
            path: envify_generator
    

    Closes #27 Closes #24 Closes #22

    opened by ThexXTURBOXx 4
  • issue with github workflow

    issue with github workflow

    I dont know if , this is the right place to post this issue,

    But before i was trying to use envify,

    i added a run command of flutter pub run build_runner build

    i know it wont work since i dont have .env file on the repo.

    so i try the method used in github workflow to declare the env

    but also it didnt work, i believe the env github workflow is using is the ENV

    on linux instance or whatever it may be on windows , but linux and mac is the same

    if we created a ENV VAR,

    so basically the issue is asking for a .env file that doesnt exists.

    i have 2 ways to go about it, one is running a shell script and use the ENV var declared with github.

    and pipe it to .env and .env.dev ...

    2nd one is to simply remove from .gitignore env.g.dart

    I hope you guys have more better solution in my mind

    please if you have please share thanks

    opened by uriah-we 1
  • Add ignore field annotation

    Add ignore field annotation

    The purpose is to ignore some elements we define in our @Envify annotated class from being read by envify_generator

    like computed fields

    
    @Envify(path: '.env')
    class Env {
      // site
      static const String secretKey = _GeneratedEnv.secretKey;
      static const bool isDebugMode = _GeneratedEnv.isDebugMode;
      static const String domain = _GeneratedEnv.domain;
      static const String port = _GeneratedEnv.port;
    
      // database
      static const String dbHost = _GeneratedEnv.dbHost;
      static const String dbPort = _GeneratedEnv.dbPort;
      static const String dbUser = _GeneratedEnv.dbUser;
      static const String dbPassword = _GeneratedEnv.dbPassword;
    
      @EnvifyIgnore()
      static final String baseUrl = 'http://${GeneratedEnv.domain}:${GeneratedEnv.port}';
    }
    
    

    right now envify throws error during generation since baseUrl value is not defined in .env file

    opened by easazade 0
  • Envify does not work with Freezed

    Envify does not work with Freezed

    Adding the two packages and running flutter pub get generates the following error:

    Because envify_generator >=2.0.1 depends on analyzer ^2.0.0 and freezed 1.1.1 depends on analyzer ^3.0.0, envify_generator >=2.0.1 is incompatible with freezed 1.1.1.
    And because no versions of freezed match >1.1.1 <2.0.0, envify_generator >=2.0.1 is incompatible with freezed ^1.1.1.
    
    opened by dorsamet 0
Owner
Frenco
19, Self-taught, Rustacean, Student at UIT Yangon
Frenco
A simple way to cache values that result from rather expensive operations.

cached_value A simple way to cache values that result from rather expensive operations. It is useful to cache values that: Are computed from other val

Renan 27 Nov 11, 2022
A repo of dart packages that I've built along the way.

Pub-Dev This project is a mono-repo (of sorts) for the packages I've created along the way. Most of them were born for my own needs, some may be just

Gio Palacino 3 Jul 20, 2022
You can use this package for transition between screens with interesting way with amazing animation

You can use this package for transition between screens with interesting way with amazing animation

Sajad Rahimi 5 Jul 10, 2022
Flutter Version Management: A simple CLI to manage Flutter SDK versions.

fvm Flutter Version Management: A simple cli to manage Flutter SDK versions. FVM helps with the need for a consistent app builds by allowing to refere

Leo Farias 3.2k Jan 8, 2023
A flutter utility to easily create flavors in your flutter application

Flutter Flavorizr A flutter utility to easily create flavors in your flutter application Getting Started Let's start by setting up our environment in

Angelo Cassano 268 Jan 1, 2023
🔥FlutterFire is a set of Flutter plugins that enable Flutter apps to use Firebase services.

FlutterFire is a set of Flutter plugins that enable Flutter apps to use Firebase services. You can follow an example that shows how to use these plugins in the Firebase for Flutter codelab.

null 7.4k Jan 2, 2023
Ecosistema de paquetes para Dart y Flutter desarrollados y mantenidos por la comunidad de Flutter Cuba relacionados con la tienda cubana de aplicaciones para dispositivos Android llamada Apklis.

Ecosistema de paquetes para Dart y Flutter desarrollados y mantenidos por la comunidad de Flutter Cuba relacionados con la tienda cubana de aplicacion

Flutter Cuba 12 Oct 24, 2022
UME is an in-app debug kits platform for Flutter. Produced by Flutter Infra team of ByteDance

flutter_ume English Flutter 应用内调试工具平台 当前版本内置 10 个插件, 开发者可以创建自己的插件,并集成进 UME 平台。 详见本文为 UME 开发插件部分。 flutter_ume 快速接入 特别说明 功能介绍 为 UME 开发插件 版本说明 兼容性 单测覆盖率

Bytedance Inc. 1.8k Dec 30, 2022
An android application built using Flutter that computes the Body Mass Index of person and suggestion to carry ,by taking Inputs (Weight, Height, and Age), Built using Flutter

BMI Calculator ?? Our Goal The objective of this tutorial is to look at how we can customise Flutter Widgets to achieve our own beautiful user interfa

dev_allauddin 7 Nov 2, 2022
The Coolicons icon pack for Flutter with over 400 icons available for your flutter project.

coolicons This flutter package allows you to use the Coolicons icon pack. ?? Installation In the dependencies: section of your pubspec.yaml, add the f

Abada Samuel Oghenero. 35 Oct 22, 2022
An extension to the Flutter SDK for building Flutter applications for Tizen devices.

Flutter for Tizen An extension to the Flutter SDK for building Flutter applications for Tizen devices. Flutter and the related logo are trademarks of

null 356 Dec 16, 2022
Fluro is a Flutter routing library that adds flexible routing options like wildcards, named parameters and clear route definitions.

Fluro is a Flutter routing library that adds flexible routing options like wildcards, named parameters and clear route definitions.

Luke Pighetti 3.5k Jan 4, 2023
AOP for Flutter(Dart)

AspectD Salute to AspectJ. AspectD is an AOP(aspect oriented programming) framework for dart. Like other traditional aop framework, AspectD provides c

null 1k Jan 7, 2023
Starter project and code generator for Flutter/Redux

Flutter Redux Starter/Code Generator Videos Short video ~ 1 minute Long video ~ 10 minutes We're using this approach to develop the Flutter app for In

Hillel Coren 278 Dec 12, 2022
Converts SVG icons to OTF font and generates Flutter-compatible class. Provides an API and a CLI tool.

Fontify The Fontify package provides an easy way to convert SVG icons to OpenType font and generate Flutter-compatible class that contains identifiers

Igor Kharakhordin 88 Oct 28, 2022
The Flutter code generator for your assets, fonts, colors, … — Get rid of all String-based APIs.

The Flutter code generator for your assets, fonts, colors, … — Get rid of all String-based APIs. Inspired by SwiftGen. Motivation Using asset path str

FlutterGen 1.1k Jan 6, 2023
🚀The Flutter dart code generator from zeplin. ex) Container, Text, Color, TextStyle, ... - Save your time.

Flutter Gen Zeplin Extension ?? The Flutter dart code generator from zeplin. ex) Container, Text, Color, TextStyle, ... - Save your time. ⬇ 1.1k Getti

NAVER 49 Oct 12, 2022
Okan YILDIRIM 37 Jul 10, 2022