penv 2.0.0 copy "penv: ^2.0.0" to clipboard
penv: ^2.0.0 copied to clipboard

A tiny, dependency-light loader for .env-style environment files.

penv #

pub package license: MIT docs

A tiny loader for .env-style environment files, written in pure Dart. penv reads a simple KEY=value file from disk and returns it as a Map<String, String>. If the file doesn't exist yet, it can generate a placeholder for you and tell you where to fill it in.

Features #

  • Supports comments (#) and blank lines.
  • Supports a leading export prefix (as used by shell-sourced env files).
  • Strips optional single or double quotes around values, including backslash escapes (\n, \t, \r, \", \\, \$) inside double-quoted values.
  • Strips trailing inline comments on unquoted values (PORT=8080 # default).
  • Expands ${OTHER_KEY} references against earlier keys in the same file or the process environment.
  • Optionally overlays real process environment variables onto matching keys, so deployment env vars can take priority over a checked-in file.
  • Optional required-key validation with a clear error listing what's missing.
  • Typed getInt / getDouble / getBool / getString accessors.
  • Sync (penvload), non-throwing (penvloadOrNull), and async (penvloadAsync) variants.
  • Optionally auto-creates a placeholder .env file (with your own template) on first run.

Installation #

Add penv to your pubspec.yaml:

dependencies:
  penv: ^2.0.0

Then run:

dart pub get

Usage #

Create a .env file in your project root:

API_KEY=your-key-here
BASE_URL="https://example.com"
GREETING='hello world'

Load it:

import 'package:penv/penv.dart';

void main() {
  final env = penvload('.env');

  print(env['API_KEY']);   // your-key-here
  print(env['BASE_URL']);  // https://example.com
  print(env['GREETING']);  // hello world
}

Handling a missing file #

By default, if the file at path doesn't exist, penvload creates it with a placeholder template and throws EnvFileNotFoundException so you notice and fill it in:

import 'package:penv/penv.dart';

void main() {
  try {
    final env = penvload('.env');
    print(env['API_KEY']);
  } on EnvFileNotFoundException catch (e) {
    print(e); // tells you a template file was created at the given path
  }
}

You can supply your own placeholder content via template:

penvload(
  '.env',
  template: '''
# App configuration
API_KEY=
BASE_URL=
''',
);

If you'd rather penv not touch the filesystem when the file is missing, pass createFile: false. In that case no file is written, and EnvFileNotFoundException is thrown immediately:

penvload('.env', createFile: false);

If a missing file is actually fine (e.g. an optional local override file), use penvloadOrNull instead — it returns null rather than throwing, and never writes a placeholder:

final overrides = penvloadOrNull('.env.local') ?? <String, String>{};

export, inline comments, and escapes #

export API_KEY=your-key-here   # `export ` is stripped automatically
PORT=8080 # inline comments after unquoted values are stripped
GREETING="Hello\nWorld"        # \n, \t, \r, \", \\, \$ are unescaped
LITERAL='no \n unescaping here' # single-quoted values are literal
final env = penvload('.env');
print(env['GREETING']); // Hello
                         // World

Variable expansion #

${OTHER_KEY} references inside unquoted or double-quoted values are expanded using keys defined earlier in the same file, falling back to the current process environment. Unresolved references expand to an empty string. Single-quoted values are never expanded.

BASE_URL=https://example.com
FULL_URL=${BASE_URL}/api
final env = penvload('.env');
print(env['FULL_URL']); // https://example.com/api

Pass expandVariables: false to disable this and treat ${...} as literal text.

Overlaying the process environment #

Real deployments (Docker, CI, hosting platforms) often set environment variables directly instead of shipping a .env file. Pass useProcessEnvironment: true to let matching process environment variables override (or, with preferProcessEnvironment: false, be overridden by) values from the file. Only keys already declared in the file are considered — unrelated system variables like PATH are never pulled in.

final env = penvload(
  '.env',
  useProcessEnvironment: true, // process env wins over the file by default
);

Required keys #

Pass required to make sure specific keys are present (and non-empty) after parsing. If any are missing, MissingRequiredKeysException is thrown listing every missing key at once:

final env = penvload('.env', required: ['API_KEY', 'BASE_URL']);

Typed accessors #

The returned map has getInt, getDouble, getBool, and getString extension methods that parse a value (with an optional defaultValue) and throw a clear FormatException instead of a null-check crash or a silent int.parse error:

final env = penvload('.env');
final port = env.getInt('PORT', defaultValue: 8080);
final debug = env.getBool('DEBUG', defaultValue: false);
final apiKey = env.getString('API_KEY'); // throws if missing/blank

getBool accepts (case-insensitively) true/false, 1/0, yes/no, and on/off.

Async loading #

penvloadAsync mirrors penvload but avoids synchronous file I/O:

final env = await penvloadAsync('.env');

See the example/ directory for runnable scripts covering the basic flow, the advanced parsing/typed-accessor features, process environment overlay, and async loading.

API #

penvload(String path, {String template, bool createFile, bool expandVariables, bool useProcessEnvironment, bool preferProcessEnvironment, List<String>? required}) #

Reads path and returns a Map<String, String> of the parsed key-value pairs.

Parameter Type Default Description
path String required Path to the env file to read.
template String a built-in placeholder Content written to path if it doesn't exist and createFile is true.
createFile bool true Whether to create a placeholder file when path doesn't exist.
expandVariables bool true Whether to expand ${OTHER_KEY} references.
useProcessEnvironment bool false Whether to overlay Platform.environment onto keys already declared in the file.
preferProcessEnvironment bool true When overlaying, whether the process environment wins over the file's value.
required List<String>? null Keys that must be present with a non-empty value, or MissingRequiredKeysException is thrown.

Throws EnvFileNotFoundException if no file exists at path. Throws MissingRequiredKeysException if required keys are missing.

penvloadOrNull(String path, {bool expandVariables, bool useProcessEnvironment, bool preferProcessEnvironment, List<String>? required}) #

Like penvload, but returns null instead of throwing when path doesn't exist, and never creates a placeholder file. Still throws MissingRequiredKeysException if the file exists but is missing required keys.

penvloadAsync(String path, {...}) #

Async equivalent of penvload, with the same parameters and thrown exceptions.

Parsing rules #

  • Lines are trimmed before processing.
  • Empty lines and lines starting with # are ignored.
  • A leading export is stripped before the key is parsed.
  • Lines without an = are ignored.
  • The key is trimmed; empty keys are ignored.
  • The value is trimmed; if it's fully wrapped in matching ' or " quotes, the quotes are stripped.
  • Inside double-quoted values, \n, \t, \r, \", \\, and \$ are unescaped. Single-quoted values are literal.
  • Unquoted values have a trailing # comment (or \t# comment) stripped.
  • If expandVariables is true, ${OTHER_KEY} in unquoted or double-quoted values is replaced by that key's value (from earlier in the file, then the process environment), or an empty string if unresolved.
  • If duplicate keys appear, the last one in the file wins.

EnvFileNotFoundException #

Thrown by penvload and penvloadAsync when path doesn't exist.

Property Type Description
path String The path that was looked up.
createFile bool Whether a placeholder file was written to path before throwing.

MissingRequiredKeysException #

Thrown by penvload, penvloadOrNull, and penvloadAsync when one or more required keys are missing or blank after parsing.

Property Type Description
keys List<String> The keys that were missing or blank.

Contributing #

Issues and pull requests are welcome at psdkjoon/penv.

License #

MIT

0
likes
160
points
150
downloads

Documentation

API reference

Publisher

verified publisherpsdkjoon.ir

Weekly Downloads

A tiny, dependency-light loader for .env-style environment files.

Repository (GitHub)
View/report issues

Topics

#environment

License

MIT (license)

More

Packages that depend on penv