react-env-secrets
Version:
A zero-config React hook for environment variables - drop-in replacement for process.env
108 lines (104 loc) • 4.07 kB
JavaScript
;
var react = require('react');
// Cache to avoid re-reading env vars on every hook call
let envCache = null;
let isLoading = false;
// Get all environment variables with smart prefix detection
function getAllEnvVars(customPrefix) {
if (typeof window === 'undefined') {
// Server-side: return all process.env
return process.env;
}
// Client-side: only return prefixed vars that are safe for frontend
const envVars = {};
const prefixes = customPrefix ? [customPrefix] : ['REACT_APP_', 'NEXT_PUBLIC_', 'VITE_', 'PUBLIC_'];
// Get all environment variables from the bundled process.env
Object.keys(process.env).forEach(key => {
const value = process.env[key];
if (value !== undefined) {
// Check if key starts with any allowed prefix
const hasValidPrefix = prefixes.some(prefix => key.startsWith(prefix));
if (hasValidPrefix) {
// Remove prefix for cleaner usage
const cleanKey = prefixes.reduce((k, prefix) => k.startsWith(prefix) ? k.slice(prefix.length) : k, key);
envVars[cleanKey] = value;
// Also keep the original prefixed version
envVars[key] = value;
}
}
});
return envVars;
}
// Main hook - simple drop-in replacement
function useEnv(options = {}) {
const { prefix, required = [], fallbacks = {} } = options;
const [envVars, setEnvVars] = react.useState(() => {
// Initialize with cached vars or get fresh ones
if (envCache)
return envCache;
return getAllEnvVars(prefix);
});
const [error, setError] = react.useState(null);
react.useEffect(() => {
if (!envCache && !isLoading) {
isLoading = true;
try {
const vars = getAllEnvVars(prefix);
// Apply fallbacks
const varsWithFallbacks = { ...vars };
Object.keys(fallbacks).forEach(key => {
if (varsWithFallbacks[key] === undefined) {
varsWithFallbacks[key] = fallbacks[key];
}
});
// Check required variables
const missingVars = required.filter(key => varsWithFallbacks[key] === undefined || varsWithFallbacks[key] === '');
if (missingVars.length > 0) {
const prefixHint = prefix || 'REACT_APP_/NEXT_PUBLIC_/VITE_';
setError(`Missing required environment variables: ${missingVars.join(', ')}. ` +
`Make sure they are prefixed with ${prefixHint} in your .env file.`);
}
else {
setError(null);
}
envCache = varsWithFallbacks;
setEnvVars(varsWithFallbacks);
}
catch (err) {
setError(`Failed to load environment variables: ${err}`);
}
finally {
isLoading = false;
}
}
}, [prefix, required, fallbacks]);
// Log error in development
if (error && process.env.NODE_ENV === 'development') {
console.error('useEnv Error:', error);
}
return envVars;
}
// Utility hook for single variable (even simpler usage)
function useEnvVar(key, fallback) {
var _a;
const envVars = useEnv();
return (_a = envVars[key]) !== null && _a !== void 0 ? _a : fallback;
}
// Helper to clear cache (useful for testing or hot reloading)
function clearEnvCache() {
envCache = null;
}
// Development helper to list all available env vars
function listEnvVars() {
if (process.env.NODE_ENV === 'development') {
const vars = getAllEnvVars();
console.log('Available environment variables:', Object.keys(vars));
return Object.keys(vars);
}
return [];
}
exports.clearEnvCache = clearEnvCache;
exports.listEnvVars = listEnvVars;
exports.useEnv = useEnv;
exports.useEnvVar = useEnvVar;
//# sourceMappingURL=index.js.map