Scoping
Create scoped views of secrets with prefix stripping.
The scope() method creates a new Secrets object containing only keys that start with a specific prefix, with that prefix removed from the key names.
Basic Usage#
const secrets = await redenv.load();
// Your secrets:
// AWS_ACCESS_KEY=AKIA...
// AWS_SECRET_KEY=wJalr...
// AWS_REGION=us-east-1
// DATABASE_URL=postgres://...
const aws = secrets.scope("AWS_");
// { ACCESS_KEY: "AKIA...", SECRET_KEY: "wJalr...", REGION: "us-east-1" }
console.log(aws.ACCESS_KEY); // "AKIA..."
console.log(aws.REGION); // "us-east-1"Why Scope?#
Scoping is useful for:
- Modular Configuration - Pass only relevant secrets to modules
- Clean Interfaces - Avoid prefix repetition in code
- Library Integration - Match expected configuration shapes
Without Scoping#
const s3Client = new S3Client({
region: secrets.AWS_REGION,
credentials: {
accessKeyId: secrets.AWS_ACCESS_KEY,
secretAccessKey: secrets.AWS_SECRET_KEY,
},
});With Scoping#
const aws = secrets.scope("AWS_");
const s3Client = new S3Client({
region: aws.REGION,
credentials: {
accessKeyId: aws.ACCESS_KEY,
secretAccessKey: aws.SECRET_KEY,
},
});Practical Examples#
AWS SDK Configuration#
import { S3Client } from "@aws-sdk/client-s3";
const secrets = await redenv.load();
const aws = secrets.scope("AWS_");
const s3 = new S3Client({
region: aws.REGION,
credentials: {
accessKeyId: aws.ACCESS_KEY,
secretAccessKey: aws.SECRET_KEY,
},
});Database Configuration#
const secrets = await redenv.load();
// Secrets: DB_HOST, DB_PORT, DB_USER, DB_PASSWORD, DB_NAME
const db = secrets.scope("DB_");
const connection = await createConnection({
host: db.HOST,
port: db.get("PORT", 5432).toInt(),
user: db.USER,
password: db.PASSWORD,
database: db.NAME,
});Multi-Service Configuration#
const secrets = await redenv.load();
// Stripe configuration
const stripe = secrets.scope("STRIPE_");
const stripeClient = new Stripe(stripe.SECRET_KEY);
// SendGrid configuration
const sendgrid = secrets.scope("SENDGRID_");
sgMail.setApiKey(sendgrid.API_KEY);
// Twilio configuration
const twilio = secrets.scope("TWILIO_");
const twilioClient = new Twilio(twilio.SID, twilio.AUTH_TOKEN);Chaining with Other Methods#
Scoped secrets retain all Secrets capabilities:
const secrets = await redenv.load();
const aws = secrets.scope("AWS_");
// Type casting works
const timeout = aws.get("TIMEOUT", 5000).toInt();
// Validation works
aws.require("ACCESS_KEY", "SECRET_KEY");
// toObject works
console.log(aws.toObject());
// { ACCESS_KEY: "...", SECRET_KEY: "...", REGION: "..." }Nested Scoping#
You can scope multiple times:
const secrets = await redenv.load();
// Secrets:
// AWS_S3_BUCKET=my-bucket
// AWS_S3_REGION=us-east-1
// AWS_SQS_QUEUE=my-queue
const aws = secrets.scope("AWS_");
const s3 = aws.scope("S3_");
console.log(s3.BUCKET); // "my-bucket"
console.log(s3.REGION); // "us-east-1"With Validation#
Validate before scoping to ensure all required secrets exist:
const secrets = await redenv.load();
// Validate full paths first
secrets.require("AWS_ACCESS_KEY", "AWS_SECRET_KEY", "AWS_REGION");
// Then scope for cleaner access
const aws = secrets.scope("AWS_");Or validate within the scoped context:
const aws = secrets.scope("AWS_");
aws.require("ACCESS_KEY", "SECRET_KEY", "REGION");