Skip to content

Commit 6d9ba3b

Browse files
refactor(config): unifica addressApiKey e cteApiKey em dataApiKey
Consolida as chaves de API separadas para serviços de consulta (addressApiKey e cteApiKey) em uma única propriedade dataApiKey, simplificando a configuração do SDK e refletindo a arquitetura real da API NFE.io (duas categorias: fiscal e consulta). Motivação: - A API NFE.io utiliza apenas duas categorias de chave: uma para operações fiscais (NFS-e, Companies, etc.) e outra para todos os serviços de consulta (Endereços, CT-e, CNPJ, CPF) - Ter chaves separadas (addressApiKey, cteApiKey) adicionava complexidade desnecessária sem benefício real - A unificação prepara o SDK para futuros serviços de consulta que usarão a mesma chave Alterações em tipos (src/core/types.ts): - NfeConfig: remove addressApiKey e cteApiKey, adiciona dataApiKey - RequiredNfeConfig: idem, mantendo tipagem string | undefined Alterações no client (src/core/client.ts): - Remove resolveAddressApiKey() e resolveCteApiKey() - Adiciona resolveDataApiKey() com cadeia de fallback: config.dataApiKey → config.apiKey → NFE_DATA_API_KEY → NFE_API_KEY - getAddressHttpClient() e getCteHttpClient() usam resolveDataApiKey() - validateAndNormalizeConfig() normaliza dataApiKey ao invés de duas - updateConfig() preserva cache de dataApiKey ao invés de duas - Mensagens de erro atualizadas para referenciar dataApiKey - JSDoc atualizado nos getters addresses e transportationInvoices Alterações em resources: - addresses.ts: JSDoc atualizado para referenciar dataApiKey - transportation-invoices.ts: JSDoc atualizado para referenciar dataApiKey Alterações em testes: - tests/unit/client-multikey.test.ts: reescrito (38 testes) - Testa cadeia de fallback para Addresses e CT-e via dataApiKey - Testa que ambos services resolvem a mesma chave - Testa uso isolado de dataApiKey sem apiKey - Testa que NFE_ADDRESS_API_KEY e NFE_CTE_API_KEY não são mais reconhecidas (breaking change documentada) - tests/integration/addresses.integration.test.ts: atualizado Alterações em documentação: - README.md: config examples, tabela env vars (2 vars ao invés de 3), notas sobre Address API e CT-e - docs/API.md: NfeConfig type, nota do recurso CT-e Alterações em exemplos: - examples/setup.js: template .env.test usa NFE_DATA_API_KEY - examples/address-lookup.js: config e env vars atualizados - examples/transportation-invoices.js: config e env vars atualizados Arquivos gerados (src/generated/): - Timestamps atualizados pela regeneração do openapi-typescript Validação: - TypeScript: zero erros (npx tsc --noEmit) - Testes: 381 passed, 47 skipped (integration) - Build: ESM + CJS + DTS gerados com sucesso BREAKING CHANGE: addressApiKey e cteApiKey foram removidos de NfeConfig. Use dataApiKey para configurar a chave de serviços de consulta. As variáveis de ambiente NFE_ADDRESS_API_KEY e NFE_CTE_API_KEY foram substituídas por NFE_DATA_API_KEY.
1 parent 00aaffc commit 6d9ba3b

19 files changed

Lines changed: 212 additions & 274 deletions

README.md

Lines changed: 7 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -360,7 +360,7 @@ const filtrado = await nfe.addresses.search({
360360
});
361361
```
362362

363-
> **Nota:** A API de Endereços usa um host separado (`address.api.nfe.io`). Você pode configurar uma chave API específica com `addressApiKey`, ou o SDK usará `apiKey` como fallback.
363+
> **Nota:** A API de Endereços usa um host separado (`address.api.nfe.io`). Você pode configurar uma chave API específica com `dataApiKey`, ou o SDK usará `apiKey` como fallback.
364364
365365
#### 🚚 Notas de Transporte - CT-e (`nfe.transportationInvoices`)
366366

@@ -420,7 +420,7 @@ const eventoXml = await nfe.transportationInvoices.downloadEventXml(
420420
);
421421
```
422422

