Skip to content

Instantly share code, notes, and snippets.

@colelawrence
Last active August 22, 2025 15:09
Show Gist options
  • Save colelawrence/1cd20a89ddef96d97985ac08a20c54a0 to your computer and use it in GitHub Desktop.
Save colelawrence/1cd20a89ddef96d97985ac08a20c54a0 to your computer and use it in GitHub Desktop.
Environment secret value / Redacted-like container
const secrets = new WeakMap<EnvSecret<unknown>, unknown>();
/**
* A secure wrapper for environment variables that contain sensitive data.
*
* Values are stored privately using WeakMap to prevent accidental exposure
* in logs, serialization, or debugging output.
*
* @template T The type of the secret value
*
* @example
* ```typescript
* // Creating a secret
* const apiKey = EnvSecret.make("API_KEY", "sk-1234567890abcdef");
*
* // Revealing the value when needed
* const actualKey = EnvSecret.reveal(apiKey); // "sk-1234567890abcdef"
*
* // Safe serialization - no sensitive data exposed
* console.log(JSON.stringify(apiKey)); // "EnvSecret(API_KEY)"
* ```
*/
export class EnvSecret<T> {
/** Type-only property for TypeScript inference - not accessible at runtime */
declare Value: T;
/**
* Creates a new EnvSecret instance containing the provided value.
*
* @param name - Human-readable identifier for debugging/logging
* @param value - The sensitive value to store securely
* @returns A new EnvSecret instance
*
* @example
* ```typescript
* const dbPassword = EnvSecret.make("DATABASE_PASSWORD", "super-secret-123");
* const authToken = EnvSecret.make("AUTH_TOKEN", { token: "abc", expires: Date.now() });
* ```
*/
static make<T>(name: string, value: T): EnvSecret<T> {
return new EnvSecret(name, value);
}
/**
* Safely extracts the original value from an EnvSecret instance.
*
* @param secret - The EnvSecret instance to unwrap
* @returns The original value that was stored
*
* @example
* ```typescript
* const secret = EnvSecret.make("API_KEY", "my-secret-key");
* const revealed = EnvSecret.reveal(secret); // "my-secret-key"
*
* // Type-safe with complex types
* const configSecret = EnvSecret.make("CONFIG", { host: "db.example.com", port: 5432 });
* const config = EnvSecret.reveal(configSecret); // { host: string, port: number }
* ```
*/
static reveal<T extends EnvSecret<any>>(secret: T): NoInfer<T["Value"]> {
return secrets.get(secret) as T["Value"];
}
private constructor(
public readonly name: string,
value: T,
) {
secrets.set(this, value);
}
toJSON(): string {
return `EnvSecret(${this.name})`;
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment