PB-ENV is a powerful, secure replacement for dotenv that supports encryption, image variables, directory imports, and advanced features using .pb
files. Compatible with Node.js, React, and EJS environments.
- AES-256-GCM encryption for sensitive data
- Automatic key management with secure file permissions
- Key rotation support
- Encrypted JSON configurations
- Direct image storage in config files
- Automatic base64 encoding/decoding
- Image caching for performance
- React components for easy image rendering
- Import entire directories with
HANDLERS_DIR=./src/handlers
- Recursive directory traversal
- File content access in templates and components
- Extraction to filesystem
- Type validation (string, number, boolean, JSON, image, directory)
- Variable interpolation with
${VAR_NAME}
- Environment-specific configs
- Configuration inheritance
- Hot reloading with cache invalidation
- Custom hooks for configuration access
- Image components with automatic data URL generation
- Directory file viewers and navigation components
- Configuration debugger component
- Template helpers for easy variable access
- Express.js middleware for automatic setup
- Image data URL generation for templates
- Directory file rendering in views
npm install @zppqr/pb-env
// Load configuration
require('@zppqr/pb-env').config();
// Or with ES modules
import pb from '@zppqr/pb-env';
pb.config();
// Access variables
console.log(process.env.APP_NAME);
console.log(process.env.PORT); // Automatically typed
import React from 'react';
import { usePBConfig, PBImage, PBDirectoryList } from '@zppqr/pb-env';
function App() {
const { config, loading, error } = usePBConfig();
if (loading) return <div>Loading configuration...</div>;
if (error) return <div>Error: {error.message}</div>;
return (
<div>
<h1>{config.APP_NAME}</h1>
<PBImage configKey="LOGO_IMAGE" alt="Logo" />
<PBDirectoryList
configKey="TEMPLATES_DIR"
onFileSelect={(file) => console.log('Selected:', file)}
/>
</div>
);
}
// Express.js setup
import express from 'express';
import { pbEJSMiddleware } from '@zppqr/pb-env';
const app = express();
// Add PB middleware
app.use(pbEJSMiddleware({
path: './config.pb',
environment: process.env.NODE_ENV
}));
app.set('view engine', 'ejs');
<!-- In your EJS template -->
<h1><%= APP_NAME %></h1>
<img src="<%= pb.getImageDataUrl('LOGO_IMAGE') %>" alt="Logo">
<% pb.getDirectoryFiles('TEMPLATES_DIR').forEach(file => { %>
<div><%= file %></div>
<% }) %>
# Metadata
@version 2.0.0
@author "Your Name"
@description "Application configuration"
# Basic variables
APP_NAME="My Application"
APP_VERSION="1.0.0"
# Typed variables
PORT=3000
@type number
@required
DEBUG=true
@type boolean
# Encrypted sensitive data
DATABASE_PASSWORD="secret-password"
@encrypted
@required
API_KEY="sk-1234567890"
@encrypted
# Image variables
LOGO_IMAGE="./assets/logo.png"
@type image
@description "Company logo"
HERO_BANNER="./assets/hero.jpg"
@type image
# Directory imports
HANDLERS_DIR="./src/handlers"
@type directory
@description "API route handlers"
TEMPLATES_DIR="./email-templates"
@type directory
# JSON configuration (can be encrypted)
DATABASE_CONFIG='{
"host": "localhost",
"port": 5432,
"ssl": true
}'
@type json
@encrypted
# Multiline values
PRIVATE_KEY="""
-----BEGIN PRIVATE KEY-----
Your private key content here
Can span multiple lines safely
-----END PRIVATE KEY-----
"""
@encrypted
# Variable interpolation
API_URL="https://api.${APP_NAME}.com"
DATABASE_URL="postgresql://user:${DATABASE_PASSWORD}@localhost/${APP_NAME}"
# Required with defaults
REDIS_URL=""
@required
@default "redis://localhost:6379"
LOG_LEVEL="info"
@default "warn"
# Extend other configs
@extends base.pb, secrets.pb
# Initialize new config
pb init
# Validate configuration
pb validate
# Load specific environment
pb load -e production
# Encrypt a value
pb encrypt "my-secret-value"
# Decrypt a value
pb decrypt "PB_ENCRYPTED:..."
# Use custom config file
pb validate -f custom-config.pb
import {
usePBConfig,
usePBVariable,
usePBImage,
usePBDirectory,
usePBEnvironment
} from '@zppqr/pb-env';
// Load entire configuration
const { config, loading, error, reload } = usePBConfig();
// Get specific variable with type safety
const appName = usePBVariable('APP_NAME', 'Default App');
const port = usePBVariable('PORT', 3000);
// Work with images
const logoData = usePBImage('LOGO_IMAGE');
// Returns: { dataUrl, mimeType, size, hash, buffer }
// Work with directories
const handlersData = usePBDirectory('HANDLERS_DIR');
// Returns: { files, getFile, fileCount }
// Environment switching
const { environment, switchEnvironment } = usePBEnvironment();
import { PBImage, PBFileViewer, PBDirectoryList, PBConfigDebugger } from '@zppqr/pb-env';
// Display images from config
<PBImage
configKey="LOGO_IMAGE"
alt="Company Logo"
className="logo"
fallback={<div>Logo not found</div>}
onLoad={() => console.log('Image loaded')}
/>
// View files from directory imports
<PBFileViewer
configKey="TEMPLATES_DIR"
filePath="welcome.html"
className="code-viewer"
/>
// List directory contents
<PBDirectoryList
configKey="HANDLERS_DIR"
onFileSelect={(file) => setSelectedFile(file)}
className="file-list"
/>
// Debug configuration (development only)
<PBConfigDebugger className="debug-panel" />
import express from 'express';
import { pbEJSMiddleware, PBEJSHelpers } from '@zppqr/pb-env';
const app = express();
// Automatic setup with middleware
app.use(pbEJSMiddleware({
path: './config.pb',
environment: process.env.NODE_ENV,
enableImageCache: true
}));
// Manual setup
PBEJSHelpers.initialize({ path: './config.pb' });
app.locals = PBEJSHelpers.createEJSLocals();
<!-- Basic variable access -->
<h1><%= APP_NAME %></h1>
<p>Version: <%= APP_VERSION %></p>
<!-- Typed variable access -->
<p>Port: <%= pb.getNumber('PORT') %></p>
<p>Debug: <%= pb.getBoolean('DEBUG') %></p>
<!-- Image handling -->
<img src="<%= pb.getImageDataUrl('LOGO_IMAGE') %>" alt="Logo">
<!-- Directory file access -->
<% const handlerFiles = pb.getDirectoryFiles('HANDLERS_DIR'); %>
<ul>
<% handlerFiles.forEach(file => { %>
<li><%= file %></li>
<% }); %>
</ul>
<!-- Render specific file content -->
<pre><%= pb.getDirectoryFile('TEMPLATES_DIR', 'email.html') %></pre>
<!-- JSON configuration -->
<% const dbConfig = pb.getJSON('DATABASE_CONFIG'); %>
<p>Database: <%= dbConfig.host %>:<%= dbConfig.port %></p>
# In .pb file
SECRET_KEY="my-secret"
@encrypted
DATABASE_CONFIG='{"password": "secret"}'
@type json
@encrypted
- Keys are automatically generated on first use
- Stored in
.pb.key
with secure permissions (600) - Never commit
.pb.key
to version control - Use
pb rotate-key
for key rotation
# Development
.env.pb
# Production
.env.production.pb
# Testing
.env.test.pb
- Caching: Configuration parsed once and cached
- Hot Reloading: Automatic cache invalidation on file changes
- Lazy Loading: Images and directories loaded on demand
- Optimized Parsing: Efficient regex-based parsing
- Memory Management: Automatic cleanup of unused resources
- Rename files:
.env
→.env.pb
- Add type annotations:
# Before PORT=3000 # After PORT=3000 @type number
- Encrypt sensitive values:
# Before DATABASE_PASSWORD=secret # After DATABASE_PASSWORD="secret" @encrypted
- Update imports:
// Before require('dotenv').config(); // After require('@zppqr/pb-env').config();
# Run tests
npm test
# Run tests in watch mode
npm run test:watch
# Run with coverage
npm test -- --coverage
- Fork the repository
- Create your feature branch (
git checkout -b feature/amazing-feature
) - Commit your changes (
git commit -m 'Add amazing feature'
) - Push to the branch (
git push origin feature/amazing-feature
) - Open a Pull Request
MIT License - see LICENSE file for details.
- Cloud Sync - Secure cloud synchronization
- VS Code Extension - Syntax highlighting and IntelliSense
- Web UI - Visual configuration management
- Database Integration - Direct database connections
- Audit Logging - Configuration change tracking
- Schema Validation - JSON schema support
- Plugin System - Extensible architecture