54 lines · 1.8 KB
// Whoever runs a deployment owns its abuse-vs-friction tradeoff, so these are
// env vars rather than hardcoded. Defaults suit a deployment other people can
// reach; someone running it just for themselves can raise every
// RATE_LIMIT_*_MAX, or set it to 0 to drop that command's limit entirely.
export interface RateLimitConfig {
  windowSeconds: number;
  maxCount: number;
}

export interface CommandConfig {
  maxActiveAddresses: number;
  addressTtlSeconds: number;
  rateLimits: Record<string, RateLimitConfig | null>;
}

function parseIntEnv(value: string | undefined, fallback: number): number {
  if (!value) {
    return fallback;
  }
  const parsed = Number.parseInt(value, 10);
  return Number.isFinite(parsed) && parsed >= 0 ? parsed : fallback;
}

function rateLimitFromEnv(
  env: Record<string, string | undefined>,
  prefix: string,
  defaultWindowSeconds: number,
  defaultMaxCount: number
): RateLimitConfig | null {
  const maxCount = parseIntEnv(env[`${prefix}_MAX`], defaultMaxCount);
  if (maxCount === 0) {
    return null; // explicitly disabled for this command
  }
  return {
    windowSeconds: parseIntEnv(env[`${prefix}_WINDOW_SECONDS`], defaultWindowSeconds),
    maxCount,
  };
}

export function buildCommandConfig(env: Record<string, string | undefined>): CommandConfig {