Skip to content

Releases: ikelaiah/dotenv-fp

🌿 dotenv-fp v1.2.1

Choose a tag to compare

@ikelaiah ikelaiah released this 20 Jul 20:23
3f3948a

Release Date: July 21, 2026

🚀 Overview

Version 1.2.1 is a documentation and example-reliability patch release. It
makes the runnable projects under examples/ the single
source of truth, brings every project up to the current safe usage guidance,
and adds one cross-platform command for building all examples into
examples-bin/.

The dotenv-fp API is unchanged from v1.2.0.

🌱 One Clear Beginner Path

Beginners should start with
examples/hello-dotenv/hello_dotenv.pas.
The new examples/README.md then provides an explicit
learning order:

  1. hello-dotenv — strict startup and typed validation
  2. basic — arrays, interpolation, and redacted diagnostics
  3. advanced — prefixing, layered files, and in-memory configuration
  4. environment-aware — .env.{environment} loading
  5. interactive-setup — prompts, validation, saving, and template generation

docs/examples.md is now a catalog linking to these projects
instead of a second collection of standalone programs that could drift out of
sync.

🔨 Reproducible Example Builds

Build all five Lazarus projects on Linux or macOS:

bash ./build-examples.sh

Build them on Windows PowerShell:

./build-examples.ps1

