Files
CurrenciCombo/orchestrator/src/config/env.ts
defiQUG 4a1f69a8e5
Some checks failed
Deploy to Phoenix / deploy (push) Failing after 5s
phoenix-deploy Deploy failed: Command failed: bash scripts/deployment/phoenix-deploy-currencicombo-from-workspace.sh [currencicombo-phoenix] packing s
deploy: make Phoenix redeploys archive-safe
2026-04-22 20:05:35 -07:00

101 lines
3.8 KiB
TypeScript

import { z } from "zod";
const emptyToUndefined = (value: unknown) => {
if (typeof value !== "string") return value;
const trimmed = value.trim();
return trimmed === "" ? undefined : trimmed;
};
const optionalString = () => z.preprocess(emptyToUndefined, z.string().optional());
const optionalUrl = () => z.preprocess(emptyToUndefined, z.string().url().optional());
/**
* Environment variable validation schema
*/
const envSchema = z.object({
NODE_ENV: z.enum(["development", "production", "test"]).default("development"),
PORT: z.string().transform(Number).pipe(z.number().int().positive()),
DATABASE_URL: optionalUrl(),
API_KEYS: optionalString(),
REDIS_URL: optionalUrl(),
LOG_LEVEL: z.enum(["error", "warn", "info", "debug"]).default("info"),
ALLOWED_IPS: optionalString(),
SESSION_SECRET: z.string().min(32),
JWT_SECRET: z.preprocess(emptyToUndefined, z.string().min(32).optional()),
AZURE_KEY_VAULT_URL: optionalUrl(),
AWS_SECRETS_MANAGER_REGION: optionalString(),
SENTRY_DSN: optionalUrl(),
// Chain-138 + NotaryRegistry wiring (arch §4.5). All optional; when
// absent the notary adapter falls back to its deterministic mock.
CHAIN_138_RPC_URL: optionalUrl(),
CHAIN_138_CHAIN_ID: z.preprocess(emptyToUndefined, z.string().regex(/^\d+$/).optional()),
NOTARY_REGISTRY_ADDRESS: z.preprocess(
emptyToUndefined,
z.string().regex(/^0x[0-9a-fA-F]{40}$/).optional(),
),
ORCHESTRATOR_PRIVATE_KEY: z.preprocess(
emptyToUndefined,
z.string().regex(/^0x[0-9a-fA-F]{64}$/).optional(),
),
});
/**
* Validated environment variables
*/
export const env = envSchema.parse({
NODE_ENV: process.env.NODE_ENV,
PORT: process.env.PORT || "8080",
DATABASE_URL: process.env.DATABASE_URL,
API_KEYS: process.env.API_KEYS || process.env.ORCHESTRATOR_API_KEYS,
REDIS_URL: process.env.REDIS_URL,
LOG_LEVEL: process.env.LOG_LEVEL,
ALLOWED_IPS: process.env.ALLOWED_IPS,
SESSION_SECRET: process.env.SESSION_SECRET || "dev-secret-change-in-production-min-32-chars",
JWT_SECRET: process.env.JWT_SECRET,
AZURE_KEY_VAULT_URL: process.env.AZURE_KEY_VAULT_URL,
AWS_SECRETS_MANAGER_REGION: process.env.AWS_SECRETS_MANAGER_REGION,
SENTRY_DSN: process.env.SENTRY_DSN,
CHAIN_138_RPC_URL: process.env.CHAIN_138_RPC_URL,
CHAIN_138_CHAIN_ID: process.env.CHAIN_138_CHAIN_ID,
NOTARY_REGISTRY_ADDRESS: process.env.NOTARY_REGISTRY_ADDRESS,
ORCHESTRATOR_PRIVATE_KEY: process.env.ORCHESTRATOR_PRIVATE_KEY,
});
/**
* Validate environment on startup
*/
export function validateEnv() {
try {
// Use same defaults as env object
const envWithDefaults = {
NODE_ENV: process.env.NODE_ENV || "development",
PORT: process.env.PORT || "8080",
DATABASE_URL: process.env.DATABASE_URL,
API_KEYS: process.env.API_KEYS || process.env.ORCHESTRATOR_API_KEYS,
REDIS_URL: process.env.REDIS_URL,
LOG_LEVEL: process.env.LOG_LEVEL || "info",
ALLOWED_IPS: process.env.ALLOWED_IPS,
SESSION_SECRET: process.env.SESSION_SECRET || "dev-secret-change-in-production-min-32-chars",
JWT_SECRET: process.env.JWT_SECRET,
AZURE_KEY_VAULT_URL: process.env.AZURE_KEY_VAULT_URL,
AWS_SECRETS_MANAGER_REGION: process.env.AWS_SECRETS_MANAGER_REGION,
SENTRY_DSN: process.env.SENTRY_DSN,
CHAIN_138_RPC_URL: process.env.CHAIN_138_RPC_URL,
CHAIN_138_CHAIN_ID: process.env.CHAIN_138_CHAIN_ID,
NOTARY_REGISTRY_ADDRESS: process.env.NOTARY_REGISTRY_ADDRESS,
ORCHESTRATOR_PRIVATE_KEY: process.env.ORCHESTRATOR_PRIVATE_KEY,
};
envSchema.parse(envWithDefaults);
console.log("✅ Environment variables validated");
} catch (error) {
if (error instanceof z.ZodError) {
console.error("❌ Environment validation failed:");
error.errors.forEach((err) => {
console.error(` - ${err.path.join(".")}: ${err.message}`);
});
process.exit(1);
}
throw error;
}
}