Class: Nfe::Configuration

Inherits:
Object
  • Object
show all
Defined in:
lib/nfe/configuration.rb,
sig/nfe/configuration.rbs

Overview

Central configuration for the SDK and the single source of truth for the multi-base-URL host map. No resource hard-codes a URL: resources declare an api_family and obtain their host via #base_url_for.

Two-key model

The SDK uses two API keys. The "data" families (#api_key_for maps :addresses, :legal_entity, :natural_person and :nfe_query to it) use data_api_key when present, falling back to api_key. Every other family uses api_key. Either key may be supplied explicitly or via the NFE_API_KEY / NFE_DATA_API_KEY environment variables (explicit wins).

Environment (reserved for future use)

environment: (+:production+ / :development) is currently a reserved, no-op parameter: it is validated but does NOT change endpoints, keys, or behavior. Production vs. test (homologação) is determined by the account configuration at https://app.nfe.io (server-side) — not by the SDK or the API key — and there is no "sandbox URL". Full environment: support is planned for a future release.

TLS trust

ca_file (and optionally ca_path) is the ONLY override of the TLS trust store and can only ADD/replace a CA bundle used to verify the peer. There is deliberately NO public API to disable peer verification (no VERIFY_NONE, no insecure_ssl). The upstream insecureSsl attribute is a server-side property of a webhook delivery target, not the SDK's outbound TLS config.

Constant Summary collapse

HOSTS =

Host per NFE.io product family, keyed by the canonical (hyphenated) family symbol. The /v1 for the :main family is supplied by each resource's api_version, not baked into the host. The :addresses family is the documented exception where /v2 is part of the host.

Returns:

  • (Hash[Symbol, String])
{
  main: "https://api.nfe.io",
  addresses: "https://address.api.nfe.io/v2",
  "nfe-query": "https://nfe.api.nfe.io",
  "legal-entity": "https://legalentity.api.nfe.io",
  "natural-person": "https://naturalperson.api.nfe.io",
  cte: "https://api.nfse.io"
}.freeze
FAMILY_ALIASES =

Maps family aliases (the snake_case names resources declare) to a canonical family key in HOSTS. Keys here are already hyphen-normalized.

Returns:

  • (Hash[Symbol, Symbol])
{
  companies: :main,
  "service-invoices": :main,
  "legal-people": :main,
  "natural-people": :main,
  webhooks: :main,
  transportation: :cte,
  "transportation-invoices": :cte,
  "inbound-product": :cte,
  "inbound-product-invoices": :cte,
  "product-invoices": :cte,
  "consumer-invoices": :cte,
  "tax-calculation": :cte,
  "tax-codes": :cte,
  "state-taxes": :cte,
  "product-invoice-query": :"nfe-query",
  "consumer-invoice-query": :"nfe-query"
}.freeze
DATA_FAMILIES =

Canonical families whose key resolves from data_api_key first. Only the four dedicated-host data-lookup families belong here. :cte (api.nfse.io — NF-e/NFC-e/CT-e emission + tax-rules/tax-codes/state-taxes) intentionally uses the main api_key and is NOT a data family: in this SDK emission is a core capability, not a data-lookup. This is a deliberate divergence from the Node SDK (which routes api.nfse.io through the data-key fallback chain) — do not add :cte here without revisiting that contract.

Returns:

  • (Array[Symbol])
%i[addresses legal-entity natural-person nfe-query].freeze
VALID_ENVIRONMENTS =

Accepted environment: values. Reserved for future use — both currently share the same endpoints and key resolution (see the class doc).

Returns:

  • (Array[Symbol])
%i[production development].freeze
DEFAULT_TIMEOUT =

Returns:

  • (Integer)
30
DEFAULT_OPEN_TIMEOUT =

Returns:

  • (Integer)
10
DEFAULT_MAX_RETRIES =

Returns:

  • (Integer)
3

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(api_key: nil, data_api_key: nil, environment: :production, timeout: DEFAULT_TIMEOUT, open_timeout: DEFAULT_OPEN_TIMEOUT, max_retries: DEFAULT_MAX_RETRIES, logger: nil, user_agent_suffix: nil, base_url_overrides: {}, ca_file: nil, ca_path: nil, proxy: nil) ⇒ Configuration

Returns a new instance of Configuration.

Parameters:

  • api_key (String, nil) (defaults to: nil)

    main key; falls back to NFE_API_KEY.

  • data_api_key (String, nil) (defaults to: nil)

    data-services key; falls back to NFE_DATA_API_KEY.

  • environment (Symbol) (defaults to: :production)

    :production (default) or :development. Reserved for future use — validated but currently has no effect on endpoints/keys (prod vs. test is set in the account at app.nfe.io).

  • timeout (Integer) (defaults to: DEFAULT_TIMEOUT)

    read timeout in seconds (must be positive).

  • open_timeout (Integer) (defaults to: DEFAULT_OPEN_TIMEOUT)

    connect timeout in seconds (must be positive).

  • max_retries (Integer) (defaults to: DEFAULT_MAX_RETRIES)

    retry budget (non-negative).

  • logger (Object, nil) (defaults to: nil)

    optional logger.

  • user_agent_suffix (String, nil) (defaults to: nil)

    appended to the SDK User-Agent.

  • base_url_overrides (Hash{Symbol=>String}) (defaults to: {})

    per-family escape hatch.

  • ca_file (String, nil) (defaults to: nil)

    path to a CA bundle to ADD to the trust store.

  • ca_path (String, nil) (defaults to: nil)

    directory of CA certs to ADD to the trust store.

  • proxy (String, URI, nil) (defaults to: nil)

    passed through to Net::HTTP.

Raises:



101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
# File 'lib/nfe/configuration.rb', line 101

def initialize(api_key: nil, data_api_key: nil, environment: :production,
               timeout: DEFAULT_TIMEOUT, open_timeout: DEFAULT_OPEN_TIMEOUT,
               max_retries: DEFAULT_MAX_RETRIES, logger: nil,
               user_agent_suffix: nil, base_url_overrides: {},
               ca_file: nil, ca_path: nil, proxy: nil)
  @api_key = resolve_key(api_key, "NFE_API_KEY")
  @data_api_key = resolve_key(data_api_key, "NFE_DATA_API_KEY")
  @environment = environment
  @timeout = timeout
  @open_timeout = open_timeout
  @max_retries = max_retries
  @logger = logger
  @user_agent_suffix = user_agent_suffix
  @base_url_overrides = base_url_overrides || {}
  @ca_file = ca_file
  @ca_path = ca_path
  @proxy = proxy

  validate!
end

Instance Attribute Details

#api_keyString? (readonly)

Returns the value of attribute api_key.

Returns:

  • (String, nil)


81
82
83
# File 'lib/nfe/configuration.rb', line 81

def api_key
  @api_key
end

#base_url_overridesHash[Symbol, String] (readonly)

Returns the value of attribute base_url_overrides.

Returns:

  • (Hash[Symbol, String])


81
82
83
# File 'lib/nfe/configuration.rb', line 81

def base_url_overrides
  @base_url_overrides
end

#ca_fileString? (readonly)

Returns the value of attribute ca_file.

Returns:

  • (String, nil)


81
82
83
# File 'lib/nfe/configuration.rb', line 81

def ca_file
  @ca_file
end

#ca_pathString? (readonly)

Returns the value of attribute ca_path.

Returns:

  • (String, nil)


81
82
83
# File 'lib/nfe/configuration.rb', line 81

def ca_path
  @ca_path
end

#data_api_keyString? (readonly)

Returns the value of attribute data_api_key.

Returns:

  • (String, nil)


81
82
83
# File 'lib/nfe/configuration.rb', line 81

def data_api_key
  @data_api_key
end

#environmentSymbol (readonly)

Returns the value of attribute environment.

Returns:

  • (Symbol)


81
82
83
# File 'lib/nfe/configuration.rb', line 81

def environment
  @environment
end

#loggerObject (readonly)

Returns the value of attribute logger.

Returns:

  • (Object)


81
82
83
# File 'lib/nfe/configuration.rb', line 81

def logger
  @logger
end

#max_retriesInteger (readonly)

Returns the value of attribute max_retries.

Returns:

  • (Integer)


81
82
83
# File 'lib/nfe/configuration.rb', line 81

def max_retries
  @max_retries
end

#open_timeoutInteger (readonly)

Returns the value of attribute open_timeout.

Returns:

  • (Integer)


81
82
83
# File 'lib/nfe/configuration.rb', line 81

def open_timeout
  @open_timeout
end

#proxyObject (readonly)

Returns the value of attribute proxy.

Returns:

  • (Object)


81
82
83
# File 'lib/nfe/configuration.rb', line 81

def proxy
  @proxy
end

#timeoutInteger (readonly)

Returns the value of attribute timeout.

Returns:

  • (Integer)


81
82
83
# File 'lib/nfe/configuration.rb', line 81

def timeout
  @timeout
end

#user_agent_suffixString? (readonly)

Returns the value of attribute user_agent_suffix.

Returns:

  • (String, nil)


81
82
83
# File 'lib/nfe/configuration.rb', line 81

def user_agent_suffix
  @user_agent_suffix
end

Instance Method Details

#api_key_for(family) ⇒ String

Resolves the API key for a family under the two-key model. Data families prefer data_api_key and fall back to api_key; all other families use api_key.

Parameters:

  • family (Symbol, String)

    family or alias (snake_case accepted).

Returns:

  • (String)

    the resolved key.

Raises:



141
142
143
144
145
146
147
148
149
150
151
152
153
# File 'lib/nfe/configuration.rb', line 141

def api_key_for(family)
  canonical = canonical_family(family)
  key = if DATA_FAMILIES.include?(canonical)
          @data_api_key || @api_key
        else
          @api_key
        end
  return key unless key.nil? || key.empty?

  raise Nfe::ConfigurationError,
        "Nenhuma chave de API configurada para a família \"#{canonical}\". " \
        "Informe api_key (ou data_api_key para famílias de dados)."
end

#base_url_for(family) ⇒ String

Returns the base host for a product family. A per-family override (from base_url_overrides) wins; an unknown family falls back to the :main host as a safe default.

Parameters:

  • family (Symbol, String)

    family or alias (snake_case accepted).

Returns:

  • (String)


128
129
130
131
132
# File 'lib/nfe/configuration.rb', line 128

def base_url_for(family)
  canonical = canonical_family(family)
  override = @base_url_overrides[canonical] || @base_url_overrides[family.to_sym]
  override || HOSTS[canonical] || HOSTS.fetch(:main)
end

#blank?(value) ⇒ Boolean

Parameters:

  • value (Object)

Returns:

  • (Boolean)


197
198
199
# File 'lib/nfe/configuration.rb', line 197

def blank?(value)
  value.nil? || value.to_s.empty?
end

#canonical_family(family) ⇒ Symbol

Normalizes a family/alias into its canonical (hyphenated) family symbol.

Parameters:

  • family (Symbol, String)

Returns:

  • (Symbol)


202
203
204
205
206
207
# File 'lib/nfe/configuration.rb', line 202

def canonical_family(family)
  normalized = family.to_s.tr("_", "-").to_sym
  return normalized if HOSTS.key?(normalized)

  FAMILY_ALIASES.fetch(normalized, normalized)
end

#resolve_key(explicit, env_name) ⇒ String?

Applies the ENV fallback: an explicit, non-empty argument always wins; otherwise the environment variable (when present) is adopted.

Parameters:

  • explicit (String, nil)
  • env_name (String)

Returns:

  • (String, nil)


159
160
161
162
163
164
165
166
# File 'lib/nfe/configuration.rb', line 159

def resolve_key(explicit, env_name)
  return explicit unless explicit.nil? || explicit.to_s.empty?

  env_value = ENV.fetch(env_name, nil)
  return env_value unless env_value.nil? || env_value.empty?

  explicit
end

#validate!void

This method returns an undefined value.



168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
# File 'lib/nfe/configuration.rb', line 168

def validate!
  unless VALID_ENVIRONMENTS.include?(@environment)
    raise Nfe::ConfigurationError,
          "environment inválido: #{@environment.inspect}. " \
          "Use :production ou :development."
  end

  if blank?(@api_key) && blank?(@data_api_key)
    raise Nfe::ConfigurationError,
          "É necessário informar uma api_key (ou data_api_key). " \
          "Defina o argumento ou a variável de ambiente NFE_API_KEY/NFE_DATA_API_KEY."
  end

  validate_positive!(:timeout, @timeout)
  validate_positive!(:open_timeout, @open_timeout)

  return unless !@max_retries.is_a?(Integer) || @max_retries.negative?

  raise Nfe::ConfigurationError,
        "max_retries deve ser um inteiro não negativo, recebido #{@max_retries.inspect}."
end

#validate_positive!(name, value) ⇒ void

This method returns an undefined value.

Parameters:

  • name (Symbol)
  • value (Object)

Raises:



190
191
192
193
194
195
# File 'lib/nfe/configuration.rb', line 190

def validate_positive!(name, value)
  return if value.is_a?(Numeric) && value.positive?

  raise Nfe::ConfigurationError,
        "#{name} deve ser um número positivo, recebido #{value.inspect}."
end