-
Notifications
You must be signed in to change notification settings - Fork 73
v5 proposal #40
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Draft
lesnitsky
wants to merge
1
commit into
mockturtl:master
Choose a base branch
from
lesnitsky:master
base: master
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
Draft
v5 proposal #40
Changes from all commits
Commits
File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,22 +1,36 @@ | ||
| /// Loads environment variables from a `.env` file. | ||
| /// Loads environment variables from a `.env` file and merges with | ||
| /// `Platform.environment`. | ||
| /// | ||
| /// ## usage | ||
| /// ## usages | ||
| /// | ||
| /// Call [DotEnv.load] to parse the file(s). | ||
| /// Read variables from the underlying [Map] using the `[]` operator. | ||
| /// Use the default instance of [DotEnv] to read env vars: | ||
| /// | ||
| /// import 'package:dotenv/dotenv.dart'; | ||
| /// | ||
| /// void main() { | ||
| /// final myVar = DotEnv.instance['MY_VAR']; | ||
| /// } | ||
| /// | ||
| /// Use `DotEnv(parser)..load()` to create a `DotEnv` instance | ||
| /// with a custom parser: | ||
| /// | ||
| /// import 'package:dotenv/dotenv.dart'; | ||
| /// | ||
| /// class CustomParser implements Parser { | ||
| /// Map<String, String> parse(Iterable<String> lines) { | ||
| /// // custom implementation | ||
| /// } | ||
| /// } | ||
| /// | ||
| /// void main() { | ||
| /// var env = DotEnv(includePlatformEnvironment: true) | ||
| /// ..load('path/to/my/.env'); | ||
| /// var foo = env['foo']; | ||
| /// var homeDir = env['HOME']; | ||
| /// final env = DotEnv(CustomParser())..load(); | ||
| /// final foo = env['foo']; | ||
| /// final homeDir = env['HOME']; | ||
| /// // ... | ||
| /// } | ||
| /// | ||
| /// Verify required variables are present: | ||
| /// | ||
| /// const _requiredEnvVars = ['host', 'port']; | ||
| /// bool get hasEnv => env.isEveryDefined(_requiredEnvVars); | ||
| export 'package:dotenv/src/dotenv.dart'; | ||
| export 'package:dotenv/src/dotenv.dart' show DotEnv, Parser; |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -4,60 +4,76 @@ import 'dart:io'; | |
|
|
||
| import 'package:meta/meta.dart'; | ||
|
|
||
| import 'parser.dart'; | ||
| part 'parser.dart'; | ||
|
|
||
| final _env = <String, String>{ | ||
| ...Platform.environment, | ||
| }; | ||
|
|
||
| @visibleForTesting | ||
| Map<String, String> get loadedEnv => _env; | ||
|
|
||
| /// Loads key-value pairs from a file into a [Map<String, String>]. | ||
| /// | ||
| /// The parser will attempt to handle simple variable substitution, | ||
| /// respect single- vs. double-quotes, and ignore `#comments` or the `export` keyword. | ||
| class DotEnv { | ||
| /// If true, the underlying map will contain the entries of [Platform.environment], | ||
| /// even after calling [clear]. | ||
| /// Otherwise, it will be empty until populated by [load]. | ||
| final bool includePlatformEnvironment; | ||
| static late DotEnv _instance; | ||
| static bool _isInitialized = false; | ||
|
|
||
| /// If true, suppress "file not found" messages on [stderr] during [load]. | ||
| final bool quiet; | ||
|
|
||
| final _map = <String, String>{}; | ||
| /// Returns an instance of [DotEnv] with default [DefaultParser]. | ||
| /// | ||
| /// ```dart | ||
| /// final myVar = DotEnv.instance['MY_VAR']; | ||
| /// ``` | ||
| /// | ||
| /// If you need a custom .env file parser, create a new instance of [DotEnv]. | ||
| /// | ||
| /// ```dart | ||
| /// class CustomParser implements Parser { | ||
| /// Map<String, String> parse(Iterable<String> lines) { | ||
| /// // custom implementation | ||
| /// } | ||
| /// } | ||
| /// | ||
| /// final env = DotEnv(CustomParser())..load(); | ||
| static DotEnv get instance { | ||
| if (!_isInitialized) { | ||
| _instance = const DotEnv()..load(); | ||
| _isInitialized = true; | ||
| } | ||
|
|
||
| DotEnv({this.includePlatformEnvironment = false, this.quiet = false}) { | ||
| if (includePlatformEnvironment) _addPlatformEnvironment(); | ||
| return _instance; | ||
| } | ||
|
|
||
| /// Provides access to the underlying [Map]. | ||
| /// | ||
| /// Prefer using [operator[]] to read values. | ||
| @visibleForTesting | ||
| Map<String, String> get map => _map; | ||
| final DefaultParser _parser; | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Shouldn't this be of type |
||
|
|
||
| const DotEnv([this._parser = const DefaultParser()]); | ||
|
|
||
| /// Reads the value for [key] from the underlying map. | ||
| /// | ||
| /// Returns `null` if [key] is absent. See [isDefined]. | ||
| String? operator [](String key) => _map[key]; | ||
| String? operator [](String key) => _env[key]; | ||
|
|
||
| /// Calls [Map.addAll] on the underlying map. | ||
| void addAll(Map<String, String> other) => _map.addAll(other); | ||
| void addAll(Map<String, String> other) => _env.addAll(other); | ||
|
|
||
| /// Calls [Map.clear] on the underlying map. | ||
| /// | ||
| /// If [includePlatformEnvironment] is true, the entries of [Platform.environment] will be reinserted. | ||
| void clear() { | ||
| _map.clear(); | ||
| if (includePlatformEnvironment) _addPlatformEnvironment(); | ||
| _env.clear(); | ||
| } | ||
|
|
||
| /// Equivalent to [operator []] when the underlying map contains [key], | ||
| /// and the value is non-empty. See [isDefined]. | ||
| /// | ||
| /// Otherwise, calls [orElse] and returns the value. | ||
| String getOrElse(String key, String Function() orElse) => | ||
| isDefined(key) ? _map[key]! : orElse(); | ||
| isDefined(key) ? _env[key]! : orElse(); | ||
|
|
||
| /// True if [key] has a nonempty value in the underlying map. | ||
| /// | ||
| /// Differs from [Map.containsKey] by excluding empty values. | ||
| bool isDefined(String key) => _map[key]?.isNotEmpty ?? false; | ||
| bool isDefined(String key) => _env[key]?.isNotEmpty ?? false; | ||
|
|
||
| /// True if all supplied [vars] have nonempty value; false otherwise. | ||
| /// | ||
|
|
@@ -68,23 +84,18 @@ class DotEnv { | |
| /// to the underlying [Map]. | ||
| /// | ||
| /// Logs to [stderr] if any file does not exist; see [quiet]. | ||
| void load( | ||
| [Iterable<String> filenames = const ['.env'], | ||
| Parser psr = const Parser()]) { | ||
| void load([ | ||
| Iterable<String> filenames = const ['.env'], | ||
| ]) { | ||
| for (var filename in filenames) { | ||
| var f = File.fromUri(Uri.file(filename)); | ||
| var lines = _verify(f); | ||
| _map.addAll(psr.parse(lines)); | ||
| } | ||
| } | ||
|
|
||
| void _addPlatformEnvironment() => _map.addAll(Platform.environment); | ||
|
|
||
| List<String> _verify(File f) { | ||
| if (!f.existsSync()) { | ||
| if (!quiet) stderr.writeln('[dotenv] Load failed: file not found: $f'); | ||
| return []; | ||
| final uri = Uri.file(filename); | ||
| final f = File.fromUri(uri); | ||
|
|
||
| if (f.existsSync()) { | ||
| final content = f.readAsLinesSync(); | ||
| final parsed = _parser.parse(content); | ||
| _env.addAll(parsed); | ||
| } | ||
| } | ||
| return f.readAsLinesSync(); | ||
| } | ||
| } | ||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,10 +1,13 @@ | ||
| import 'dart:io'; | ||
| part of './dotenv.dart'; | ||
|
|
||
| import 'package:meta/meta.dart'; | ||
| abstract class Parser { | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I guess this serve as an interface. So it could be |
||
| /// Parses .env file contents into a [Map<String, String>]. | ||
| Map<String, String> parse(Iterable<String> lines); | ||
| } | ||
|
|
||
| /// Creates key-value pairs from strings formatted as environment | ||
| /// variable definitions. | ||
| class Parser { | ||
| class DefaultParser implements Parser { | ||
| static const _singleQuot = "'"; | ||
| static const _keyword = 'export'; | ||
|
|
||
|
|
@@ -13,8 +16,8 @@ class Parser { | |
| static final _bashVar = | ||
| new RegExp(r'(?:\\)?(\$)(?:{)?([a-zA-Z_][\w]*)+(?:})?'); | ||
|
|
||
| /// [Parser] methods are pure functions. | ||
| const Parser(); | ||
| /// [DefaultParser] methods are pure functions. | ||
| const DefaultParser(); | ||
|
|
||
| /// Substitutes $bash_vars in [val] with values from [env]. | ||
| @visibleForTesting | ||
|
|
||
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Making the loaded environment
Mapfully available (even if just read only) would help to not have to update any existing types in apps.Since
Platform.environmentis a plain oldMap<String, String>It would be preferred if we can get access to the raw map