Both scripts:

  • Discover canonical examples/*/*.lpi projects one directory deep
  • Build every project in Lazarus Release mode
  • Place executables directly under examples-bin/
  • Keep compiler units under examples-bin/units/<example>/
  • Fail when a project or expected executable is missing
  • Clean the generated output directory before rebuilding

The generated examples-bin/ directory is ignored by Git.

🛡️ Safer Runnable Examples

  • Basic and advanced configuration keys are namespaced to avoid common process
    environment collisions
  • The basic example reports whether a secret exists and uses redacted
    diagnostics without printing the secret
  • The advanced example no longer prints database URLs or other potentially
    credential-bearing values
  • The interactive setup confirms that a database URL is configured without
    displaying it
  • The environment-aware example uses non-secret values in a unique temporary
    directory and removes its files on exit
  • Previously committed runtime .env files were removed; safe templates use
    .env.example names

🔄 Continuous Integration

Windows CI runs build-examples.ps1, and Linux CI runs build-examples.sh.
Both platforms smoke-test all five examples. CI supplies blank input to the
interactive setup, verifies that .env and .env.example are created, and
checks that the generated template contains no configured values.

✅ Validation

  • FPC 3.2.2: 121 tests, 0 errors, 0 failures
  • Lazarus package v1.2.1 build: pass
  • Windows PowerShell example build script: all five projects pass
  • POSIX shell script syntax check: pass
  • Newcomer hostile-environment smoke test: pass
  • All five example runtime smoke tests: pass
  • Markdown links and code fences: pass
  • git diff --check: pass

🔀 Migration from v1.2.0

No application code changes are required. The public API and runtime behavior
are unchanged.

Repository contributors should use the new build scripts instead of invoking
each example project manually. Built executables now live in examples-bin/
when using the documented workflow.

🔐 Security Reminder

Commit .env.example templates only. Keep real .env files ignored, avoid
printing credential-bearing configuration, and use a dedicated secret manager
for production credentials.


Thank you for using dotenv-fp! 🎉

For issues or suggestions, visit the
dotenv-fp repository.

🌿dotenv-fp v1.2.0

Choose a tag to compare

@ikelaiah ikelaiah released this 20 Jul 08:55

Release Date: July 20, 2026

🚀 Overview

Version 1.2.0 focuses on reliable application startup, safer diagnostics, and dependable .env file round trips. It adds strict loading with actionable errors, aggregate typed schema validation, atomic saving, secret redaction, a five-minute newcomer example, and Windows/Linux continuous integration.

Existing applications can continue using the permissive Load() API. The stricter behavior is opt-in through LoadRequired() and the schema validation methods.

✨ New Features

1. 🚨 Strict Dotenv Loading

Method: LoadRequired(const APath: string = '.env'): Boolean

Strictly loads a dotenv file and raises an actionable exception when the file is missing or malformed.

Key Benefits:

  • Reports the absolute file path
  • Identifies the line number and offending key or entry
  • Explains why parsing failed
  • Keeps the existing permissive Load() behavior available

Usage:

try
  Env.LoadRequired('.env');
except
  on E: EDotEnvException do
    WriteLn(E.Message);
end;

Depending on the failure, LoadRequired() raises EDotEnvFileNotFound, EDotEnvParseError, or EDotEnvException.


2. 🧭 Aggregate Typed Schema Validation

Types and methods:

  • TDotEnvSchemaItem
  • ValidateSchema()
  • ValidateSchemaRequired()

Validate all required configuration values and their expected types in one pass. Supported types are string, integer, boolean, and float.

Key Benefits:

  • Reports all missing and invalid values together
  • Avoids repeated fix-and-restart cycles during application startup
  • Provides both a Boolean API and an exception-based API
  • Uses the same typed rules as dotenv-fp's required getters

Usage:

Env.ValidateSchemaRequired([
  TDotEnvSchemaItem.Create('DATABASE_URL'),
  TDotEnvSchemaItem.Create('APP_PORT', dvkInteger),
  TDotEnvSchemaItem.Create('APP_DEBUG', dvkBoolean),
  TDotEnvSchemaItem.Create('REQUEST_TIMEOUT', dvkFloat)
]);

ValidateSchemaRequired() raises one EDotEnvValidationError containing every schema problem.


3. 🛡️ Redacted Diagnostics

Method: ToRedactedString: string

Produces diagnostic output while replacing values for likely secret keys with [REDACTED].

WriteLn(Env.ToRedactedString);

Verbose loading now applies the same protection so common password, token, secret, and API-key values are not printed in plaintext.

Redaction is a diagnostic safeguard, not a substitute for keeping real secrets out of source control and application logs.


4. 👋 Five-Minute Newcomer Example

A new examples/hello-dotenv/ Lazarus project demonstrates the recommended startup flow:

  1. Strictly load .env
  2. Validate all required settings
  3. Read typed values
  4. Display actionable errors

The example uses namespaced APP_PORT and APP_DEBUG keys so unrelated process variables such as PORT and DEBUG cannot unexpectedly override it. A root .env.example provides a safe configuration template.

🔧 Reliability and Safety Improvements

💾 Atomic, Escaped Saving

Save() now:

  • Quotes and escapes every value
  • Writes to a same-directory temporary file
  • Atomically replaces the destination
  • Preserves spaces, #, quotes, backslashes, control characters, and interpolation-like text across save/load round trips
Env.SetToEnv('MESSAGE', 'A value with spaces and # characters');
Env.Save('.env');
Env.LoadRequired('.env');

🧩 Parsing and Type Safety

  • Multiline double-quoted values no longer truncate at escaped quotes
  • Single-quoted values are treated as literals and do not interpolate variables
  • Empty ${} interpolation resolves to an empty string instead of querying the operating system with an empty variable name
  • The empty-interpolation fix prevents hidden Windows drive-current-directory entries, such as ::=::\, from leaking into parsed values
  • GetBoolRequired() now rejects unrecognized Boolean values instead of silently treating them as False

🧭 Clearer Environment Semantics

Documentation now distinguishes dotenv-fp's in-memory values from operating-system environment variables. SetToEnv() updates the current TDotEnv instance; it does not modify the parent process environment.

🔄 Continuous Integration

The project now validates every change on both Windows and Linux. CI builds and checks:

  • The Lazarus package
  • The complete FPCUnit test suite
  • All five Lazarus examples
  • The newcomer example with hostile generic PORT and DEBUG process variables

✅ Testing

  • ✅ FPC 3.2.2: 121 tests, 0 errors, 0 failures
  • ✅ Lazarus package build passes
  • ✅ All five Lazarus examples build and run successfully
  • ✅ Newcomer smoke test passes with PORT=not-an-integer and DEBUG=release
  • ✅ Windows and Linux CI coverage
  • ✅ No new runtime dependencies

📚 Documentation Updates

  • ✅ README updated with strict loading, schema validation, safe saving, and redacted diagnostics
  • ✅ API reference updated for the new types, methods, and exceptions
  • ✅ Getting-started and configuration guides updated
  • ✅ Root .env.example added
  • ✅ Package metadata and changelog updated for version 1.2.0

🔀 Migration Guide

From v1.1.0 to v1.2.0

No APIs were removed, and existing Load() calls remain permissive. Existing applications can upgrade without changing their loading code.

For stricter application startup, replace:

Env.Load('.env');

with:

Env.LoadRequired('.env');
Env.ValidateSchemaRequired([
  TDotEnvSchemaItem.Create('DATABASE_URL'),
  TDotEnvSchemaItem.Create('APP_PORT', dvkInteger),
  TDotEnvSchemaItem.Create('APP_DEBUG', dvkBoolean)
]);

Review these behavior refinements when upgrading:

  • GetBoolRequired() now raises an error for values other than true, false, yes, no, 1, 0, on, or off
  • Single-quoted values no longer interpolate; use double quotes when interpolation is intended
  • Files written by Save() are consistently quoted and escaped, although loading them returns the original values

🔐 Security Recommendations

  1. Never commit .env files containing real credentials
  2. Commit .env.example with safe placeholders or empty values
  3. Keep .env* ignored except for approved example files
  4. Prefer ToRedactedString() over raw values when troubleshooting
  5. Use a dedicated secret manager for production credentials

Thank you for using dotenv-fp! 🎉

For issues or suggestions, please visit: https://github.com/ikelaiah/dotenv-fp

🌿 dotenv-fp v1.1.0

Choose a tag to compare

@ikelaiah ikelaiah released this 15 Dec 20:03
81d0e9d

Overview

Version 1.1.0 adds four practical, easy-to-use features that enhance the dotenv-fp library with minimal cognitive burden for both new and experienced developers. All features follow industry-standard patterns familiar to developers from other ecosystems.

New Features

1. 🌍 Environment-Aware Loading

Method: LoadForEnvironment(const AEnvironment: string = ''): Boolean

Automatically loads base configuration from .env, then environment-specific overrides from .env.{environment}.

Key Benefits:

  • Industry-standard pattern (used in Node.js, Rails, Django, etc.)
  • Auto-detects environment from APP_ENV or NODE_ENV system variables
  • Zero cognitive burden - developers already know this pattern
  • Simplifies managing dev/staging/production configs

Usage:

// Load for specific environment
Env.LoadForEnvironment('production');  // Loads .env + .env.production

// Auto-detect from system environment
Env.LoadForEnvironment();  // Uses APP_ENV or NODE_ENV

2. 💾 Save to File

Method: Save(const APath: string = '.env'): Boolean

Saves all loaded environment variables to a .env file.

Key Benefits:

  • Generate .env files programmatically
  • Persist runtime configuration changes
  • Useful for installers and setup scripts
  • Simple API - just one method call

Usage:

Env := TDotEnv.Create;
Env.SetToEnv('DATABASE_URL', 'postgres://localhost/mydb');
Env.SetToEnv('PORT', '3000');
Env.Save('.env');  // Write to disk

3. 💬 Interactive Prompts

Method: GetOrPrompt(const AKey, APrompt: string; const ADefault: string = ''): string

Gets a value by key, or prompts the user if the value is missing.

Key Benefits:

  • Perfect for first-run setup scripts
  • Interactive configuration wizards
  • No need for separate input handling code
  • Stored value can be saved with Save()

Usage:

DbUrl := Env.GetOrPrompt('DATABASE_URL',
                        'Enter database URL',
                        'postgres://localhost/mydb');
// If DATABASE_URL exists, returns it
// If missing, prompts user and stores the answer

4. 📋 Generate Example Files

Method: GenerateExample(const ASourcePath: string = '.env'; const ADestPath: string = '.env.example'): Boolean

Creates a .env.example file from a source .env file, preserving keys and comments but removing values.

Key Benefits:

  • Standard Git best practice - commit .env.example, not .env
  • Documents required configuration for team members
  • Preserves file structure and comments
  • One command to generate template

Usage:

Env.GenerateExample('.env', '.env.example');

Input (.env):

# Database config
DATABASE_URL=postgres://localhost/mydb
PORT=3000

Output (.env.example):

# Database config
DATABASE_URL=
PORT=

Examples

Two new comprehensive examples added as Lazarus projects:

  1. examples/interactive-setup/ - Interactive setup wizard using GetOrPrompt() and Save()

    • Includes .lpi project file and comprehensive README
  2. examples/environment-aware/ - Multi-environment loading with LoadForEnvironment()

    • Includes .lpi project file and comprehensive README

⚠️ Important Security Note for Examples

The example programs create files with NO actual secrets - only demonstration values like DEBUG=true or PORT=3000. They are meant to show the loading pattern, not production security practices.

Real-world security best practices:

  1. NEVER commit files with actual secrets to Git, even if named .env.production
  2. Use .env.example files (empty values) for version control
  3. Add .env* to .gitignore (except .env.example)
  4. Store real secrets in:
    • Environment variables (set by hosting platform: Heroku, AWS, Azure, etc.)
    • Secret management tools (AWS Secrets Manager, HashiCorp Vault, etc.)
    • Local .env files (NOT committed to Git)

Testing

  • ✅ All 96 existing tests pass
  • ✅ Compiles cleanly with FPC 3.2.2+
  • ✅ No breaking changes to existing API
  • ✅ Zero new dependencies

Documentation Updates

  • ✅ README.md updated with new features
  • ✅ CHANGELOG.md updated
  • ✅ Version number bumped to 1.1.0
  • ✅ Code comments added for all new methods
  • ✅ Example programs created

Migration Guide

From v1.0.0 to v1.1.0: No breaking changes! All existing code continues to work.

Simply update your library file and start using the new features:

// Old way still works
Env := TDotEnv.Create;
Env.Load('.env');

// New way - more convenient
Env := TDotEnv.Create;
Env.LoadForEnvironment('production');

Future Compatibility

All new features are designed to be:

  • ✅ Simple and intuitive
  • ✅ Following established patterns
  • ✅ Easy to understand
  • ✅ Well-documented
  • ✅ Tested and reliable

Developer Experience

Cognitive load: Minimal - all features use familiar patterns from other ecosystems

Learning curve: Near zero for developers familiar with Node.js, Python, Ruby, or similar environments

What's Next?

Version 1.1.0 focuses on practical, commonly-needed features.

Future versions may include:

  • Schema validation with type checking
  • File watching and auto-reload
  • Encryption support for sensitive values
  • Export to other formats (JSON, XML, INI)

Thank you for using dotenv-fp! 🎉

For issues or suggestions, please visit: https://github.com/ikelaiah/dotenv-fp

🌿 dotenv-fp – Initial Release

Choose a tag to compare

@ikelaiah ikelaiah released this 11 Dec 19:28

A feature-rich dotenv library for Free Pascal 3.2.2+

We're excited to announce the first stable release of dotenv-fp, a powerful and easy-to-use library for loading environment variables from .env files in Free Pascal applications!

🌟 Highlights

  • Zero Dependencies → Uses only standard FPC units
  • Zero Memory Leaks → Advanced records mean no manual Free calls
  • Type-Safe → Built-in type conversion with GetInt(), GetBool(), GetFloat(), GetArray()
  • Production Ready → 96 comprehensive tests, all passing
  • Cross-Platform → Works on Windows, Linux, and macOS

✨ Features

Core Functionality

  • 📁 Load environment variables from .env files
  • 🔗 Variable interpolation with ${VAR} or $VAR syntax
  • 📝 Multi-line value support
  • 🎯 Quoted values (single quotes, double quotes, or unquoted)
  • 💬 Comment support with # (line or inline)
  • 🐚 Shell-compatible export prefix

Advanced Features

  • 🔒 Type-safe getters with automatic conversion
  • ⚡ Default value fallbacks for missing keys
  • ✅ Built-in validation for required variables
  • 📚 Multiple file loading (.env, .env.local, .env.production, etc.)
  • 🏷️ Key prefixing support (e.g., add APP_ prefix to all keys)

📦 Installation

// 1. Copy src/DotEnv.pas to your project
// 2. Add to your uses clause
uses
  DotEnv;

// 3. Load your .env file
var
  Env: TDotEnv;
begin
  Env := TDotEnv.Create('.env');
  WriteLn(Env.Get('DATABASE_URL'));
end;

📚 Documentation

🔧 Requirements

  • Free Pascal 3.2.2 or higher
  • Compatible with Lazarus 4.0+
  • Supports Windows, Linux, and macOS

🙏 Acknowledgments

Inspired by python-dotenv, bringing the convenience of dotenv to the Pascal ecosystem!

📝 License

MIT License - see LICENSE for details


Full Changelog: https://github.com/ikelaiah/dotenv-fp/blob/main/CHANGELOG.md