11import 'dart:async' ;
22
3- import 'package:flutter/material.dart' ;
43import 'package:flutter/services.dart' show rootBundle;
54import 'package:flutter/widgets.dart' ;
65
@@ -35,7 +34,7 @@ class DotEnv {
3534 bool _isInitialized = false ;
3635 final Map <String , String > _envMap = {};
3736
38- /// A copy of variables loaded at runtime from a file + any entries from mergeWith when loaded.
37+ /// Variables loaded at runtime from a file + any entries from mergeWith when loaded.
3938 Map <String , String > get env {
4039 if (! _isInitialized) {
4140 throw NotInitializedError ();
@@ -60,62 +59,42 @@ class DotEnv {
6059 return value;
6160 }
6261
63- /// Load the enviroment variable value as an [int]
64- ///
65- /// If variable with [ name] does not exist then [ fallback] will be used.
66- /// However if also no [ fallback] is supplied an error will occur.
67- ///
68- /// Furthermore an [FormatException] will be thrown if the variable with [name]
69- /// exists but can not be parsed as an [int] .
70- int getInt (String name, {int ? fallback}) {
71- final value = maybeGet (name);
72- if (value == null && fallback == null ) {
73- throw AssertionError (
74- '$ name variable not found. A non-null fallback is required for missing entries' );
75- }
76- return value != null ? int . parse (value) : fallback ! ;
77- }
62+ /// Throws [AssertionError] if not found and no [fallback] given.
63+ /// Throws [FormatException] if found but not parseable.
64+ int getInt ( String name, { int ? fallback}) =>
65+ _getTyped (name, fallback, int .parse);
66+
67+ /// Throws [AssertionError] if not found and no [fallback] given.
68+ /// Throws [FormatException] if found but not parseable .
69+ double getDouble (String name, {double ? fallback}) =>
70+ _getTyped (name, fallback, double .parse );
71+
72+ /// Accepts `true` / `1` and `false` / `0` (case-insensitive).
73+ /// Throws [AssertionError] if not found and no [ fallback] given.
74+ /// Throws [FormatException] if found but not parseable.
75+ bool getBool ( String name, { bool ? fallback}) =>
76+ _getTyped (name, fallback, _parseBool);
7877
79- /// Load the enviroment variable value as a [double]
80- ///
81- /// If variable with [name] does not exist then [fallback] will be used.
82- /// However if also no [fallback] is supplied an error will occur.
83- ///
84- /// Furthermore an [FormatException] will be thrown if the variable with [name]
85- /// exists but can not be parsed as a [double] .
86- double getDouble (String name, {double ? fallback}) {
78+ T _getTyped <T >(String name, T ? fallback, T Function (String ) parse) {
8779 final value = maybeGet (name);
8880 if (value == null && fallback == null ) {
8981 throw AssertionError (
9082 '$name variable not found. A non-null fallback is required for missing entries' );
9183 }
92- return value != null ? double . parse (value) : fallback! ;
84+ return value != null ? parse (value) : fallback! ;
9385 }
9486
95- /// Load the enviroment variable value as a [bool]
96- ///
97- /// If variable with [name] does not exist then [fallback] will be used.
98- /// However if also no [fallback] is supplied an error will occur.
99- ///
100- /// Furthermore an [FormatException] will be thrown if the variable with [name]
101- /// exists but can not be parsed as a [bool] .
102- bool getBool (String name, {bool ? fallback}) {
103- final value = maybeGet (name);
104- if (value == null && fallback == null ) {
105- throw AssertionError (
106- '$name variable not found. A non-null fallback is required for missing entries' );
107- }
108- if (value != null ) {
109- if (['true' , '1' ].contains (value.toLowerCase ())) {
87+ static bool _parseBool (String value) {
88+ switch (value.toLowerCase ()) {
89+ case 'true' :
90+ case '1' :
11091 return true ;
111- } else if (['false' , '0' ].contains (value.toLowerCase ())) {
92+ case 'false' :
93+ case '0' :
11294 return false ;
113- } else {
95+ default :
11496 throw const FormatException ('Could not parse as a bool' );
115- }
11697 }
117-
118- return fallback! ;
11998 }
12099
121100 String ? maybeGet (String name, {String ? fallback}) => env[name] ?? fallback;
@@ -159,15 +138,12 @@ class DotEnv {
159138 }
160139 }
161140
162- final linesFromMergeWith = mergeWith.entries
163- .map ((entry) => "${entry .key }=${entry .value }" )
164- .toList ();
165- final allLines = linesFromMergeWith
166- ..addAll (linesFromOverrides)
167- ..addAll (linesFromFile);
168- final envEntries = parser.parse (allLines);
169- _envMap.addAll (envEntries);
170- _isInitialized = true ;
141+ _mergeAndStore (
142+ linesFromFile: linesFromFile,
143+ linesFromOverrides: linesFromOverrides,
144+ mergeWith: mergeWith,
145+ parser: parser,
146+ );
171147 }
172148
173149 void loadFromString ({
@@ -187,21 +163,28 @@ class DotEnv {
187163 throw EmptyEnvFileError ();
188164 }
189165 final linesFromFile = envString.split ('\n ' );
190- final linesFromOverrides = overrideWith
191- .map ((String lines) => lines.split ('\n ' ))
192- .expand ((x) => x)
193- .toList ();
194- final linesFromMergeWith = mergeWith.entries
195- .map ((entry) => "${entry .key }=${entry .value }" )
196- .toList ();
197-
198- final allLines = linesFromMergeWith
199- ..addAll (linesFromOverrides)
200- ..addAll (linesFromFile);
201-
202- final envEntries = parser.parse (allLines);
166+ final linesFromOverrides = overrideWith.expand ((s) => s.split ('\n ' )).toList ();
167+
168+ _mergeAndStore (
169+ linesFromFile: linesFromFile,
170+ linesFromOverrides: linesFromOverrides,
171+ mergeWith: mergeWith,
172+ parser: parser,
173+ );
174+ }
203175
204- _envMap.addAll (envEntries);
176+ void _mergeAndStore ({
177+ required List <String > linesFromFile,
178+ required List <String > linesFromOverrides,
179+ required Map <String , String > mergeWith,
180+ required Parser parser,
181+ }) {
182+ final allLines = [
183+ ...mergeWith.entries.map ((e) => '${e .key }=${e .value }' ),
184+ ...linesFromOverrides,
185+ ...linesFromFile,
186+ ];
187+ _envMap.addAll (parser.parse (allLines));
205188 _isInitialized = true ;
206189 }
207190
@@ -213,7 +196,7 @@ class DotEnv {
213196 Future <List <String >> _getEntriesFromFile (String filename) async {
214197 try {
215198 WidgetsFlutterBinding .ensureInitialized ();
216- var envString = await rootBundle.loadString (filename);
199+ final envString = await rootBundle.loadString (filename);
217200 if (envString.isEmpty) {
218201 throw EmptyEnvFileError (filename: filename);
219202 }
0 commit comments