Skip to content

Commit fa3718c

Browse files
authored
Merge pull request BrasilAPI#55 from filipedeschamps/custom-error
feat(error): change public error interface to use Custom Error
2 parents c7aeb90 + baa78db commit fa3718c

File tree

9 files changed

+452
-322
lines changed

9 files changed

+452
-322
lines changed

README.md

Lines changed: 35 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -20,15 +20,15 @@
2020
</p>
2121

2222
<p align="center">
23-
Busca por CEP integrado diretamente aos serviços dos Correios e ViaCEP
23+
Busca por CEP integrado diretamente aos serviços dos Correios e ViaCEP (Node.js e Browser)
2424
</p>
2525

2626
## Features
2727

2828
* Sempre atualizado em tempo-real por se conectar diretamente aos serviços dos Correios ou ViaCEP
2929
* Possui alta disponibilidade por usar serviços como fallback
30-
* Sempre retorna a resposta mais rápida por usar concorrência
31-
* Sem limites de uso (rate limit) conhecidos
30+
* Sempre retorna a resposta mais rápida por fazer as consultas de forma concorrente
31+
* Sem limites de uso (rate limits) conhecidos
3232
* Interface de Promise extremamente simples
3333
* Suporte ao Node.js `0.10.x`, `0.12.x`, `4.x`, `5.x`, `6.x` e `@stable`
3434
* 100% de code coverage com testes unitários e E2E
@@ -50,10 +50,10 @@ $ npm install --save cep-promise
5050
Por ser multifornecedor, a biblioteca irá resolver a Promise com o fornecedor que mais rápido lhe responder.
5151

5252
``` js
53-
import cep from 'cep-promise';
53+
import cep from 'cep-promise'
5454

5555
cep('05010000')
56-
.then(console.log);
56+
.then(console.log)
5757

5858
// {
5959
// "zipcode": "05010000",
@@ -70,11 +70,11 @@ cep('05010000')
7070
Em muitos sistemas o CEP é utilizado erroneamente como um Inteiro (e com isto cortanto todos os zeros à esquerda). Caso este seja o seu caso, não há problema, pois a biblioteca irá preencher os caracteres faltantes na String, por exemplo:
7171

7272
``` js
73-
import cep from 'cep-promise';
73+
import cep from 'cep-promise'
7474

7575
// enviando sem ter um zero à esquerda do CEP "05010000"
7676
cep(5010000)
77-
.then(console.log);
77+
.then(console.log)
7878

7979
// {
8080
// "zipcode": "05010000",
@@ -87,45 +87,46 @@ cep(5010000)
8787

8888
### Quando o CEP não é encontrado
8989

90-
Por ser multifornecedor, a biblioteca irá rejeitar a Promise apenas quando tiver a resposta negativa de todos os fornecedores.
90+
Neste caso será retornado um `"service_error"` e por ser multifornecedor, a biblioteca irá rejeitar a Promise apenas quando tiver a resposta negativa de todos os fornecedores.
9191

9292
``` js
93-
import cep from 'cep-promise';
93+
import cep from 'cep-promise'
9494

9595
cep('99999999')
96-
.catch(console.log);
97-
98-
// [
99-
// {
100-
// "type": "range_error",
101-
// "message": "CEP não encontrado na base dos Correios",
102-
// "service": 'correios'
103-
// },
104-
// {
105-
// "type": "range_error",
106-
// "message": "CEP inválido",
107-
// "service": "viacep"
108-
// }
109-
// ]
96+
.catch(console.log)
97+
98+
// {
99+
// message: 'Todos os serviços de CEP retornaram erro.',
100+
// type: 'service_error',
101+
// errors: [{
102+
// message: 'CEP NAO ENCONTRADO',
103+
// service: 'correios'
104+
// }, {
105+
// message: 'CEP não encontrado na base do ViaCEP.',
106+
// service: 'viacep'
107+
// }]
108+
// }
109+
110110
```
111111

112112
### Quando o CEP possui um formato inválido
113113

114-
Neste caso a biblioteca irá rejeitar imediatamente a Promise, sem chegar a consultar nenhum fornecedor.
114+
Neste caso será retornado um `"validation_error"` e a biblioteca irá rejeitar imediatamente a Promise, sem chegar a consultar nenhum fornecedor.
115115

116116
``` js
117-
import cep from 'cep-promise';
117+
import cep from 'cep-promise'
118118

119119
cep('123456789123456789')
120-
.catch(console.log);
121-
122-
// [
123-
// {
124-
// "type": "type_error",
125-
// "message": "CEP deve conter exatamente 8 caracteres",
126-
// "service": undefined
127-
// }
128-
// ]
120+
.catch(console.log)
121+
122+
// {
123+
// message: 'CEP deve conter exatamente 8 caracteres.',
124+
// type: 'validation_error',
125+
// errors: [{
126+
// message: 'CEP informado possui mais do que 8 caracteres.',
127+
// service: 'cep_validation'
128+
// }]
129+
// }
129130
```
130131

131132
## Contribuidores

