class AnyCable::Config

AnyCable configuration.

def broadcast_key!

def broadcast_key!
  if http_broadcast_secret && !broadcast_key
    self.broadcast_key ||= http_broadcast_secret
    warn "DEPRECATION WARNING: `http_broadcast_secret` is deprecated, use `broadcast_key` instead"
  end
  return broadcast_key if broadcast_key
  return unless secret
  self.broadcast_key = infer_from_application_secret(BROADCAST_SECRET_PHRASE)
end

def detect_presets

def detect_presets
  [].tap do
    _1 << "fly" if ENV.key?("FLY_APP_NAME") && ENV.key?("FLY_ALLOC_ID") && ENV.key?("FLY_REGION")
  end
end

def http_health_port_provided?

def http_health_port_provided?
  !http_health_port.nil? && http_health_port != ""
end

def http_rpc_secret!

def http_rpc_secret!
  return http_rpc_secret if http_rpc_secret
  return unless secret
  self.http_rpc_secret = infer_from_application_secret(HTTP_RPC_SECRET_PHRASE)
end

def infer_from_application_secret(phrase)

def infer_from_application_secret(phrase)
  app_secret = secret
  return unless app_secret
  require "openssl"
  OpenSSL::HMAC.hexdigest("SHA256", app_secret, phrase)
end

def jwt_secret

def jwt_secret
  super || secret
end

def load(*_args)

def load(*_args)
  super.tap { load_presets }
end

def load_fly_presets

def load_fly_presets
  write_preset(:rpc_host, "0.0.0.0:50051", preset: "fly")
  ws_app_name = ENV["ANYCABLE_FLY_WS_APP_NAME"]
  return unless ws_app_name
  region = ENV.fetch("FLY_REGION")
  write_preset(:http_broadcast_url, "http://#{region}.#{ws_app_name}.internal:8090/_broadcast", preset: "fly")
  write_preset(:nats_servers, "nats://#{region}.#{ws_app_name}.internal:4222", preset: "fly")
end

def load_presets

def load_presets
  if presets.nil? || presets.empty?
    self.presets = detect_presets
    __trace__&.record_value(presets, :presets, type: :env)
  end
  return if presets.empty?
  presets.each { send(:"load_#{_1}_presets") if respond_to?(:"load_#{_1}_presets", true) }
end

def log_level

def log_level
  debug? ? "debug" : super
end

def parse_sentinel(sentinel)

def parse_sentinel(sentinel)
  return sentinel.to_hash.transform_keys(&:to_sym) if sentinel.respond_to?(:to_hash)
  uri = URI.parse("redis://#{sentinel}")
  {host: uri.host, port: uri.port}.tap do |opts|
    opts[:password] = uri.password if uri.password
  end
end

def streams_secret

def streams_secret
  super || secret
end

def to_http_health_params

Build HTTP health server parameters
def to_http_health_params
  {
    port: http_health_port,
    path: http_health_path
  }
end

def to_nats_params

Build options for NATS.connect
def to_nats_params
  {
    servers: Array(nats_servers),
    dont_randomize_servers: nats_dont_randomize_servers
  }.merge(nats_options)
end

def to_redis_params

Build Redis parameters
def to_redis_params
  # @type var base_params: { url: String, sentinels: Array[untyped]?, ssl_params: Hash[Symbol, untyped]? }
  base_params = {url: redis_url}
  base_params.tap do |params|
    sentinels = redis_sentinels
    next if sentinels.nil? || sentinels.empty?
    sentinels = Array(sentinels) unless sentinels.is_a?(Array)
    next if sentinels.empty?
    params[:sentinels] = sentinels.map { |sentinel| parse_sentinel(sentinel) }
  end.tap do |params|
    next unless redis_url.match?(/rediss:\/\//)
    if !!redis_tls_client_cert_path ^ !!redis_tls_client_key_path
      raise_validation_error "Both Redis TLS client certificate and private key must be specified (or none of them)"
    end
    if !redis_tls_verify?
      params[:ssl_params] = {verify_mode: OpenSSL::SSL::VERIFY_NONE}
    else
      cert_path, key_path = redis_tls_client_cert_path, redis_tls_client_key_path
      if cert_path && key_path
        params[:ssl_params] = {
          cert: OpenSSL::X509::Certificate.new(File.read(cert_path)),
          key: OpenSSL::PKey.read(File.read(key_path))
        }
      end
    end
  end
end

def usage(txt)

Add usage txt for CLI
def usage(txt)
  usages << txt
end

def usages

def usages
  @usages ||= []
end

def write_preset(key, value, preset:)

def write_preset(key, value, preset:)
  # do not override explicitly provided values
  return unless __trace__&.dig(key.to_s)&.source&.dig(:type) == :defaults
  write_config_attr(key, value)
  __trace__&.record_value(value, key, type: :preset, preset: preset)
end