423-
> **Nota:** A API de CT-e usa um host separado (`api.nfse.io`). Você pode configurar uma chave API específica com `cteApiKey`, ou o SDK usará `apiKey` como fallback.
423+
> **Nota:** A API de CT-e usa um host separado (`api.nfse.io`). Você pode configurar uma chave API específica com `dataApiKey`, ou o SDK usará `apiKey` como fallback.
424424
425425
**Pré-requisitos:**
426426
- Empresa deve estar cadastrada com certificado digital A1 válido
@@ -432,16 +432,12 @@ const eventoXml = await nfe.transportationInvoices.downloadEventXml(
432432

433433
```typescript
434434
const nfe = new NfeClient({
435-
// Chave API principal do NFE.io (opcional se usar apenas Addresses com addressApiKey)
435+
// Chave API principal do NFE.io (operações com documentos fiscais)
436436
apiKey: 'sua-chave-api',
437437

438-
// Opcional: Chave API específica para consulta de endereços
438+
// Opcional: Chave API para serviços de consulta (Endereços, CT-e, CNPJ, CPF)
439439
// Se não fornecida, usa apiKey como fallback
440-
addressApiKey: 'sua-chave-address-api',
441-
442-
// Opcional: Chave API específica para consulta de CT-e
443-
// Se não fornecida, usa apiKey como fallback
444-
cteApiKey: 'sua-chave-cte-api',
440+
dataApiKey: 'sua-chave-data-api',
445441

446442
// Opcional: Ambiente (padrão: 'production')
447443
environment: 'production', // ou 'sandbox'
@@ -469,14 +465,12 @@ O SDK suporta as seguintes variáveis de ambiente:
469465
| Variável | Descrição |
470466
|----------|-----------|
471467
| `NFE_API_KEY` | Chave API principal (fallback para `apiKey`) |
472-
| `NFE_ADDRESS_API_KEY` | Chave API para endereços (fallback para `addressApiKey`) |
473-
| `NFE_CTE_API_KEY` | Chave API para CT-e (fallback para `cteApiKey`) |
468+
| `NFE_DATA_API_KEY` | Chave API para serviços de consulta (fallback para `dataApiKey`) |
474469

475470
```bash
476471
# Configurar via ambiente
477472
export NFE_API_KEY="sua-chave-api"
478-
export NFE_ADDRESS_API_KEY="sua-chave-address"
479-
export NFE_CTE_API_KEY="sua-chave-cte"
473+
export NFE_DATA_API_KEY="sua-chave-data"
480474

481475
# Usar SDK sem passar chaves no código
482476
const nfe = new NfeClient({});

docs/API.md

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1513,7 +1513,7 @@ const events = await nfe.webhooks.getAvailableEvents();
15131513

15141514
Manage CT-e (Conhecimento de Transporte Eletrônico) documents via SEFAZ Distribuição DFe.
15151515

1516-
> **Note:** This resource uses a separate API host (`api.nfse.io`). You can configure a specific API key with `cteApiKey`, or the SDK will use `apiKey` as fallback.
1516+
> **Note:** This resource uses a separate API host (`api.nfse.io`). You can configure a specific API key with `dataApiKey`, or the SDK will use `apiKey` as fallback.
15171517
15181518
**Prerequisites:**
15191519
- Company must be registered with a valid A1 digital certificate
@@ -1651,8 +1651,7 @@ fs.writeFileSync('cte-event.xml', eventXml);
16511651
```typescript
16521652
interface NfeConfig {
16531653
apiKey?: string;
1654-
addressApiKey?: string; // Specific API key for address lookups
1655-
cteApiKey?: string; // Specific API key for CT-e (transportation invoices)
1654+
dataApiKey?: string; // API key for data/query services (Addresses, CT-e, CNPJ, CPF)
16561655
environment?: 'production' | 'development';
16571656
baseUrl?: string;
16581657
timeout?: number;

examples/address-lookup.js

Lines changed: 14 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
* Brazilian addresses (CEP/postal code lookups).
66
*
77
* Prerequisites:
8-
* - Set NFE_ADDRESS_API_KEY or NFE_API_KEY environment variable
8+
* - Set NFE_DATA_API_KEY or NFE_API_KEY environment variable
99
* - Or pass the API key directly in the configuration
1010
*
1111
* Run this example:
@@ -14,12 +14,12 @@
1414

1515
import { NfeClient } from '../dist/index.js';
1616

17-
// Configuration with separate address API key (optional)
17+
// Configuration with separate data API key (optional)
1818
const client = new NfeClient({
19-
// You can use a separate API key for address lookups
20-
// addressApiKey: process.env.NFE_ADDRESS_API_KEY,
19+
// You can use a separate API key for data/query services (addresses, CT-e)
20+
// dataApiKey: process.env.NFE_DATA_API_KEY,
2121

22-
// Or use the main API key (will be used as fallback for addresses)
22+
// Or use the main API key (will be used as fallback for data services)
2323
apiKey: process.env.NFE_API_KEY,
2424

2525
// Environment: 'production' or 'development'
@@ -103,21 +103,21 @@ async function searchWithFilter() {
103103
}
104104

105105
/**
106-
* Example 4: Using only addressApiKey (isolated usage)
106+
* Example 4: Using only dataApiKey (isolated usage)
107107
*/
108108
async function isolatedAddressUsage() {
109-
console.log('\n🔐 Example 4: Isolated Address API Usage');
109+
console.log('\n🔐 Example 4: Isolated Data API Usage');
110110
console.log('='.repeat(50));
111111

112-
// Create a client with ONLY addressApiKey
113-
// This is useful when you only have access to the Address API
114-
const addressOnlyClient = new NfeClient({
115-
addressApiKey: process.env.NFE_ADDRESS_API_KEY || process.env.NFE_API_KEY,
112+
// Create a client with ONLY dataApiKey
113+
// This is useful when you only have access to data/query services
114+
const dataOnlyClient = new NfeClient({
115+
dataApiKey: process.env.NFE_DATA_API_KEY || process.env.NFE_API_KEY,
116116
});
117117

118118
try {
119119
// Addresses work
120-
const result = await addressOnlyClient.addresses.lookupByPostalCode('20040-020');
120+
const result = await dataOnlyClient.addresses.lookupByPostalCode('20040-020');
121121
console.log('Rio de Janeiro CEP lookup succeeded!');
122122
console.log(` ${result.street}, ${result.city?.name}/${result.state}`);
123123
} catch (error) {
@@ -165,9 +165,9 @@ async function main() {
165165
console.log('🏠 NFE.io Address Lookup Examples');
166166
console.log('━'.repeat(50));
167167

168-
if (!process.env.NFE_API_KEY && !process.env.NFE_ADDRESS_API_KEY) {
168+
if (!process.env.NFE_API_KEY && !process.env.NFE_DATA_API_KEY) {
169169
console.error('\n❌ No API key found!');
170-
console.error('Please set NFE_API_KEY or NFE_ADDRESS_API_KEY environment variable.');
170+
console.error('Please set NFE_API_KEY or NFE_DATA_API_KEY environment variable.');
171171
console.error('\nExample:');
172172
console.error(' export NFE_API_KEY="your-api-key"');
173173
console.error(' node examples/address-lookup.js');

examples/setup.js

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -113,10 +113,9 @@ ${companyId ? `NFE_COMPANY_ID=${companyId}` : '# NFE_COMPANY_ID=seu-company-id-a
113113
# Timeout em ms (opcional)
114114
# NFE_TIMEOUT=30000
115115
116-
# Chaves de API específicas (opcional)
117-
# Se não definidas, usa NFE_API_KEY como fallback
118-
# NFE_ADDRESS_API_KEY=sua-chave-address-aqui
119-
# NFE_CTE_API_KEY=sua-chave-cte-aqui
116+
# Chave de API para serviços de consulta (opcional)
117+
# Se não definida, usa NFE_API_KEY como fallback
118+
# NFE_DATA_API_KEY=sua-chave-data-aqui
120119
`;
121120

122121
try {

examples/transportation-invoices.js

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -11,12 +11,12 @@
1111
*
1212
* Configuration:
1313
* Set one of the following environment variables:
14-
* - NFE_CTE_API_KEY - Specific CT-e API key (recommended)
14+
* - NFE_DATA_API_KEY - Data/query API key (recommended)
1515
* - NFE_API_KEY - Main API key (will be used as fallback)
1616
*
1717
* Or configure in code:
1818
* const nfe = new NfeClient({
19-
* cteApiKey: 'your-cte-api-key', // Or use apiKey if you have unified access
19+
* dataApiKey: 'your-data-api-key', // Or use apiKey if you have unified access
2020
* });
2121
*
2222
* Usage:
@@ -34,12 +34,12 @@ import { NfeClient } from 'nfe-io';
3434
// ============================================================================
3535

3636
// Create client - API key fallback chain:
37-
// 1. cteApiKey (config)
37+
// 1. dataApiKey (config)
3838
// 2. apiKey (config)
39-
// 3. NFE_CTE_API_KEY (env)
39+
// 3. NFE_DATA_API_KEY (env)
4040
// 4. NFE_API_KEY (env)
4141
const nfe = new NfeClient({
42-
// cteApiKey: process.env.NFE_CTE_API_KEY, // Uncomment for explicit configuration
42+
// dataApiKey: process.env.NFE_DATA_API_KEY, // Uncomment for explicit configuration
4343
});
4444

4545
// ============================================================================
@@ -277,7 +277,7 @@ async function main() {
277277
} catch (error) {
278278
console.error('\n❌ Error:', error.message);
279279
if (error.name === 'ConfigurationError') {
280-
console.error(' Make sure you have set NFE_CTE_API_KEY or NFE_API_KEY');
280+
console.error(' Make sure you have set NFE_DATA_API_KEY or NFE_API_KEY');
281281
}
282282
if (error.name === 'ValidationError') {
283283
console.error(' Check your input parameters');

src/core/client.ts

Lines changed: 20 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -285,10 +285,10 @@ export class NfeClient {
285285
* - Search by generic term
286286
*
287287
* **Note:** This resource uses a different API host (address.api.nfe.io).
288-
* Configure `addressApiKey` for a separate key, or it will fallback to `apiKey`.
288+
* Configure `dataApiKey` for a separate key, or it will fallback to `apiKey`.
289289
*
290290
* @see {@link AddressesResource}
291-
* @throws {ConfigurationError} If no API key is configured (addressApiKey or apiKey)
291+
* @throws {ConfigurationError} If no API key is configured (dataApiKey or apiKey)
292292
*
293293
* @example
294294
* ```typescript
@@ -318,10 +318,10 @@ export class NfeClient {
318318
* - Webhook must be configured to receive CT-e notifications
319319
*
320320
* **Note:** This resource uses a different API host (api.nfse.io).
321-
* Configure `cteApiKey` for a separate key, or it will fallback to `apiKey`.
321+
* Configure `dataApiKey` for a separate key, or it will fallback to `apiKey`.
322322
*
323323
* @see {@link TransportationInvoicesResource}
324-
* @throws {ConfigurationError} If no API key is configured (cteApiKey or apiKey)
324+
* @throws {ConfigurationError} If no API key is configured (dataApiKey or apiKey)
325325
*
326326
* @example
327327
* ```typescript
@@ -379,11 +379,11 @@ export class NfeClient {
379379
* });
380380
* ```
381381
*
382-
* @example With only address API key
382+
* @example With only data API key
383383
* ```typescript
384-
* // Only use address lookup, no main API access
384+
* // Only use data services (address lookup, CT-e), no main API access
385385
* const nfe = new NfeClient({
386-
* addressApiKey: 'address-api-key'
386+
* dataApiKey: 'data-api-key'
387387
* });
388388
* await nfe.addresses.lookupByPostalCode('01310-100');
389389
* ```
@@ -431,10 +431,10 @@ export class NfeClient {
431431
*/
432432
private getAddressHttpClient(): HttpClient {
433433
if (!this._addressHttp) {
434-
const apiKey = this.resolveAddressApiKey();
434+
const apiKey = this.resolveDataApiKey();
435435
if (!apiKey) {
436436
throw new ConfigurationError(
437-
'API key required for Addresses. Set "addressApiKey" or "apiKey" in config, or NFE_ADDRESS_API_KEY/NFE_API_KEY environment variable.'
437+
'API key required for data services. Set "dataApiKey" or "apiKey" in config, or NFE_DATA_API_KEY/NFE_API_KEY environment variable.'
438438
);
439439
}
440440
const httpConfig = buildHttpConfig(
@@ -459,27 +459,14 @@ export class NfeClient {
459459
}
460460

461461
/**
462-
* Resolve the Address API key using fallback chain
463-
* Order: addressApiKey → apiKey → NFE_ADDRESS_API_KEY → NFE_API_KEY
462+
* Resolve the data API key using fallback chain
463+
* Order: dataApiKey → apiKey → NFE_DATA_API_KEY → NFE_API_KEY
464464
*/
465-
private resolveAddressApiKey(): string | undefined {
465+
private resolveDataApiKey(): string | undefined {
466466
return (
467-
this.config.addressApiKey ||
467+
this.config.dataApiKey ||
468468
this.config.apiKey ||
469-
this.getEnvironmentVariable('NFE_ADDRESS_API_KEY') ||
470-
this.getEnvironmentVariable('NFE_API_KEY')
471-
);
472-
}
473-
474-
/**
475-
* Resolve the CT-e API key using fallback chain
476-
* Order: cteApiKey → apiKey → NFE_CTE_API_KEY → NFE_API_KEY
477-
*/
478-
private resolveCteApiKey(): string | undefined {
479-
return (
480-
this.config.cteApiKey ||
481-
this.config.apiKey ||
482-
this.getEnvironmentVariable('NFE_CTE_API_KEY') ||
469+
this.getEnvironmentVariable('NFE_DATA_API_KEY') ||
483470
this.getEnvironmentVariable('NFE_API_KEY')
484471
);
485472
}
@@ -490,10 +477,10 @@ export class NfeClient {
490477
*/
491478
private getCteHttpClient(): HttpClient {
492479
if (!this._cteHttp) {
493-
const apiKey = this.resolveCteApiKey();
480+
const apiKey = this.resolveDataApiKey();
494481
if (!apiKey) {
495482
throw new ConfigurationError(
496-
'API key required for Transportation Invoices (CT-e). Set "cteApiKey" or "apiKey" in config, or NFE_CTE_API_KEY/NFE_API_KEY environment variable.'
483+
'API key required for data services. Set "dataApiKey" or "apiKey" in config, or NFE_DATA_API_KEY/NFE_API_KEY environment variable.'
497484
);
498485
}
499486
const httpConfig = buildHttpConfig(
@@ -514,8 +501,7 @@ export class NfeClient {
514501
private validateAndNormalizeConfig(config: NfeConfig): RequiredNfeConfig {
515502
// API keys are now optional - validated lazily when resources are accessed
516503
const apiKey = config.apiKey?.trim() || undefined;
517-
const addressApiKey = config.addressApiKey?.trim() || undefined;
518-
const cteApiKey = config.cteApiKey?.trim() || undefined;
504+
const dataApiKey = config.dataApiKey?.trim() || undefined;
519505

520506
// Normalize environment
521507
const environment = config.environment || 'production';
@@ -534,8 +520,7 @@ export class NfeClient {
534520

535521
const normalizedConfig: RequiredNfeConfig = {
536522
apiKey,
537-
addressApiKey,
538-
cteApiKey,
523+
dataApiKey,
539524
environment,
540525
baseUrl: config.baseUrl || this.getDefaultBaseUrl(),
541526
timeout: config.timeout || 30000,
@@ -632,11 +617,8 @@ export class NfeClient {
632617
if (normalizedConfig.apiKey === undefined && this.config.apiKey !== undefined && newConfig.apiKey === undefined) {
633618
normalizedConfig.apiKey = this.config.apiKey;
634619
}
635-
if (normalizedConfig.addressApiKey === undefined && this.config.addressApiKey !== undefined && newConfig.addressApiKey === undefined) {
636-
normalizedConfig.addressApiKey = this.config.addressApiKey;
637-
}
638-
if (normalizedConfig.cteApiKey === undefined && this.config.cteApiKey !== undefined && newConfig.cteApiKey === undefined) {
639-
normalizedConfig.cteApiKey = this.config.cteApiKey;
620+
if (normalizedConfig.dataApiKey === undefined && this.config.dataApiKey !== undefined && newConfig.dataApiKey === undefined) {
621+
normalizedConfig.dataApiKey = this.config.dataApiKey;
640622
}
641623

642624
// Update internal config

src/core/resources/addresses.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -68,7 +68,7 @@ function normalizePostalCode(postalCode: string): string {
6868
* Data is sourced from Correios DNE (Diretório Nacional de Endereços) integrated with IBGE city codes.
6969
*
7070
* **Note:** This resource uses a different API host (address.api.nfe.io) and may require
71-
* a separate API key configured via `addressApiKey` in the client configuration.
71+
* a separate API key configured via `dataApiKey` in the client configuration.
7272
*
7373
* @example Basic postal code lookup
7474
* ```typescript

src/core/resources/transportation-invoices.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -73,7 +73,7 @@ function validateCompanyId(companyId: string): void {
7373
* - Webhook must be configured to receive CT-e notifications
7474
*
7575
* **Note:** This resource uses a different API host (api.nfse.io) and may require
76-
* a separate API key configured via `cteApiKey` in the client configuration.
76+
* a separate API key configured via `dataApiKey` in the client configuration.
7777
* If not set, it falls back to `apiKey`.
7878
*
7979
* @example Enable automatic CT-e search

src/core/types.ts

Lines changed: 5 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -17,10 +17,8 @@
1717
export interface NfeConfig {
1818
/** NFE.io API Key for main resources (companies, invoices, etc.) */
1919
apiKey?: string;
20-
/** NFE.io API Key specifically for Address API (optional, falls back to apiKey) */
21-
addressApiKey?: string;
22-
/** NFE.io API Key specifically for CT-e API (optional, falls back to apiKey) */
23-
cteApiKey?: string;
20+
/** NFE.io API Key for data/query services: Addresses, CT-e, CNPJ, CPF (optional, falls back to apiKey) */
21+
dataApiKey?: string;
2422
/** Environment to use (both use same endpoint, differentiated by API key) */
2523
environment?: 'production' | 'development';
2624
/** Custom base URL (overrides environment) */
@@ -296,12 +294,10 @@ export interface PollOptions {
296294
* API keys remain optional since validation is done lazily when resources are accessed.
297295
*/
298296
export interface RequiredNfeConfig {
299-
/** Main API key (may be undefined if only using address API) */
297+
/** Main API key (may be undefined if only using data services) */
300298
apiKey: string | undefined;
301-
/** Address API key (may be undefined, will fallback to apiKey) */
302-
addressApiKey: string | undefined;
303-
/** CT-e API key (may be undefined, will fallback to apiKey) */
304-
cteApiKey: string | undefined;
299+
/** Data API key for query services: Addresses, CT-e, CNPJ, CPF (may be undefined, will fallback to apiKey) */
300+
dataApiKey: string | undefined;
305301
/** Environment */
306302
environment: 'production' | 'development';
307303
/** Base URL for main API */

src/generated/calculo-impostos-v1.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
* Do not edit this file directly.
55
*
66
* To regenerate: npm run generate
7-
* Last generated: 2026-02-03T01:51:28.320Z
7+
* Last generated: 2026-02-14T00:32:45.806Z
88
* Generator: openapi-typescript
99
*/
1010

0 commit comments

Comments
 (0)