Last active
August 22, 2025 15:09
-
-
Save colelawrence/1cd20a89ddef96d97985ac08a20c54a0 to your computer and use it in GitHub Desktop.
Environment secret value / Redacted-like container
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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