package.json

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@
3838
"browserify": "13.1.0",
3939
"chai": "3.5.0",
4040
"chai-as-promised": "5.3.0",
41+
"chai-subset": "1.3.0",
4142
"mocha": "3.0.1",
4243
"nock": "8.0.0",
4344
"standard": "7.1.2",
@@ -52,7 +53,11 @@
5253
]
5354
},
5455
"dependencies": {
56+
"babel-cli": "6.16.0",
57+
"babel-core": "6.17.0",
58+
"babel-preset-es2015": "6.16.0",
5559
"bluebird": "3.4.6",
60+
"chai-as-promised": "6.0.0",
5661
"isomorphic-fetch": "2.2.1",
5762
"lodash.get": "4.4.2",
5863
"xml2js": "0.4.16"

src/cep-promise.js

Lines changed: 45 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,9 @@
11
'use strict'
22

3-
import getCorreios from './services/correios.js'
4-
import getViaCep from './services/viacep.js'
3+
import fetchCorreios from './services/correios.js'
4+
import fetchViaCep from './services/viacep.js'
55
import Promise from 'bluebird'
6+
import CepPromiseError from './errors/cep-promise.js'
67

78
const CEP_SIZE = 8
89

@@ -13,14 +14,10 @@ export default function (cepRawValue) {
1314
.then(removeSpecialCharacters)
1415
.then(validateInputLength)
1516
.then(leftPadWithZeros)
16-
.then(getCep)
17-
.then(finish)
18-
.catch(Promise.AggregateError, (err) => {
19-
return reject(err.map((error) => {
20-
return errorHandler(error)
21-
}))
22-
})
23-
.catch((err) => reject([errorHandler(err)]))
17+
.then(fetchCepFromServices)
18+
.then(resolvePromise)
19+
.catch(Promise.AggregateError, handleServicesError)
20+
.catch(rejectWithCepPromiseError)
2421

2522
function validateInputType (cepRawValue) {
2623
let cepTypeOf = typeof cepRawValue
@@ -29,7 +26,14 @@ export default function (cepRawValue) {
2926
return cepRawValue
3027
}
3128

32-
throw new TypeError('Você deve chamar o construtor utilizando uma String ou Number')
29+
throw new CepPromiseError({
30+
message: 'Erro ao inicializar a instância do CepPromise.',
31+
type: 'validation_error',
32+
errors: [{
33+
message: 'Você deve chamar o construtor utilizando uma String ou Number.',
34+
service: 'cep_validation'
35+
}]
36+
})
3337
}
3438

3539
function removeSpecialCharacters (cepRawValue) {
@@ -44,48 +48,50 @@ export default function (cepRawValue) {
4448
if (cepWithLeftPad.length <= CEP_SIZE) {
4549
return cepWithLeftPad
4650
}
47-
throw new TypeError('CEP deve conter exatamente 8 caracteres')
51+
52+
throw new CepPromiseError({
53+
message: 'CEP deve conter exatamente 8 caracteres.',
54+
type: 'validation_error',
55+
errors: [{
56+
message: 'CEP informado possui mais do que 8 caracteres.',
57+
service: 'cep_validation'
58+
}]
59+
})
4860
}
4961

50-
function getCep (cepWithLeftPad) {
62+
function fetchCepFromServices (cepWithLeftPad) {
5163
return Promise.any([
52-
getCorreios(cepWithLeftPad),
53-
getViaCep(cepWithLeftPad)
64+
fetchCorreios(cepWithLeftPad),
65+
fetchViaCep(cepWithLeftPad)
5466
])
55-
.catch(Promise.AggregateError, (err) => {
56-
throw err
57-
})
5867
}
5968

60-
function finish (addressObject) {
69+
function resolvePromise (addressObject) {
6170
resolve(addressObject)
6271
}
6372

64-
function errorHandler (error) {
65-
error.service = error.service || 'cep-promise'
66-
67-
if (error instanceof TypeError) {
73+
function handleServicesError (aggregatedErrors) {
74+
const errors = aggregatedErrors.map((error) => {
6875
return {
69-
type: 'type_error',
7076
message: error.message,
7177
service: error.service
7278
}
73-
}
79+
})
7480

75-
if (error instanceof RangeError) {
76-
return {
77-
type: 'range_error',
78-
message: error.message,
79-
service: error.service
80-
}
81-
}
82-
if (error instanceof Error) {
83-
return {
84-
type: 'error',
85-
message: error.message,
86-
service: error.service
87-
}
88-
}
81+
throw new CepPromiseError({
82+
message: 'Todos os serviços de CEP retornaram erro.',
83+
type: 'service_error',
84+
errors: errors
85+
})
8986
}
87+
88+
function rejectWithCepPromiseError (error) {
89+
reject(new CepPromiseError({
90+
message: error.message,
91+
type: error.type,
92+
errors: error.errors
93+
}))
94+
}
95+
9096
})
9197
}

src/errors/cep-promise.js

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
function CepPromiseError (options) {
2+
options = options || {}
3+
this.name = 'CepPromiseError'
4+
this.message = options.message
5+
this.type = options.type
6+
this.errors = options.errors
7+
}
8+
9+
CepPromiseError.prototype = Object.create(Error.prototype)
10+
CepPromiseError.prototype.constructor = CepPromiseError
11+
12+
export default CepPromiseError

src/errors/service.js

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
function ServiceError (options) {
2+
options = options || {}
3+
this.name = 'ServiceError'
4+
this.message = options.message
5+
this.service = options.service
6+
}
7+
8+
ServiceError.prototype = Object.create(Error.prototype)
9+
ServiceError.prototype.constructor = Error
10+
11+
export default ServiceError
12+

0 commit comments

Comments
 (0)