├── .babelrc
├── .editorconfig
├── .github
└── workflows
│ └── continuous-integration.yml
├── .gitignore
├── .mocharc.json
├── .nvmrc
├── CONTRIBUTING.md
├── LICENSE
├── README.md
├── bower.json
├── content
└── logo.gif
├── dist
├── cep-promise-browser.js
├── cep-promise-browser.min.js
├── cep-promise.js
└── cep-promise.min.js
├── index.d.ts
├── package-lock.json
├── package.json
├── rollup.config.js
├── src
├── cep-promise.js
├── errors
│ ├── cep-promise.js
│ └── service.js
├── services
│ ├── brasilapi.js
│ ├── correios-alt.js
│ ├── correios.js
│ ├── index.js
│ ├── viacep.js
│ └── widenet.js
└── utils
│ └── promise-any.js
└── test
├── e2e
└── cep-promise.spec.js
└── unit
├── cep-promise-browser.spec.js
├── cep-promise-node.spec.js
├── cep-promise-providers.spec.js
├── cep-promise-timeout.spec.js
└── fixtures
├── brasilapi-cep-05010000-found.json
├── brasilapi-cep-99999999-error.json
├── cep-aberto-05010000-found.json
├── cep-aberto-99999999-error.json
├── correios-alt-cep-05010000-found.json
├── correios-alt-cep-99999999-error.json
├── response-bad-xml.xml
├── response-cep-05010000-found.xml
├── response-cep-invalid-format.xml
├── response-cep-not-found.xml
├── response-unknown-format.xml
├── viacep-cep-05010000-found.json
├── viacep-cep-99999999-error.json
├── widenet-cep-05010000-found.json
└── widenet-cep-99999999-error.json
/.babelrc:
--------------------------------------------------------------------------------
1 | {
2 | "presets": ["@babel/preset-env"],
3 | "plugins": [
4 | [
5 | "@babel/plugin-transform-runtime"
6 | ]
7 | ]
8 | }
9 |
--------------------------------------------------------------------------------
/.editorconfig:
--------------------------------------------------------------------------------
1 | root = true
2 |
3 | [*]
4 | end_of_line = lf
5 | insert_final_newline = true
6 | charset = utf-8
7 | indent_style = space
8 | indent_size = 2
9 | trim_trailing_whitespace = true
10 |
--------------------------------------------------------------------------------
/.github/workflows/continuous-integration.yml:
--------------------------------------------------------------------------------
1 | name: Continuous Integration
2 |
3 | on:
4 | push:
5 | branches:
6 | - master
7 | pull_request:
8 | branches:
9 | - master
10 |
11 | jobs:
12 | build:
13 | runs-on: ubuntu-latest
14 | strategy:
15 | matrix:
16 | node: [ '10', '11', '12', '13', '14' ]
17 | name: Node ${{ matrix.node }} sample
18 | steps:
19 | - uses: actions/checkout@v2
20 | - name: Setup node
21 | uses: actions/setup-node@v2
22 | with:
23 | node-version: ${{ matrix.node }}
24 | - run: npm install
25 | - run: npm test
26 |
27 | - name: Coveralls
28 | uses: coverallsapp/github-action@master
29 | with:
30 | github-token: ${{ secrets.GITHUB_TOKEN }}
31 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | # Logs
2 | logs
3 | *.log
4 |
5 | # Runtime data
6 | pids
7 | *.pid
8 | *.seed
9 |
10 | # Directory for instrumented libs generated by jscoverage/JSCover
11 | lib-cov
12 |
13 | # Coverage directory used by tools like istanbul
14 | coverage
15 |
16 | # Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files)
17 | .grunt
18 |
19 | # node-waf configuration
20 | .lock-wscript
21 |
22 | # Compiled binary addons (http://nodejs.org/api/addons.html)
23 | build/Release
24 |
25 | # Dependency directory
26 | # https://www.npmjs.org/doc/misc/npm-faq.html#should-i-check-my-node_modules-folder-into-git
27 | node_modules
28 |
29 | # MacOS .DS_Store
30 | .DS_Store
31 |
32 | #Allow only web browser to be versioned
33 | dist/*
34 | !dist/cep-promise*.js
35 |
36 | #Intellij Ide
37 | .idea
38 |
39 | #Yarn
40 | yarn.lock
41 |
42 | # Intelij IDE stuff
43 | .idea/
44 |
--------------------------------------------------------------------------------
/.mocharc.json:
--------------------------------------------------------------------------------
1 | {
2 | "timeout": 60000,
3 | "require": "@babel/register"
4 | }
5 |
--------------------------------------------------------------------------------
/.nvmrc:
--------------------------------------------------------------------------------
1 | 5.0
2 |
--------------------------------------------------------------------------------
/CONTRIBUTING.md:
--------------------------------------------------------------------------------
1 | # Como contribuir com o projeto
2 |
3 | - [Instalando o projeto](#instalando-o-projeto)
4 | - [Reportando Issues](#reportando-issues)
5 | - [Submetendo Pull Requests](#submetendo-pull-requests)
6 |
7 | ## Instalando o projeto
8 |
9 | Para abrir um pull-request, primeiramente crie um fork do projeto para a sua conta, então clone o projeto em sua maquina:
10 |
11 | `git clone git@github.com:seu-usuario/cep-promise.git`
12 |
13 | Em seguida baixe os modulos necessários com:
14 |
15 | `npm install`
16 |
17 | Agora pronto, você já pode começar a contribuir com o projeto!
18 |
19 | ## Reportando Issues
20 |
21 | Você pode criar uma issue [aqui](https://github.com/BrasilAPI/cep-promise/issues), mas, lembre-se de ser claro e informar o máximo de detalhes possíveis.
22 |
23 | ## Submetendo Pull Requests
24 | * Crie pull requests pequenos, para que a revisão seja feita mais facilmente
25 | * Inclua detalhes do que está sendo feito na descrição
26 | * Altera a documentação se for necessário
27 | * Verifique se todos os testes estão passando localmente
28 | * Não esqueça de verificar o build com as validações de teste coverage e build no travis-ci
29 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | The MIT License (MIT)
2 |
3 | Copyright (c) 2015 Filipe Deschamps
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
23 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | CEP Promise
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 | Busca por CEP integrado diretamente aos serviços dos Correios, ViaCEP e WideNet (Node.js e Browser)
27 |
28 |
29 | ## Features
30 |
31 | * Sempre atualizado em tempo-real por se conectar diretamente aos serviços dos Correios, ViaCEP e WideNet.
32 | * Possui alta disponibilidade por usar vários serviços como fallback.
33 | * Sempre retorna a resposta mais rápida por fazer as consultas de forma concorrente.
34 | * Sem limites de uso (rate limits) conhecidos.
35 | * Interface de Promise extremamente simples.
36 | * Suporte ao Node.js `10.x`, `11.x`, `12.x`, `13.x`, `14.x` e `@stable`.
37 | * Suporte ao Node.js `4.x`, `5.x`, `6.x`, `7.x`, `8.x`, `9.x`, até cep-promise versão `3.0.9`.
38 | * Suporte ao Node.js `0.10.x` e `0.12.x` até cep-promise versão `2.0.8`.
39 | * 100% de code coverage com testes unitários e E2E.
40 | * Desenvolvido utilizando ES6.
41 |
42 |
43 | ## Como utilizar
44 |
45 | Teste e aprenda aqui.
46 |
47 | ### Realizando uma consulta
48 |
49 | Por ser multifornecedor, a biblioteca irá resolver a Promise com o fornecedor que **mais rápido** lhe responder.
50 |
51 | ``` js
52 | import cep from 'cep-promise'
53 |
54 | cep('05010000')
55 | .then(console.log)
56 |
57 | // {
58 | // "cep": "05010000",
59 | // "state": "SP",
60 | // "city": "São Paulo",
61 | // "street": "Rua Caiubí",
62 | // "neighborhood": "Perdizes",
63 | // }
64 | ```
65 |
66 |
67 | ### Você também poderá passar o CEP como Inteiro
68 |
69 | Em muitos sistemas o CEP é utilizado erroneamente como um Inteiro (e com isto cortando 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:
70 |
71 | ``` js
72 | import cep from 'cep-promise'
73 |
74 | // enviando sem ter um zero à esquerda do CEP "05010000"
75 | cep(5010000)
76 | .then(console.log)
77 |
78 | // {
79 | // "cep": "05010000",
80 | // "state": "SP",
81 | // "city": "São Paulo",
82 | // "street": "Rua Caiubí",
83 | // "neighborhood": "Perdizes",
84 | // }
85 | ```
86 |
87 | ### Quando o CEP não é encontrado
88 |
89 | 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.
90 |
91 | ``` js
92 | import cep from 'cep-promise'
93 |
94 | cep('99999999')
95 | .catch(console.log)
96 |
97 | // {
98 | // name: 'CepPromiseError',
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 |
110 | ```
111 |
112 | ### Quando o CEP possui um formato inválido
113 |
114 | Neste caso será retornado um `"validation_error"` e a biblioteca irá rejeitar imediatamente a Promise, sem chegar a consultar nenhum fornecedor.
115 |
116 | ``` js
117 | import cep from 'cep-promise'
118 |
119 | cep('123456789123456789')
120 | .catch(console.log)
121 |
122 | // {
123 | // name: 'CepPromiseError',
124 | // message: 'CEP deve conter exatamente 8 caracteres.',
125 | // type: 'validation_error',
126 | // errors: [{
127 | // message: 'CEP informado possui mais do que 8 caracteres.',
128 | // service: 'cep_validation'
129 | // }]
130 | // }
131 | ```
132 | ### Options
133 | - `timeout`: Timeout em milisegundos das consultas em cada serviço. O tempo total poderá ser maior devido a limites no paralelismo.
134 | - `providers`: Lista de providers a serem usados na consulta. Default é usar todos os providers disponíveis.
135 |
136 | ```js
137 | import cep from 'cep-promise'
138 | cep('5010000', { timeout: 5000, providers: ['brasilapi'] })
139 | .then(console.log)
140 |
141 | ```
142 |
143 | ### Instalação
144 |
145 | #### Browser usando CDN
146 | ```
147 |
148 | ```
149 |
150 | #### npm
151 |
152 | ```
153 | $ npm install --save cep-promise
154 | ```
155 |
156 | #### Bower
157 |
158 | ```
159 | $ bower install --save cep-promise
160 | ```
161 | #### yarn
162 |
163 | ```
164 | $ yarn add cep-promise
165 | ```
166 |
167 | #### Angular 2
168 |
169 | ``` ts
170 | import * as cep from 'cep-promise'
171 |
172 | cep('05010000')
173 | .then(console.log)
174 | ```
175 |
176 | ## Como contribuir
177 |
178 | Leia nosso guia de contribuição [aqui](CONTRIBUTING.md)
179 |
180 | ## Contribuidores
181 |
182 |
183 |
184 | ## Autor
185 |
186 | | [
@filipedeschamps](https://github.com/filipedeschamps) |
187 | | :---: |
--------------------------------------------------------------------------------
/bower.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "cep-promise",
3 | "version": "2.0.5",
4 | "description": "Busca por CEP integrado diretamente aos serviços dos Correios e ViaCEP",
5 | "main": "dist/cep-promise.js",
6 | "authors": [
7 | "Filipe Deschamps"
8 | ],
9 | "license": "MIT",
10 | "homepage": "https://github.com/filipedeschamps/cep-promise",
11 | "ignore": [
12 | "**/.*",
13 | "node_modules",
14 | "src",
15 | "test"
16 | ]
17 | }
18 |
--------------------------------------------------------------------------------
/content/logo.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/BrasilAPI/cep-promise/43fbb0004dee5b0f89af5df6399fc37aca151a6d/content/logo.gif
--------------------------------------------------------------------------------
/dist/cep-promise-browser.js:
--------------------------------------------------------------------------------
1 | (function (global, factory) {
2 | typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory() :
3 | typeof define === 'function' && define.amd ? define(factory) :
4 | (global = global || self, global.cep = factory());
5 | }(this, (function () { 'use strict';
6 |
7 | function _typeof(obj) {
8 | "@babel/helpers - typeof";
9 |
10 | if (typeof Symbol === "function" && typeof Symbol.iterator === "symbol") {
11 | _typeof = function (obj) {
12 | return typeof obj;
13 | };
14 | } else {
15 | _typeof = function (obj) {
16 | return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj;
17 | };
18 | }
19 |
20 | return _typeof(obj);
21 | }
22 |
23 | function _classCallCheck(instance, Constructor) {
24 | if (!(instance instanceof Constructor)) {
25 | throw new TypeError("Cannot call a class as a function");
26 | }
27 | }
28 |
29 | function _inherits(subClass, superClass) {
30 | if (typeof superClass !== "function" && superClass !== null) {
31 | throw new TypeError("Super expression must either be null or a function");
32 | }
33 |
34 | subClass.prototype = Object.create(superClass && superClass.prototype, {
35 | constructor: {
36 | value: subClass,
37 | writable: true,
38 | configurable: true
39 | }
40 | });
41 | if (superClass) _setPrototypeOf(subClass, superClass);
42 | }
43 |
44 | function _getPrototypeOf(o) {
45 | _getPrototypeOf = Object.setPrototypeOf ? Object.getPrototypeOf : function _getPrototypeOf(o) {
46 | return o.__proto__ || Object.getPrototypeOf(o);
47 | };
48 | return _getPrototypeOf(o);
49 | }
50 |
51 | function _setPrototypeOf(o, p) {
52 | _setPrototypeOf = Object.setPrototypeOf || function _setPrototypeOf(o, p) {
53 | o.__proto__ = p;
54 | return o;
55 | };
56 |
57 | return _setPrototypeOf(o, p);
58 | }
59 |
60 | function _isNativeReflectConstruct() {
61 | if (typeof Reflect === "undefined" || !Reflect.construct) return false;
62 | if (Reflect.construct.sham) return false;
63 | if (typeof Proxy === "function") return true;
64 |
65 | try {
66 | Date.prototype.toString.call(Reflect.construct(Date, [], function () {}));
67 | return true;
68 | } catch (e) {
69 | return false;
70 | }
71 | }
72 |
73 | function _construct(Parent, args, Class) {
74 | if (_isNativeReflectConstruct()) {
75 | _construct = Reflect.construct;
76 | } else {
77 | _construct = function _construct(Parent, args, Class) {
78 | var a = [null];
79 | a.push.apply(a, args);
80 | var Constructor = Function.bind.apply(Parent, a);
81 | var instance = new Constructor();
82 | if (Class) _setPrototypeOf(instance, Class.prototype);
83 | return instance;
84 | };
85 | }
86 |
87 | return _construct.apply(null, arguments);
88 | }
89 |
90 | function _isNativeFunction(fn) {
91 | return Function.toString.call(fn).indexOf("[native code]") !== -1;
92 | }
93 |
94 | function _wrapNativeSuper(Class) {
95 | var _cache = typeof Map === "function" ? new Map() : undefined;
96 |
97 | _wrapNativeSuper = function _wrapNativeSuper(Class) {
98 | if (Class === null || !_isNativeFunction(Class)) return Class;
99 |
100 | if (typeof Class !== "function") {
101 | throw new TypeError("Super expression must either be null or a function");
102 | }
103 |
104 | if (typeof _cache !== "undefined") {
105 | if (_cache.has(Class)) return _cache.get(Class);
106 |
107 | _cache.set(Class, Wrapper);
108 | }
109 |
110 | function Wrapper() {
111 | return _construct(Class, arguments, _getPrototypeOf(this).constructor);
112 | }
113 |
114 | Wrapper.prototype = Object.create(Class.prototype, {
115 | constructor: {
116 | value: Wrapper,
117 | enumerable: false,
118 | writable: true,
119 | configurable: true
120 | }
121 | });
122 | return _setPrototypeOf(Wrapper, Class);
123 | };
124 |
125 | return _wrapNativeSuper(Class);
126 | }
127 |
128 | function _assertThisInitialized(self) {
129 | if (self === void 0) {
130 | throw new ReferenceError("this hasn't been initialised - super() hasn't been called");
131 | }
132 |
133 | return self;
134 | }
135 |
136 | function _possibleConstructorReturn(self, call) {
137 | if (call && (typeof call === "object" || typeof call === "function")) {
138 | return call;
139 | }
140 |
141 | return _assertThisInitialized(self);
142 | }
143 |
144 | function _createSuper(Derived) {
145 | var hasNativeReflectConstruct = _isNativeReflectConstruct();
146 |
147 | return function _createSuperInternal() {
148 | var Super = _getPrototypeOf(Derived),
149 | result;
150 |
151 | if (hasNativeReflectConstruct) {
152 | var NewTarget = _getPrototypeOf(this).constructor;
153 |
154 | result = Reflect.construct(Super, arguments, NewTarget);
155 | } else {
156 | result = Super.apply(this, arguments);
157 | }
158 |
159 | return _possibleConstructorReturn(this, result);
160 | };
161 | }
162 |
163 | function _toConsumableArray(arr) {
164 | return _arrayWithoutHoles(arr) || _iterableToArray(arr) || _unsupportedIterableToArray(arr) || _nonIterableSpread();
165 | }
166 |
167 | function _arrayWithoutHoles(arr) {
168 | if (Array.isArray(arr)) return _arrayLikeToArray(arr);
169 | }
170 |
171 | function _iterableToArray(iter) {
172 | if (typeof Symbol !== "undefined" && Symbol.iterator in Object(iter)) return Array.from(iter);
173 | }
174 |
175 | function _unsupportedIterableToArray(o, minLen) {
176 | if (!o) return;
177 | if (typeof o === "string") return _arrayLikeToArray(o, minLen);
178 | var n = Object.prototype.toString.call(o).slice(8, -1);
179 | if (n === "Object" && o.constructor) n = o.constructor.name;
180 | if (n === "Map" || n === "Set") return Array.from(o);
181 | if (n === "Arguments" || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)) return _arrayLikeToArray(o, minLen);
182 | }
183 |
184 | function _arrayLikeToArray(arr, len) {
185 | if (len == null || len > arr.length) len = arr.length;
186 |
187 | for (var i = 0, arr2 = new Array(len); i < len; i++) arr2[i] = arr[i];
188 |
189 | return arr2;
190 | }
191 |
192 | function _nonIterableSpread() {
193 | throw new TypeError("Invalid attempt to spread non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.");
194 | }
195 |
196 | function _createForOfIteratorHelper(o, allowArrayLike) {
197 | var it;
198 |
199 | if (typeof Symbol === "undefined" || o[Symbol.iterator] == null) {
200 | if (Array.isArray(o) || (it = _unsupportedIterableToArray(o)) || allowArrayLike && o && typeof o.length === "number") {
201 | if (it) o = it;
202 | var i = 0;
203 |
204 | var F = function () {};
205 |
206 | return {
207 | s: F,
208 | n: function () {
209 | if (i >= o.length) return {
210 | done: true
211 | };
212 | return {
213 | done: false,
214 | value: o[i++]
215 | };
216 | },
217 | e: function (e) {
218 | throw e;
219 | },
220 | f: F
221 | };
222 | }
223 |
224 | throw new TypeError("Invalid attempt to iterate non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.");
225 | }
226 |
227 | var normalCompletion = true,
228 | didErr = false,
229 | err;
230 | return {
231 | s: function () {
232 | it = o[Symbol.iterator]();
233 | },
234 | n: function () {
235 | var step = it.next();
236 | normalCompletion = step.done;
237 | return step;
238 | },
239 | e: function (e) {
240 | didErr = true;
241 | err = e;
242 | },
243 | f: function () {
244 | try {
245 | if (!normalCompletion && it.return != null) it.return();
246 | } finally {
247 | if (didErr) throw err;
248 | }
249 | }
250 | };
251 | }
252 |
253 | var CepPromiseError = /*#__PURE__*/function (_Error) {
254 | _inherits(CepPromiseError, _Error);
255 |
256 | var _super = _createSuper(CepPromiseError);
257 |
258 | function CepPromiseError() {
259 | var _this;
260 |
261 | var _ref = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {},
262 | message = _ref.message,
263 | type = _ref.type,
264 | errors = _ref.errors;
265 |
266 | _classCallCheck(this, CepPromiseError);
267 |
268 | _this = _super.call(this);
269 | _this.name = 'CepPromiseError';
270 | _this.message = message;
271 | _this.type = type;
272 | _this.errors = errors;
273 | return _this;
274 | }
275 |
276 | return CepPromiseError;
277 | }( /*#__PURE__*/_wrapNativeSuper(Error));
278 |
279 | function fetch (e, n) {
280 | return n = n || {}, new Promise(function (t, r) {
281 | var s = new XMLHttpRequest(),
282 | o = [],
283 | u = [],
284 | i = {},
285 | a = function a() {
286 | return {
287 | ok: 2 == (s.status / 100 | 0),
288 | statusText: s.statusText,
289 | status: s.status,
290 | url: s.responseURL,
291 | text: function text() {
292 | return Promise.resolve(s.responseText);
293 | },
294 | json: function json() {
295 | return Promise.resolve(JSON.parse(s.responseText));
296 | },
297 | blob: function blob() {
298 | return Promise.resolve(new Blob([s.response]));
299 | },
300 | clone: a,
301 | headers: {
302 | keys: function keys() {
303 | return o;
304 | },
305 | entries: function entries() {
306 | return u;
307 | },
308 | get: function get(e) {
309 | return i[e.toLowerCase()];
310 | },
311 | has: function has(e) {
312 | return e.toLowerCase() in i;
313 | }
314 | }
315 | };
316 | };
317 |
318 | for (var l in s.open(n.method || "get", e, !0), s.onload = function () {
319 | s.getAllResponseHeaders().replace(/^(.*?):[^\S\n]*([\s\S]*?)$/gm, function (e, n, t) {
320 | o.push(n = n.toLowerCase()), u.push([n, t]), i[n] = i[n] ? i[n] + "," + t : t;
321 | }), t(a());
322 | }, s.onerror = r, s.withCredentials = "include" == n.credentials, n.headers) {
323 | s.setRequestHeader(l, n.headers[l]);
324 | }
325 |
326 | s.send(n.body || null);
327 | });
328 | }
329 |
330 | var ServiceError = /*#__PURE__*/function (_Error) {
331 | _inherits(ServiceError, _Error);
332 |
333 | var _super = _createSuper(ServiceError);
334 |
335 | function ServiceError() {
336 | var _this;
337 |
338 | var _ref = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {},
339 | message = _ref.message,
340 | service = _ref.service;
341 |
342 | _classCallCheck(this, ServiceError);
343 |
344 | _this = _super.call(this);
345 | _this.name = 'ServiceError';
346 | _this.message = message;
347 | _this.service = service;
348 | return _this;
349 | }
350 |
351 | return ServiceError;
352 | }( /*#__PURE__*/_wrapNativeSuper(Error));
353 |
354 | function fetchCorreiosService(cepWithLeftPad, configurations) {
355 | var url = 'https://apps.correios.com.br/SigepMasterJPA/AtendeClienteService/AtendeCliente';
356 | var options = {
357 | method: 'POST',
358 | body: "\n\n \n \n \n ".concat(cepWithLeftPad, "\n \n \n"),
359 | headers: {
360 | 'Content-Type': 'text/xml;charset=UTF-8',
361 | 'cache-control': 'no-cache'
362 | },
363 | timeout: configurations.timeout || 30000
364 | };
365 | return fetch(url, options).then(analyzeAndParseResponse)["catch"](throwApplicationError);
366 | }
367 |
368 | function analyzeAndParseResponse(response) {
369 | if (response.ok) {
370 | return response.text().then(parseSuccessXML).then(extractValuesFromSuccessResponse);
371 | }
372 |
373 | return response.text().then(parseAndextractErrorMessage).then(throwCorreiosError);
374 | }
375 |
376 | function parseSuccessXML(xmlString) {
377 | try {
378 | var _xmlString$replace$ma;
379 |
380 | var returnStatement = (_xmlString$replace$ma = xmlString.replace(/\r?\n|\r/g, '').match(/(.*)<\/return>/)[0]) !== null && _xmlString$replace$ma !== void 0 ? _xmlString$replace$ma : '';
381 | var cleanReturnStatement = returnStatement.replace('', '').replace('', '');
382 | var parsedReturnStatement = cleanReturnStatement.split(/).reduce(function (result, exp) {
383 | var splittenExp = exp.split('>');
384 |
385 | if (splittenExp.length > 1 && splittenExp[1].length) {
386 | result[splittenExp[0]] = splittenExp[1];
387 | }
388 |
389 | return result;
390 | }, {});
391 | return parsedReturnStatement;
392 | } catch (e) {
393 | throw new Error('Não foi possível interpretar o XML de resposta.');
394 | }
395 | }
396 |
397 | function parseAndextractErrorMessage(xmlString) {
398 | try {
399 | var _xmlString$match$;
400 |
401 | var returnStatement = (_xmlString$match$ = xmlString.match(/(.*)<\/faultstring>/)[0]) !== null && _xmlString$match$ !== void 0 ? _xmlString$match$ : '';
402 | var cleanReturnStatement = returnStatement.replace('', '').replace('', '');
403 | return cleanReturnStatement;
404 | } catch (e) {
405 | throw new Error('Não foi possível interpretar o XML de resposta.');
406 | }
407 | }
408 |
409 | function throwCorreiosError(translatedErrorMessage) {
410 | throw new Error(translatedErrorMessage);
411 | }
412 |
413 | function extractValuesFromSuccessResponse(xmlObject) {
414 | return {
415 | cep: xmlObject.cep,
416 | state: xmlObject.uf,
417 | city: xmlObject.cidade,
418 | neighborhood: xmlObject.bairro,
419 | street: xmlObject.end,
420 | service: 'correios'
421 | };
422 | }
423 |
424 | function throwApplicationError(error) {
425 | var serviceError = new ServiceError({
426 | message: error.message,
427 | service: 'correios'
428 | });
429 |
430 | if (error.name === 'FetchError') {
431 | serviceError.message = 'Erro ao se conectar com o serviço dos Correios.';
432 | }
433 |
434 | throw serviceError;
435 | }
436 |
437 | function fetchCorreiosAltAPIService(cepWithLeftPad, configurations) {
438 | var url = 'https://buscacepinter.correios.com.br/app/endereco/carrega-cep-endereco.php';
439 | var options = {
440 | method: 'POST',
441 | mode: 'cors',
442 | headers: {
443 | 'content-type': 'application/x-www-form-urlencoded; charset=UTF-8',
444 | 'Referer': 'https://buscacepinter.correios.com.br/app/endereco/index.php',
445 | 'Referrer-Policy': 'strict-origin-when-cross-origin'
446 | },
447 | body: "endereco=".concat(cepWithLeftPad, "&tipoCEP=ALL"),
448 | timeout: configurations.timeout || 30000
449 | };
450 | return fetch(url, options).then(parseResponse).then(extractCepValuesFromResponse)["catch"](throwApplicationError$1);
451 | }
452 |
453 | function parseResponse(response) {
454 | return response.json().then(function (result) {
455 | if (result.total === 0 || result.erro || result.dados[0].cep === "") {
456 | throw new Error('CEP não encontrado na base dos Correios.');
457 | }
458 |
459 | return result;
460 | });
461 | }
462 |
463 | function extractCepValuesFromResponse(response) {
464 | var firstCep = response.dados[0];
465 | return {
466 | cep: firstCep.cep,
467 | state: firstCep.uf,
468 | city: firstCep.localidade,
469 | neighborhood: firstCep.bairro,
470 | street: firstCep.logradouroDNEC,
471 | service: 'correios-alt'
472 | };
473 | }
474 |
475 | function throwApplicationError$1(error) {
476 | var serviceError = new ServiceError({
477 | message: error.message,
478 | service: 'correios-alt'
479 | });
480 |
481 | if (error.name === 'FetchError') {
482 | serviceError.message = 'Erro ao se conectar com o serviço dos Correios Alt.';
483 | }
484 |
485 | throw serviceError;
486 | }
487 |
488 | function fetchViaCepService(cepWithLeftPad, configurations) {
489 | var url = "https://viacep.com.br/ws/".concat(cepWithLeftPad, "/json/");
490 | var options = {
491 | method: 'GET',
492 | mode: 'cors',
493 | headers: {
494 | 'content-type': 'application/json;charset=utf-8'
495 | },
496 | timeout: configurations.timeout || 30000
497 | };
498 |
499 | if (typeof window == 'undefined') {
500 | options.headers['user-agent'] = 'cep-promise';
501 | }
502 |
503 | return fetch(url, options).then(analyzeAndParseResponse$1).then(checkForViaCepError).then(extractCepValuesFromResponse$1)["catch"](throwApplicationError$2);
504 | }
505 |
506 | function analyzeAndParseResponse$1(response) {
507 | if (response.ok) {
508 | return response.json();
509 | }
510 |
511 | throw Error('Erro ao se conectar com o serviço ViaCEP.');
512 | }
513 |
514 | function checkForViaCepError(responseObject) {
515 | if (responseObject.erro === true) {
516 | throw new Error('CEP não encontrado na base do ViaCEP.');
517 | }
518 |
519 | return responseObject;
520 | }
521 |
522 | function extractCepValuesFromResponse$1(responseObject) {
523 | return {
524 | cep: responseObject.cep.replace('-', ''),
525 | state: responseObject.uf,
526 | city: responseObject.localidade,
527 | neighborhood: responseObject.bairro,
528 | street: responseObject.logradouro,
529 | service: 'viacep'
530 | };
531 | }
532 |
533 | function throwApplicationError$2(error) {
534 | var serviceError = new ServiceError({
535 | message: error.message,
536 | service: 'viacep'
537 | });
538 |
539 | if (error.name === 'FetchError') {
540 | serviceError.message = 'Erro ao se conectar com o serviço ViaCEP.';
541 | }
542 |
543 | throw serviceError;
544 | }
545 |
546 | function fetchWideNetService(cepWithLeftPad, configurations) {
547 | var cepWithDash = "".concat(cepWithLeftPad.slice(0, 5), "-").concat(cepWithLeftPad.slice(5));
548 | var url = "https://cdn.apicep.com/file/apicep/".concat(cepWithDash, ".json");
549 | var options = {
550 | method: 'GET',
551 | mode: 'cors',
552 | headers: {
553 | accept: 'application/json'
554 | },
555 | timeout: configurations.timeout || 30000
556 | };
557 | return fetch(url, options).then(analyzeAndParseResponse$2).then(checkForWideNetError).then(extractCepValuesFromResponse$2)["catch"](throwApplicationError$3);
558 | }
559 |
560 | function analyzeAndParseResponse$2(response) {
561 | if (response.ok) {
562 | return response.json();
563 | }
564 |
565 | throw Error('Erro ao se conectar com o serviço WideNet.');
566 | }
567 |
568 | function checkForWideNetError(object) {
569 | if (object.ok === false || object.status !== 200) {
570 | throw new Error('CEP não encontrado na base do WideNet.');
571 | }
572 |
573 | return object;
574 | }
575 |
576 | function extractCepValuesFromResponse$2(object) {
577 | return {
578 | cep: object.code.replace('-', ''),
579 | state: object.state,
580 | city: object.city,
581 | neighborhood: object.district,
582 | street: object.address,
583 | service: 'widenet'
584 | };
585 | }
586 |
587 | function throwApplicationError$3(error) {
588 | var serviceError = new ServiceError({
589 | message: error.message,
590 | service: 'widenet'
591 | });
592 |
593 | if (error.name === 'FetchError') {
594 | serviceError.message = 'Erro ao se conectar com o serviço WideNet.';
595 | }
596 |
597 | throw serviceError;
598 | }
599 |
600 | function fetchBrasilAPIService(cepWithLeftPad, configurations) {
601 | var url = "https://brasilapi.com.br/api/cep/v1/".concat(cepWithLeftPad);
602 | var options = {
603 | method: 'GET',
604 | mode: 'cors',
605 | headers: {
606 | 'content-type': 'application/json;charset=utf-8'
607 | },
608 | timeout: configurations.timeout || 30000
609 | };
610 | return fetch(url, options).then(parseResponse$1).then(extractCepValuesFromResponse$3)["catch"](throwApplicationError$4);
611 | }
612 |
613 | function parseResponse$1(response) {
614 | if (response.ok === false || response.status !== 200) {
615 | throw new Error('CEP não encontrado na base do BrasilAPI.');
616 | }
617 |
618 | return response.json();
619 | }
620 |
621 | function extractCepValuesFromResponse$3(response) {
622 | return {
623 | cep: response.cep,
624 | state: response.state,
625 | city: response.city,
626 | neighborhood: response.neighborhood,
627 | street: response.street,
628 | service: 'brasilapi'
629 | };
630 | }
631 |
632 | function throwApplicationError$4(error) {
633 | var serviceError = new ServiceError({
634 | message: error.message,
635 | service: 'brasilapi'
636 | });
637 |
638 | if (error.name === 'FetchError') {
639 | serviceError.message = 'Erro ao se conectar com o serviço BrasilAPI.';
640 | }
641 |
642 | throw serviceError;
643 | }
644 |
645 | function getAvailableServices() {
646 | var isBrowser = typeof window !== 'undefined';
647 |
648 | if (isBrowser) {
649 | return {
650 | viacep: fetchViaCepService,
651 | widenet: fetchWideNetService,
652 | brasilapi: fetchBrasilAPIService
653 | };
654 | }
655 |
656 | return {
657 | correios: fetchCorreiosService,
658 | 'correios-alt': fetchCorreiosAltAPIService,
659 | viacep: fetchViaCepService,
660 | widenet: fetchWideNetService,
661 | brasilapi: fetchBrasilAPIService
662 | };
663 | }
664 |
665 | var reverse = function reverse(promise) {
666 | return new Promise(function (resolve, reject) {
667 | return Promise.resolve(promise).then(reject, resolve);
668 | });
669 | };
670 |
671 | Promise.any = function (iterable) {
672 | return reverse(Promise.all(_toConsumableArray(iterable).map(reverse)));
673 | };
674 |
675 | var Promise$1 = Promise;
676 |
677 | var CEP_SIZE = 8;
678 | function cepPromise (cepRawValue) {
679 | var configurations = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
680 | return Promise$1.resolve(cepRawValue).then(validateInputType).then(function (cepRawValue) {
681 | configurations.providers = configurations.providers ? configurations.providers : [];
682 | validateProviders(configurations.providers);
683 | return cepRawValue;
684 | }).then(removeSpecialCharacters).then(validateInputLength).then(leftPadWithZeros).then(function (cepWithLeftPad) {
685 | return fetchCepFromServices(cepWithLeftPad, configurations);
686 | })["catch"](handleServicesError)["catch"](throwApplicationError$5);
687 | }
688 |
689 | function validateProviders(providers) {
690 | var availableProviders = Object.keys(getAvailableServices());
691 |
692 | if (!Array.isArray(providers)) {
693 | throw new CepPromiseError({
694 | message: 'Erro ao inicializar a instância do CepPromise.',
695 | type: 'validation_error',
696 | errors: [{
697 | message: 'O parâmetro providers deve ser uma lista.',
698 | service: 'providers_validation'
699 | }]
700 | });
701 | }
702 |
703 | var _iterator = _createForOfIteratorHelper(providers),
704 | _step;
705 |
706 | try {
707 | for (_iterator.s(); !(_step = _iterator.n()).done;) {
708 | var provider = _step.value;
709 |
710 | if (!availableProviders.includes(provider)) {
711 | throw new CepPromiseError({
712 | message: 'Erro ao inicializar a instância do CepPromise.',
713 | type: 'validation_error',
714 | errors: [{
715 | message: "O provider \"".concat(provider, "\" \xE9 inv\xE1lido. Os providers dispon\xEDveis s\xE3o: [\"").concat(availableProviders.join('", "'), "\"]."),
716 | service: 'providers_validation'
717 | }]
718 | });
719 | }
720 | }
721 | } catch (err) {
722 | _iterator.e(err);
723 | } finally {
724 | _iterator.f();
725 | }
726 | }
727 |
728 | function validateInputType(cepRawValue) {
729 | var cepTypeOf = _typeof(cepRawValue);
730 |
731 | if (cepTypeOf === 'number' || cepTypeOf === 'string') {
732 | return cepRawValue;
733 | }
734 |
735 | throw new CepPromiseError({
736 | message: 'Erro ao inicializar a instância do CepPromise.',
737 | type: 'validation_error',
738 | errors: [{
739 | message: 'Você deve chamar o construtor utilizando uma String ou um Number.',
740 | service: 'cep_validation'
741 | }]
742 | });
743 | }
744 |
745 | function removeSpecialCharacters(cepRawValue) {
746 | return cepRawValue.toString().replace(/\D+/g, '');
747 | }
748 |
749 | function leftPadWithZeros(cepCleanValue) {
750 | return '0'.repeat(CEP_SIZE - cepCleanValue.length) + cepCleanValue;
751 | }
752 |
753 | function validateInputLength(cepWithLeftPad) {
754 | if (cepWithLeftPad.length <= CEP_SIZE) {
755 | return cepWithLeftPad;
756 | }
757 |
758 | throw new CepPromiseError({
759 | message: "CEP deve conter exatamente ".concat(CEP_SIZE, " caracteres."),
760 | type: 'validation_error',
761 | errors: [{
762 | message: "CEP informado possui mais do que ".concat(CEP_SIZE, " caracteres."),
763 | service: 'cep_validation'
764 | }]
765 | });
766 | }
767 |
768 | function fetchCepFromServices(cepWithLeftPad, configurations) {
769 | var providersServices = getAvailableServices();
770 |
771 | if (configurations.providers.length === 0) {
772 | return Promise$1.any(Object.values(providersServices).map(function (provider) {
773 | return provider(cepWithLeftPad, configurations);
774 | }));
775 | }
776 |
777 | return Promise$1.any(configurations.providers.map(function (provider) {
778 | return providersServices[provider](cepWithLeftPad, configurations);
779 | }));
780 | }
781 |
782 | function handleServicesError(aggregatedErrors) {
783 | if (aggregatedErrors.length !== undefined) {
784 | throw new CepPromiseError({
785 | message: 'Todos os serviços de CEP retornaram erro.',
786 | type: 'service_error',
787 | errors: aggregatedErrors
788 | });
789 | }
790 |
791 | throw aggregatedErrors;
792 | }
793 |
794 | function throwApplicationError$5(_ref) {
795 | var message = _ref.message,
796 | type = _ref.type,
797 | errors = _ref.errors;
798 | throw new CepPromiseError({
799 | message: message,
800 | type: type,
801 | errors: errors
802 | });
803 | }
804 |
805 | return cepPromise;
806 |
807 | })));
808 |
--------------------------------------------------------------------------------
/dist/cep-promise-browser.min.js:
--------------------------------------------------------------------------------
1 | !function(e,r){"object"==typeof exports&&"undefined"!=typeof module?module.exports=r():"function"==typeof define&&define.amd?define(r):(e=e||self).cep=r()}(this,function(){"use strict";function t(e){return(t="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(e){return typeof e}:function(e){return e&&"function"==typeof Symbol&&e.constructor===Symbol&&e!==Symbol.prototype?"symbol":typeof e})(e)}function a(e,r){if(!(e instanceof r))throw new TypeError("Cannot call a class as a function")}function e(e,r){if("function"!=typeof r&&null!==r)throw new TypeError("Super expression must either be null or a function");e.prototype=Object.create(r&&r.prototype,{constructor:{value:e,writable:!0,configurable:!0}}),r&&i(e,r)}function o(e){return(o=Object.setPrototypeOf?Object.getPrototypeOf:function(e){return e.__proto__||Object.getPrototypeOf(e)})(e)}function i(e,r){return(i=Object.setPrototypeOf||function(e,r){return e.__proto__=r,e})(e,r)}function c(){if("undefined"==typeof Reflect||!Reflect.construct)return!1;if(Reflect.construct.sham)return!1;if("function"==typeof Proxy)return!0;try{return Date.prototype.toString.call(Reflect.construct(Date,[],function(){})),!0}catch(e){return!1}}function s(e,r,t){return(s=c()?Reflect.construct:function(e,r,t){var n=[null];n.push.apply(n,r);var o=new(Function.bind.apply(e,n));return t&&i(o,t.prototype),o}).apply(null,arguments)}function r(e){var n="function"==typeof Map?new Map:void 0;return(r=function(e){if(null===e||(r=e,-1===Function.toString.call(r).indexOf("[native code]")))return e;var r;if("function"!=typeof e)throw new TypeError("Super expression must either be null or a function");if(void 0!==n){if(n.has(e))return n.get(e);n.set(e,t)}function t(){return s(e,arguments,o(this).constructor)}return t.prototype=Object.create(e.prototype,{constructor:{value:t,enumerable:!1,writable:!0,configurable:!0}}),i(t,e)})(e)}function u(e,r){return!r||"object"!=typeof r&&"function"!=typeof r?function(e){if(void 0===e)throw new ReferenceError("this hasn't been initialised - super() hasn't been called");return e}(e):r}function n(t){var n=c();return function(){var e,r=o(t);return u(this,n?(e=o(this).constructor,Reflect.construct(r,arguments,e)):r.apply(this,arguments))}}function p(e){return function(e){if(Array.isArray(e))return l(e)}(e)||function(e){if("undefined"!=typeof Symbol&&Symbol.iterator in Object(e))return Array.from(e)}(e)||f(e)||function(){throw new TypeError("Invalid attempt to spread non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.")}()}function f(e,r){if(e){if("string"==typeof e)return l(e,r);var t=Object.prototype.toString.call(e).slice(8,-1);return"Object"===t&&e.constructor&&(t=e.constructor.name),"Map"===t||"Set"===t?Array.from(e):"Arguments"===t||/^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(t)?l(e,r):void 0}}function l(e,r){(null==r||r>e.length)&&(r=e.length);for(var t=0,n=new Array(r);t\n\n \n \n \n '.concat(e,"\n \n \n"),headers:{"Content-Type":"text/xml;charset=UTF-8","cache-control":"no-cache"},timeout:r.timeout||3e4}).then(y).catch(P)}function y(e){return e.ok?e.text().then(b).then(E):e.text().then(g).then(w)}function b(e){try{var r;return(null!==(r=e.replace(/\r?\n|\r/g,"").match(/(.*)<\/return>/)[0])&&void 0!==r?r:"").replace("","").replace("","").split(/).reduce(function(e,r){var t=r.split(">");return 1(.*)<\/faultstring>/)[0])&&void 0!==r?r:"").replace("","").replace("","")}catch(e){throw new Error("Não foi possível interpretar o XML de resposta.")}}function w(e){throw new Error(e)}function E(e){return{cep:e.cep,state:e.uf,city:e.cidade,neighborhood:e.bairro,street:e.end,service:"correios"}}function P(e){var r=new m({message:e.message,service:"correios"});throw"FetchError"===e.name&&(r.message="Erro ao se conectar com o serviço dos Correios."),r}function C(e,r){return h("https://buscacepinter.correios.com.br/app/endereco/carrega-cep-endereco.php",{method:"POST",mode:"cors",headers:{"content-type":"application/x-www-form-urlencoded; charset=UTF-8",Referer:"https://buscacepinter.correios.com.br/app/endereco/index.php","Referrer-Policy":"strict-origin-when-cross-origin"},body:"endereco=".concat(e,"&tipoCEP=ALL"),timeout:r.timeout||3e4}).then(S).then(j).catch(x)}function S(e){return e.json().then(function(e){if(0===e.total||e.erro||""===e.dados[0].cep)throw new Error("CEP não encontrado na base dos Correios.");return e})}function j(e){var r=e.dados[0];return{cep:r.cep,state:r.uf,city:r.localidade,neighborhood:r.bairro,street:r.logradouroDNEC,service:"correios-alt"}}function x(e){var r=new m({message:e.message,service:"correios-alt"});throw"FetchError"===e.name&&(r.message="Erro ao se conectar com o serviço dos Correios Alt."),r}function O(e,r){var t="https://viacep.com.br/ws/".concat(e,"/json/"),n={method:"GET",mode:"cors",headers:{"content-type":"application/json;charset=utf-8"},timeout:r.timeout||3e4};return"undefined"==typeof window&&(n.headers["user-agent"]="cep-promise"),h(t,n).then(A).then(T).then(_).catch(R)}function A(e){if(e.ok)return e.json();throw Error("Erro ao se conectar com o serviço ViaCEP.")}function T(e){if(!0===e.erro)throw new Error("CEP não encontrado na base do ViaCEP.");return e}function _(e){return{cep:e.cep.replace("-",""),state:e.uf,city:e.localidade,neighborhood:e.bairro,street:e.logradouro,service:"viacep"}}function R(e){var r=new m({message:e.message,service:"viacep"});throw"FetchError"===e.name&&(r.message="Erro ao se conectar com o serviço ViaCEP."),r}function F(e,r){var t="".concat(e.slice(0,5),"-").concat(e.slice(5));return h("https://cdn.apicep.com/file/apicep/".concat(t,".json"),{method:"GET",mode:"cors",headers:{accept:"application/json"},timeout:r.timeout||3e4}).then(L).then(k).then(N).catch(I)}function L(e){if(e.ok)return e.json();throw Error("Erro ao se conectar com o serviço WideNet.")}function k(e){if(!1===e.ok||200!==e.status)throw new Error("CEP não encontrado na base do WideNet.");return e}function N(e){return{cep:e.code.replace("-",""),state:e.state,city:e.city,neighborhood:e.district,street:e.address,service:"widenet"}}function I(e){var r=new m({message:e.message,service:"widenet"});throw"FetchError"===e.name&&(r.message="Erro ao se conectar com o serviço WideNet."),r}function M(e,r){return h("https://brasilapi.com.br/api/cep/v1/".concat(e),{method:"GET",mode:"cors",headers:{"content-type":"application/json;charset=utf-8"},timeout:r.timeout||3e4}).then(B).then(z).catch(D)}function B(e){if(!1===e.ok||200!==e.status)throw new Error("CEP não encontrado na base do BrasilAPI.");return e.json()}function z(e){return{cep:e.cep,state:e.state,city:e.city,neighborhood:e.neighborhood,street:e.street,service:"brasilapi"}}function D(e){var r=new m({message:e.message,service:"brasilapi"});throw"FetchError"===e.name&&(r.message="Erro ao se conectar com o serviço BrasilAPI."),r}function H(){return"undefined"!=typeof window?{viacep:O,widenet:F,brasilapi:M}:{correios:v,"correios-alt":C,viacep:O,widenet:F,brasilapi:M}}function U(t){return new Promise(function(e,r){return Promise.resolve(t).then(r,e)})}Promise.any=function(e){return U(Promise.all(p(e).map(U)))};var V=Promise,q=8;function G(e){var r=t(e);if("number"===r||"string"===r)return e;throw new d({message:"Erro ao inicializar a instância do CepPromise.",type:"validation_error",errors:[{message:"Você deve chamar o construtor utilizando uma String ou um Number.",service:"cep_validation"}]})}function W(e){return e.toString().replace(/\D+/g,"")}function X(e){return"0".repeat(q-e.length)+e}function J(e){if(e.length<=q)return e;throw new d({message:"CEP deve conter exatamente ".concat(q," caracteres."),type:"validation_error",errors:[{message:"CEP informado possui mais do que ".concat(q," caracteres."),service:"cep_validation"}]})}function $(e){if(void 0!==e.length)throw new d({message:"Todos os serviços de CEP retornaram erro.",type:"service_error",errors:e});throw e}function K(e){var r=e.message,t=e.type,n=e.errors;throw new d({message:r,type:t,errors:n})}return function(e){var o=1=e.length?{done:!0}:{done:!1,value:e[n++]}},e:function(e){throw e},f:o}}throw new TypeError("Invalid attempt to iterate non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.")}var i,c=!0,a=!1;return{s:function(){t=e[Symbol.iterator]()},n:function(){var e=t.next();return c=e.done,e},e:function(e){a=!0,i=e},f:function(){try{c||null==t.return||t.return()}finally{if(a)throw i}}}}(e);try{for(n.s();!(t=n.n()).done;){var o=t.value;if(!r.includes(o))throw new d({message:"Erro ao inicializar a instância do CepPromise.",type:"validation_error",errors:[{message:'O provider "'.concat(o,'" é inválido. Os providers disponíveis são: ["').concat(r.join('", "'),'"].'),service:"providers_validation"}]})}}catch(e){n.e(e)}finally{n.f()}}(o.providers),e}).then(W).then(J).then(X).then(function(e){return r=e,t=o,n=H(),0!==t.providers.length?V.any(t.providers.map(function(e){return n[e](r,t)})):V.any(Object.values(n).map(function(e){return e(r,t)}));var r,t,n}).catch($).catch(K)}});
--------------------------------------------------------------------------------
/dist/cep-promise.js:
--------------------------------------------------------------------------------
1 | (function (global, factory) {
2 | typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory(require('node-fetch')) :
3 | typeof define === 'function' && define.amd ? define(['node-fetch'], factory) :
4 | (global = global || self, global.cep = factory(global.fetch));
5 | }(this, (function (fetch) { 'use strict';
6 |
7 | fetch = fetch && Object.prototype.hasOwnProperty.call(fetch, 'default') ? fetch['default'] : fetch;
8 |
9 | function _typeof(obj) {
10 | "@babel/helpers - typeof";
11 |
12 | if (typeof Symbol === "function" && typeof Symbol.iterator === "symbol") {
13 | _typeof = function (obj) {
14 | return typeof obj;
15 | };
16 | } else {
17 | _typeof = function (obj) {
18 | return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj;
19 | };
20 | }
21 |
22 | return _typeof(obj);
23 | }
24 |
25 | function _classCallCheck(instance, Constructor) {
26 | if (!(instance instanceof Constructor)) {
27 | throw new TypeError("Cannot call a class as a function");
28 | }
29 | }
30 |
31 | function _inherits(subClass, superClass) {
32 | if (typeof superClass !== "function" && superClass !== null) {
33 | throw new TypeError("Super expression must either be null or a function");
34 | }
35 |
36 | subClass.prototype = Object.create(superClass && superClass.prototype, {
37 | constructor: {
38 | value: subClass,
39 | writable: true,
40 | configurable: true
41 | }
42 | });
43 | if (superClass) _setPrototypeOf(subClass, superClass);
44 | }
45 |
46 | function _getPrototypeOf(o) {
47 | _getPrototypeOf = Object.setPrototypeOf ? Object.getPrototypeOf : function _getPrototypeOf(o) {
48 | return o.__proto__ || Object.getPrototypeOf(o);
49 | };
50 | return _getPrototypeOf(o);
51 | }
52 |
53 | function _setPrototypeOf(o, p) {
54 | _setPrototypeOf = Object.setPrototypeOf || function _setPrototypeOf(o, p) {
55 | o.__proto__ = p;
56 | return o;
57 | };
58 |
59 | return _setPrototypeOf(o, p);
60 | }
61 |
62 | function _isNativeReflectConstruct() {
63 | if (typeof Reflect === "undefined" || !Reflect.construct) return false;
64 | if (Reflect.construct.sham) return false;
65 | if (typeof Proxy === "function") return true;
66 |
67 | try {
68 | Date.prototype.toString.call(Reflect.construct(Date, [], function () {}));
69 | return true;
70 | } catch (e) {
71 | return false;
72 | }
73 | }
74 |
75 | function _construct(Parent, args, Class) {
76 | if (_isNativeReflectConstruct()) {
77 | _construct = Reflect.construct;
78 | } else {
79 | _construct = function _construct(Parent, args, Class) {
80 | var a = [null];
81 | a.push.apply(a, args);
82 | var Constructor = Function.bind.apply(Parent, a);
83 | var instance = new Constructor();
84 | if (Class) _setPrototypeOf(instance, Class.prototype);
85 | return instance;
86 | };
87 | }
88 |
89 | return _construct.apply(null, arguments);
90 | }
91 |
92 | function _isNativeFunction(fn) {
93 | return Function.toString.call(fn).indexOf("[native code]") !== -1;
94 | }
95 |
96 | function _wrapNativeSuper(Class) {
97 | var _cache = typeof Map === "function" ? new Map() : undefined;
98 |
99 | _wrapNativeSuper = function _wrapNativeSuper(Class) {
100 | if (Class === null || !_isNativeFunction(Class)) return Class;
101 |
102 | if (typeof Class !== "function") {
103 | throw new TypeError("Super expression must either be null or a function");
104 | }
105 |
106 | if (typeof _cache !== "undefined") {
107 | if (_cache.has(Class)) return _cache.get(Class);
108 |
109 | _cache.set(Class, Wrapper);
110 | }
111 |
112 | function Wrapper() {
113 | return _construct(Class, arguments, _getPrototypeOf(this).constructor);
114 | }
115 |
116 | Wrapper.prototype = Object.create(Class.prototype, {
117 | constructor: {
118 | value: Wrapper,
119 | enumerable: false,
120 | writable: true,
121 | configurable: true
122 | }
123 | });
124 | return _setPrototypeOf(Wrapper, Class);
125 | };
126 |
127 | return _wrapNativeSuper(Class);
128 | }
129 |
130 | function _assertThisInitialized(self) {
131 | if (self === void 0) {
132 | throw new ReferenceError("this hasn't been initialised - super() hasn't been called");
133 | }
134 |
135 | return self;
136 | }
137 |
138 | function _possibleConstructorReturn(self, call) {
139 | if (call && (typeof call === "object" || typeof call === "function")) {
140 | return call;
141 | }
142 |
143 | return _assertThisInitialized(self);
144 | }
145 |
146 | function _createSuper(Derived) {
147 | var hasNativeReflectConstruct = _isNativeReflectConstruct();
148 |
149 | return function _createSuperInternal() {
150 | var Super = _getPrototypeOf(Derived),
151 | result;
152 |
153 | if (hasNativeReflectConstruct) {
154 | var NewTarget = _getPrototypeOf(this).constructor;
155 |
156 | result = Reflect.construct(Super, arguments, NewTarget);
157 | } else {
158 | result = Super.apply(this, arguments);
159 | }
160 |
161 | return _possibleConstructorReturn(this, result);
162 | };
163 | }
164 |
165 | function _toConsumableArray(arr) {
166 | return _arrayWithoutHoles(arr) || _iterableToArray(arr) || _unsupportedIterableToArray(arr) || _nonIterableSpread();
167 | }
168 |
169 | function _arrayWithoutHoles(arr) {
170 | if (Array.isArray(arr)) return _arrayLikeToArray(arr);
171 | }
172 |
173 | function _iterableToArray(iter) {
174 | if (typeof Symbol !== "undefined" && Symbol.iterator in Object(iter)) return Array.from(iter);
175 | }
176 |
177 | function _unsupportedIterableToArray(o, minLen) {
178 | if (!o) return;
179 | if (typeof o === "string") return _arrayLikeToArray(o, minLen);
180 | var n = Object.prototype.toString.call(o).slice(8, -1);
181 | if (n === "Object" && o.constructor) n = o.constructor.name;
182 | if (n === "Map" || n === "Set") return Array.from(o);
183 | if (n === "Arguments" || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)) return _arrayLikeToArray(o, minLen);
184 | }
185 |
186 | function _arrayLikeToArray(arr, len) {
187 | if (len == null || len > arr.length) len = arr.length;
188 |
189 | for (var i = 0, arr2 = new Array(len); i < len; i++) arr2[i] = arr[i];
190 |
191 | return arr2;
192 | }
193 |
194 | function _nonIterableSpread() {
195 | throw new TypeError("Invalid attempt to spread non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.");
196 | }
197 |
198 | function _createForOfIteratorHelper(o, allowArrayLike) {
199 | var it;
200 |
201 | if (typeof Symbol === "undefined" || o[Symbol.iterator] == null) {
202 | if (Array.isArray(o) || (it = _unsupportedIterableToArray(o)) || allowArrayLike && o && typeof o.length === "number") {
203 | if (it) o = it;
204 | var i = 0;
205 |
206 | var F = function () {};
207 |
208 | return {
209 | s: F,
210 | n: function () {
211 | if (i >= o.length) return {
212 | done: true
213 | };
214 | return {
215 | done: false,
216 | value: o[i++]
217 | };
218 | },
219 | e: function (e) {
220 | throw e;
221 | },
222 | f: F
223 | };
224 | }
225 |
226 | throw new TypeError("Invalid attempt to iterate non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.");
227 | }
228 |
229 | var normalCompletion = true,
230 | didErr = false,
231 | err;
232 | return {
233 | s: function () {
234 | it = o[Symbol.iterator]();
235 | },
236 | n: function () {
237 | var step = it.next();
238 | normalCompletion = step.done;
239 | return step;
240 | },
241 | e: function (e) {
242 | didErr = true;
243 | err = e;
244 | },
245 | f: function () {
246 | try {
247 | if (!normalCompletion && it.return != null) it.return();
248 | } finally {
249 | if (didErr) throw err;
250 | }
251 | }
252 | };
253 | }
254 |
255 | var CepPromiseError = /*#__PURE__*/function (_Error) {
256 | _inherits(CepPromiseError, _Error);
257 |
258 | var _super = _createSuper(CepPromiseError);
259 |
260 | function CepPromiseError() {
261 | var _this;
262 |
263 | var _ref = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {},
264 | message = _ref.message,
265 | type = _ref.type,
266 | errors = _ref.errors;
267 |
268 | _classCallCheck(this, CepPromiseError);
269 |
270 | _this = _super.call(this);
271 | _this.name = 'CepPromiseError';
272 | _this.message = message;
273 | _this.type = type;
274 | _this.errors = errors;
275 | return _this;
276 | }
277 |
278 | return CepPromiseError;
279 | }( /*#__PURE__*/_wrapNativeSuper(Error));
280 |
281 | var ServiceError = /*#__PURE__*/function (_Error) {
282 | _inherits(ServiceError, _Error);
283 |
284 | var _super = _createSuper(ServiceError);
285 |
286 | function ServiceError() {
287 | var _this;
288 |
289 | var _ref = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {},
290 | message = _ref.message,
291 | service = _ref.service;
292 |
293 | _classCallCheck(this, ServiceError);
294 |
295 | _this = _super.call(this);
296 | _this.name = 'ServiceError';
297 | _this.message = message;
298 | _this.service = service;
299 | return _this;
300 | }
301 |
302 | return ServiceError;
303 | }( /*#__PURE__*/_wrapNativeSuper(Error));
304 |
305 | function fetchCorreiosService(cepWithLeftPad, configurations) {
306 | var url = 'https://apps.correios.com.br/SigepMasterJPA/AtendeClienteService/AtendeCliente';
307 | var options = {
308 | method: 'POST',
309 | body: "\n\n \n \n \n ".concat(cepWithLeftPad, "\n \n \n"),
310 | headers: {
311 | 'Content-Type': 'text/xml;charset=UTF-8',
312 | 'cache-control': 'no-cache'
313 | },
314 | timeout: configurations.timeout || 30000
315 | };
316 | return fetch(url, options).then(analyzeAndParseResponse)["catch"](throwApplicationError);
317 | }
318 |
319 | function analyzeAndParseResponse(response) {
320 | if (response.ok) {
321 | return response.text().then(parseSuccessXML).then(extractValuesFromSuccessResponse);
322 | }
323 |
324 | return response.text().then(parseAndextractErrorMessage).then(throwCorreiosError);
325 | }
326 |
327 | function parseSuccessXML(xmlString) {
328 | try {
329 | var _xmlString$replace$ma;
330 |
331 | var returnStatement = (_xmlString$replace$ma = xmlString.replace(/\r?\n|\r/g, '').match(/(.*)<\/return>/)[0]) !== null && _xmlString$replace$ma !== void 0 ? _xmlString$replace$ma : '';
332 | var cleanReturnStatement = returnStatement.replace('', '').replace('', '');
333 | var parsedReturnStatement = cleanReturnStatement.split(/).reduce(function (result, exp) {
334 | var splittenExp = exp.split('>');
335 |
336 | if (splittenExp.length > 1 && splittenExp[1].length) {
337 | result[splittenExp[0]] = splittenExp[1];
338 | }
339 |
340 | return result;
341 | }, {});
342 | return parsedReturnStatement;
343 | } catch (e) {
344 | throw new Error('Não foi possível interpretar o XML de resposta.');
345 | }
346 | }
347 |
348 | function parseAndextractErrorMessage(xmlString) {
349 | try {
350 | var _xmlString$match$;
351 |
352 | var returnStatement = (_xmlString$match$ = xmlString.match(/(.*)<\/faultstring>/)[0]) !== null && _xmlString$match$ !== void 0 ? _xmlString$match$ : '';
353 | var cleanReturnStatement = returnStatement.replace('', '').replace('', '');
354 | return cleanReturnStatement;
355 | } catch (e) {
356 | throw new Error('Não foi possível interpretar o XML de resposta.');
357 | }
358 | }
359 |
360 | function throwCorreiosError(translatedErrorMessage) {
361 | throw new Error(translatedErrorMessage);
362 | }
363 |
364 | function extractValuesFromSuccessResponse(xmlObject) {
365 | return {
366 | cep: xmlObject.cep,
367 | state: xmlObject.uf,
368 | city: xmlObject.cidade,
369 | neighborhood: xmlObject.bairro,
370 | street: xmlObject.end,
371 | service: 'correios'
372 | };
373 | }
374 |
375 | function throwApplicationError(error) {
376 | var serviceError = new ServiceError({
377 | message: error.message,
378 | service: 'correios'
379 | });
380 |
381 | if (error.name === 'FetchError') {
382 | serviceError.message = 'Erro ao se conectar com o serviço dos Correios.';
383 | }
384 |
385 | throw serviceError;
386 | }
387 |
388 | function fetchCorreiosAltAPIService(cepWithLeftPad, configurations) {
389 | var url = 'https://buscacepinter.correios.com.br/app/endereco/carrega-cep-endereco.php';
390 | var options = {
391 | method: 'POST',
392 | mode: 'cors',
393 | headers: {
394 | 'content-type': 'application/x-www-form-urlencoded; charset=UTF-8',
395 | 'Referer': 'https://buscacepinter.correios.com.br/app/endereco/index.php',
396 | 'Referrer-Policy': 'strict-origin-when-cross-origin'
397 | },
398 | body: "endereco=".concat(cepWithLeftPad, "&tipoCEP=ALL"),
399 | timeout: configurations.timeout || 30000
400 | };
401 | return fetch(url, options).then(parseResponse).then(extractCepValuesFromResponse)["catch"](throwApplicationError$1);
402 | }
403 |
404 | function parseResponse(response) {
405 | return response.json().then(function (result) {
406 | if (result.total === 0 || result.erro || result.dados[0].cep === "") {
407 | throw new Error('CEP não encontrado na base dos Correios.');
408 | }
409 |
410 | return result;
411 | });
412 | }
413 |
414 | function extractCepValuesFromResponse(response) {
415 | var firstCep = response.dados[0];
416 | return {
417 | cep: firstCep.cep,
418 | state: firstCep.uf,
419 | city: firstCep.localidade,
420 | neighborhood: firstCep.bairro,
421 | street: firstCep.logradouroDNEC,
422 | service: 'correios-alt'
423 | };
424 | }
425 |
426 | function throwApplicationError$1(error) {
427 | var serviceError = new ServiceError({
428 | message: error.message,
429 | service: 'correios-alt'
430 | });
431 |
432 | if (error.name === 'FetchError') {
433 | serviceError.message = 'Erro ao se conectar com o serviço dos Correios Alt.';
434 | }
435 |
436 | throw serviceError;
437 | }
438 |
439 | function fetchViaCepService(cepWithLeftPad, configurations) {
440 | var url = "https://viacep.com.br/ws/".concat(cepWithLeftPad, "/json/");
441 | var options = {
442 | method: 'GET',
443 | mode: 'cors',
444 | headers: {
445 | 'content-type': 'application/json;charset=utf-8'
446 | },
447 | timeout: configurations.timeout || 30000
448 | };
449 |
450 | if (typeof window == 'undefined') {
451 | options.headers['user-agent'] = 'cep-promise';
452 | }
453 |
454 | return fetch(url, options).then(analyzeAndParseResponse$1).then(checkForViaCepError).then(extractCepValuesFromResponse$1)["catch"](throwApplicationError$2);
455 | }
456 |
457 | function analyzeAndParseResponse$1(response) {
458 | if (response.ok) {
459 | return response.json();
460 | }
461 |
462 | throw Error('Erro ao se conectar com o serviço ViaCEP.');
463 | }
464 |
465 | function checkForViaCepError(responseObject) {
466 | if (responseObject.erro === true) {
467 | throw new Error('CEP não encontrado na base do ViaCEP.');
468 | }
469 |
470 | return responseObject;
471 | }
472 |
473 | function extractCepValuesFromResponse$1(responseObject) {
474 | return {
475 | cep: responseObject.cep.replace('-', ''),
476 | state: responseObject.uf,
477 | city: responseObject.localidade,
478 | neighborhood: responseObject.bairro,
479 | street: responseObject.logradouro,
480 | service: 'viacep'
481 | };
482 | }
483 |
484 | function throwApplicationError$2(error) {
485 | var serviceError = new ServiceError({
486 | message: error.message,
487 | service: 'viacep'
488 | });
489 |
490 | if (error.name === 'FetchError') {
491 | serviceError.message = 'Erro ao se conectar com o serviço ViaCEP.';
492 | }
493 |
494 | throw serviceError;
495 | }
496 |
497 | function fetchWideNetService(cepWithLeftPad, configurations) {
498 | var cepWithDash = "".concat(cepWithLeftPad.slice(0, 5), "-").concat(cepWithLeftPad.slice(5));
499 | var url = "https://cdn.apicep.com/file/apicep/".concat(cepWithDash, ".json");
500 | var options = {
501 | method: 'GET',
502 | mode: 'cors',
503 | headers: {
504 | accept: 'application/json'
505 | },
506 | timeout: configurations.timeout || 30000
507 | };
508 | return fetch(url, options).then(analyzeAndParseResponse$2).then(checkForWideNetError).then(extractCepValuesFromResponse$2)["catch"](throwApplicationError$3);
509 | }
510 |
511 | function analyzeAndParseResponse$2(response) {
512 | if (response.ok) {
513 | return response.json();
514 | }
515 |
516 | throw Error('Erro ao se conectar com o serviço WideNet.');
517 | }
518 |
519 | function checkForWideNetError(object) {
520 | if (object.ok === false || object.status !== 200) {
521 | throw new Error('CEP não encontrado na base do WideNet.');
522 | }
523 |
524 | return object;
525 | }
526 |
527 | function extractCepValuesFromResponse$2(object) {
528 | return {
529 | cep: object.code.replace('-', ''),
530 | state: object.state,
531 | city: object.city,
532 | neighborhood: object.district,
533 | street: object.address,
534 | service: 'widenet'
535 | };
536 | }
537 |
538 | function throwApplicationError$3(error) {
539 | var serviceError = new ServiceError({
540 | message: error.message,
541 | service: 'widenet'
542 | });
543 |
544 | if (error.name === 'FetchError') {
545 | serviceError.message = 'Erro ao se conectar com o serviço WideNet.';
546 | }
547 |
548 | throw serviceError;
549 | }
550 |
551 | function fetchBrasilAPIService(cepWithLeftPad, configurations) {
552 | var url = "https://brasilapi.com.br/api/cep/v1/".concat(cepWithLeftPad);
553 | var options = {
554 | method: 'GET',
555 | mode: 'cors',
556 | headers: {
557 | 'content-type': 'application/json;charset=utf-8'
558 | },
559 | timeout: configurations.timeout || 30000
560 | };
561 | return fetch(url, options).then(parseResponse$1).then(extractCepValuesFromResponse$3)["catch"](throwApplicationError$4);
562 | }
563 |
564 | function parseResponse$1(response) {
565 | if (response.ok === false || response.status !== 200) {
566 | throw new Error('CEP não encontrado na base do BrasilAPI.');
567 | }
568 |
569 | return response.json();
570 | }
571 |
572 | function extractCepValuesFromResponse$3(response) {
573 | return {
574 | cep: response.cep,
575 | state: response.state,
576 | city: response.city,
577 | neighborhood: response.neighborhood,
578 | street: response.street,
579 | service: 'brasilapi'
580 | };
581 | }
582 |
583 | function throwApplicationError$4(error) {
584 | var serviceError = new ServiceError({
585 | message: error.message,
586 | service: 'brasilapi'
587 | });
588 |
589 | if (error.name === 'FetchError') {
590 | serviceError.message = 'Erro ao se conectar com o serviço BrasilAPI.';
591 | }
592 |
593 | throw serviceError;
594 | }
595 |
596 | function getAvailableServices() {
597 | var isBrowser = typeof window !== 'undefined';
598 |
599 | if (isBrowser) {
600 | return {
601 | viacep: fetchViaCepService,
602 | widenet: fetchWideNetService,
603 | brasilapi: fetchBrasilAPIService
604 | };
605 | }
606 |
607 | return {
608 | correios: fetchCorreiosService,
609 | 'correios-alt': fetchCorreiosAltAPIService,
610 | viacep: fetchViaCepService,
611 | widenet: fetchWideNetService,
612 | brasilapi: fetchBrasilAPIService
613 | };
614 | }
615 |
616 | var reverse = function reverse(promise) {
617 | return new Promise(function (resolve, reject) {
618 | return Promise.resolve(promise).then(reject, resolve);
619 | });
620 | };
621 |
622 | Promise.any = function (iterable) {
623 | return reverse(Promise.all(_toConsumableArray(iterable).map(reverse)));
624 | };
625 |
626 | var Promise$1 = Promise;
627 |
628 | var CEP_SIZE = 8;
629 | function cepPromise (cepRawValue) {
630 | var configurations = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
631 | return Promise$1.resolve(cepRawValue).then(validateInputType).then(function (cepRawValue) {
632 | configurations.providers = configurations.providers ? configurations.providers : [];
633 | validateProviders(configurations.providers);
634 | return cepRawValue;
635 | }).then(removeSpecialCharacters).then(validateInputLength).then(leftPadWithZeros).then(function (cepWithLeftPad) {
636 | return fetchCepFromServices(cepWithLeftPad, configurations);
637 | })["catch"](handleServicesError)["catch"](throwApplicationError$5);
638 | }
639 |
640 | function validateProviders(providers) {
641 | var availableProviders = Object.keys(getAvailableServices());
642 |
643 | if (!Array.isArray(providers)) {
644 | throw new CepPromiseError({
645 | message: 'Erro ao inicializar a instância do CepPromise.',
646 | type: 'validation_error',
647 | errors: [{
648 | message: 'O parâmetro providers deve ser uma lista.',
649 | service: 'providers_validation'
650 | }]
651 | });
652 | }
653 |
654 | var _iterator = _createForOfIteratorHelper(providers),
655 | _step;
656 |
657 | try {
658 | for (_iterator.s(); !(_step = _iterator.n()).done;) {
659 | var provider = _step.value;
660 |
661 | if (!availableProviders.includes(provider)) {
662 | throw new CepPromiseError({
663 | message: 'Erro ao inicializar a instância do CepPromise.',
664 | type: 'validation_error',
665 | errors: [{
666 | message: "O provider \"".concat(provider, "\" \xE9 inv\xE1lido. Os providers dispon\xEDveis s\xE3o: [\"").concat(availableProviders.join('", "'), "\"]."),
667 | service: 'providers_validation'
668 | }]
669 | });
670 | }
671 | }
672 | } catch (err) {
673 | _iterator.e(err);
674 | } finally {
675 | _iterator.f();
676 | }
677 | }
678 |
679 | function validateInputType(cepRawValue) {
680 | var cepTypeOf = _typeof(cepRawValue);
681 |
682 | if (cepTypeOf === 'number' || cepTypeOf === 'string') {
683 | return cepRawValue;
684 | }
685 |
686 | throw new CepPromiseError({
687 | message: 'Erro ao inicializar a instância do CepPromise.',
688 | type: 'validation_error',
689 | errors: [{
690 | message: 'Você deve chamar o construtor utilizando uma String ou um Number.',
691 | service: 'cep_validation'
692 | }]
693 | });
694 | }
695 |
696 | function removeSpecialCharacters(cepRawValue) {
697 | return cepRawValue.toString().replace(/\D+/g, '');
698 | }
699 |
700 | function leftPadWithZeros(cepCleanValue) {
701 | return '0'.repeat(CEP_SIZE - cepCleanValue.length) + cepCleanValue;
702 | }
703 |
704 | function validateInputLength(cepWithLeftPad) {
705 | if (cepWithLeftPad.length <= CEP_SIZE) {
706 | return cepWithLeftPad;
707 | }
708 |
709 | throw new CepPromiseError({
710 | message: "CEP deve conter exatamente ".concat(CEP_SIZE, " caracteres."),
711 | type: 'validation_error',
712 | errors: [{
713 | message: "CEP informado possui mais do que ".concat(CEP_SIZE, " caracteres."),
714 | service: 'cep_validation'
715 | }]
716 | });
717 | }
718 |
719 | function fetchCepFromServices(cepWithLeftPad, configurations) {
720 | var providersServices = getAvailableServices();
721 |
722 | if (configurations.providers.length === 0) {
723 | return Promise$1.any(Object.values(providersServices).map(function (provider) {
724 | return provider(cepWithLeftPad, configurations);
725 | }));
726 | }
727 |
728 | return Promise$1.any(configurations.providers.map(function (provider) {
729 | return providersServices[provider](cepWithLeftPad, configurations);
730 | }));
731 | }
732 |
733 | function handleServicesError(aggregatedErrors) {
734 | if (aggregatedErrors.length !== undefined) {
735 | throw new CepPromiseError({
736 | message: 'Todos os serviços de CEP retornaram erro.',
737 | type: 'service_error',
738 | errors: aggregatedErrors
739 | });
740 | }
741 |
742 | throw aggregatedErrors;
743 | }
744 |
745 | function throwApplicationError$5(_ref) {
746 | var message = _ref.message,
747 | type = _ref.type,
748 | errors = _ref.errors;
749 | throw new CepPromiseError({
750 | message: message,
751 | type: type,
752 | errors: errors
753 | });
754 | }
755 |
756 | return cepPromise;
757 |
758 | })));
759 |
--------------------------------------------------------------------------------
/dist/cep-promise.min.js:
--------------------------------------------------------------------------------
1 | !function(e,r){"object"==typeof exports&&"undefined"!=typeof module?module.exports=r(require("node-fetch")):"function"==typeof define&&define.amd?define(["node-fetch"],r):(e=e||self).cep=r(e.fetch)}(this,function(i){"use strict";function t(e){return(t="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(e){return typeof e}:function(e){return e&&"function"==typeof Symbol&&e.constructor===Symbol&&e!==Symbol.prototype?"symbol":typeof e})(e)}function a(e,r){if(!(e instanceof r))throw new TypeError("Cannot call a class as a function")}function e(e,r){if("function"!=typeof r&&null!==r)throw new TypeError("Super expression must either be null or a function");e.prototype=Object.create(r&&r.prototype,{constructor:{value:e,writable:!0,configurable:!0}}),r&&c(e,r)}function n(e){return(n=Object.setPrototypeOf?Object.getPrototypeOf:function(e){return e.__proto__||Object.getPrototypeOf(e)})(e)}function c(e,r){return(c=Object.setPrototypeOf||function(e,r){return e.__proto__=r,e})(e,r)}function s(){if("undefined"==typeof Reflect||!Reflect.construct)return!1;if(Reflect.construct.sham)return!1;if("function"==typeof Proxy)return!0;try{return Date.prototype.toString.call(Reflect.construct(Date,[],function(){})),!0}catch(e){return!1}}function u(e,r,t){return(u=s()?Reflect.construct:function(e,r,t){var o=[null];o.push.apply(o,r);var n=new(Function.bind.apply(e,o));return t&&c(n,t.prototype),n}).apply(null,arguments)}function r(e){var o="function"==typeof Map?new Map:void 0;return(r=function(e){if(null===e||(r=e,-1===Function.toString.call(r).indexOf("[native code]")))return e;var r;if("function"!=typeof e)throw new TypeError("Super expression must either be null or a function");if(void 0!==o){if(o.has(e))return o.get(e);o.set(e,t)}function t(){return u(e,arguments,n(this).constructor)}return t.prototype=Object.create(e.prototype,{constructor:{value:t,enumerable:!1,writable:!0,configurable:!0}}),c(t,e)})(e)}function p(e,r){return!r||"object"!=typeof r&&"function"!=typeof r?function(e){if(void 0===e)throw new ReferenceError("this hasn't been initialised - super() hasn't been called");return e}(e):r}function o(t){var o=s();return function(){var e,r=n(t);return p(this,o?(e=n(this).constructor,Reflect.construct(r,arguments,e)):r.apply(this,arguments))}}function f(e){return function(e){if(Array.isArray(e))return d(e)}(e)||function(e){if("undefined"!=typeof Symbol&&Symbol.iterator in Object(e))return Array.from(e)}(e)||l(e)||function(){throw new TypeError("Invalid attempt to spread non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.")}()}function l(e,r){if(e){if("string"==typeof e)return d(e,r);var t=Object.prototype.toString.call(e).slice(8,-1);return"Object"===t&&e.constructor&&(t=e.constructor.name),"Map"===t||"Set"===t?Array.from(e):"Arguments"===t||/^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(t)?d(e,r):void 0}}function d(e,r){(null==r||r>e.length)&&(r=e.length);for(var t=0,o=new Array(r);t\n\n \n \n \n '.concat(e,"\n \n \n"),headers:{"Content-Type":"text/xml;charset=UTF-8","cache-control":"no-cache"},timeout:r.timeout||3e4};return i("https://apps.correios.com.br/SigepMasterJPA/AtendeClienteService/AtendeCliente",t).then(y).catch(P)}function y(e){return e.ok?e.text().then(b).then(E):e.text().then(g).then(w)}function b(e){try{var r;return(null!==(r=e.replace(/\r?\n|\r/g,"").match(/(.*)<\/return>/)[0])&&void 0!==r?r:"").replace("","").replace("","").split(/).reduce(function(e,r){var t=r.split(">");return 1(.*)<\/faultstring>/)[0])&&void 0!==r?r:"").replace("","").replace("","")}catch(e){throw new Error("Não foi possível interpretar o XML de resposta.")}}function w(e){throw new Error(e)}function E(e){return{cep:e.cep,state:e.uf,city:e.cidade,neighborhood:e.bairro,street:e.end,service:"correios"}}function P(e){var r=new m({message:e.message,service:"correios"});throw"FetchError"===e.name&&(r.message="Erro ao se conectar com o serviço dos Correios."),r}function j(e,r){var t={method:"POST",mode:"cors",headers:{"content-type":"application/x-www-form-urlencoded; charset=UTF-8",Referer:"https://buscacepinter.correios.com.br/app/endereco/index.php","Referrer-Policy":"strict-origin-when-cross-origin"},body:"endereco=".concat(e,"&tipoCEP=ALL"),timeout:r.timeout||3e4};return i("https://buscacepinter.correios.com.br/app/endereco/carrega-cep-endereco.php",t).then(C).then(S).catch(O)}function C(e){return e.json().then(function(e){if(0===e.total||e.erro||""===e.dados[0].cep)throw new Error("CEP não encontrado na base dos Correios.");return e})}function S(e){var r=e.dados[0];return{cep:r.cep,state:r.uf,city:r.localidade,neighborhood:r.bairro,street:r.logradouroDNEC,service:"correios-alt"}}function O(e){var r=new m({message:e.message,service:"correios-alt"});throw"FetchError"===e.name&&(r.message="Erro ao se conectar com o serviço dos Correios Alt."),r}function x(e,r){var t="https://viacep.com.br/ws/".concat(e,"/json/"),o={method:"GET",mode:"cors",headers:{"content-type":"application/json;charset=utf-8"},timeout:r.timeout||3e4};return"undefined"==typeof window&&(o.headers["user-agent"]="cep-promise"),i(t,o).then(A).then(_).then(T).catch(F)}function A(e){if(e.ok)return e.json();throw Error("Erro ao se conectar com o serviço ViaCEP.")}function _(e){if(!0===e.erro)throw new Error("CEP não encontrado na base do ViaCEP.");return e}function T(e){return{cep:e.cep.replace("-",""),state:e.uf,city:e.localidade,neighborhood:e.bairro,street:e.logradouro,service:"viacep"}}function F(e){var r=new m({message:e.message,service:"viacep"});throw"FetchError"===e.name&&(r.message="Erro ao se conectar com o serviço ViaCEP."),r}function R(e,r){var t="".concat(e.slice(0,5),"-").concat(e.slice(5)),o="https://cdn.apicep.com/file/apicep/".concat(t,".json"),n={method:"GET",mode:"cors",headers:{accept:"application/json"},timeout:r.timeout||3e4};return i(o,n).then(I).then(N).then(k).catch(M)}function I(e){if(e.ok)return e.json();throw Error("Erro ao se conectar com o serviço WideNet.")}function N(e){if(!1===e.ok||200!==e.status)throw new Error("CEP não encontrado na base do WideNet.");return e}function k(e){return{cep:e.code.replace("-",""),state:e.state,city:e.city,neighborhood:e.district,street:e.address,service:"widenet"}}function M(e){var r=new m({message:e.message,service:"widenet"});throw"FetchError"===e.name&&(r.message="Erro ao se conectar com o serviço WideNet."),r}function z(e,r){var t="https://brasilapi.com.br/api/cep/v1/".concat(e),o={method:"GET",mode:"cors",headers:{"content-type":"application/json;charset=utf-8"},timeout:r.timeout||3e4};return i(t,o).then(B).then(D).catch(L)}function B(e){if(!1===e.ok||200!==e.status)throw new Error("CEP não encontrado na base do BrasilAPI.");return e.json()}function D(e){return{cep:e.cep,state:e.state,city:e.city,neighborhood:e.neighborhood,street:e.street,service:"brasilapi"}}function L(e){var r=new m({message:e.message,service:"brasilapi"});throw"FetchError"===e.name&&(r.message="Erro ao se conectar com o serviço BrasilAPI."),r}function V(){return"undefined"!=typeof window?{viacep:x,widenet:R,brasilapi:z}:{correios:v,"correios-alt":j,viacep:x,widenet:R,brasilapi:z}}function G(t){return new Promise(function(e,r){return Promise.resolve(t).then(r,e)})}Promise.any=function(e){return G(Promise.all(f(e).map(G)))};var U=Promise,W=8;function q(e){var r=t(e);if("number"===r||"string"===r)return e;throw new h({message:"Erro ao inicializar a instância do CepPromise.",type:"validation_error",errors:[{message:"Você deve chamar o construtor utilizando uma String ou um Number.",service:"cep_validation"}]})}function X(e){return e.toString().replace(/\D+/g,"")}function H(e){return"0".repeat(W-e.length)+e}function J(e){if(e.length<=W)return e;throw new h({message:"CEP deve conter exatamente ".concat(W," caracteres."),type:"validation_error",errors:[{message:"CEP informado possui mais do que ".concat(W," caracteres."),service:"cep_validation"}]})}function $(e){if(void 0!==e.length)throw new h({message:"Todos os serviços de CEP retornaram erro.",type:"service_error",errors:e});throw e}function K(e){var r=e.message,t=e.type,o=e.errors;throw new h({message:r,type:t,errors:o})}return function(e){var n=1=e.length?{done:!0}:{done:!1,value:e[o++]}},e:function(e){throw e},f:n}}throw new TypeError("Invalid attempt to iterate non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.")}var i,c=!0,a=!1;return{s:function(){t=e[Symbol.iterator]()},n:function(){var e=t.next();return c=e.done,e},e:function(e){a=!0,i=e},f:function(){try{c||null==t.return||t.return()}finally{if(a)throw i}}}}(e);try{for(o.s();!(t=o.n()).done;){var n=t.value;if(!r.includes(n))throw new h({message:"Erro ao inicializar a instância do CepPromise.",type:"validation_error",errors:[{message:'O provider "'.concat(n,'" é inválido. Os providers disponíveis são: ["').concat(r.join('", "'),'"].'),service:"providers_validation"}]})}}catch(e){o.e(e)}finally{o.f()}}(n.providers),e}).then(X).then(J).then(H).then(function(e){return r=e,t=n,o=V(),0!==t.providers.length?U.any(t.providers.map(function(e){return o[e](r,t)})):U.any(Object.values(o).map(function(e){return e(r,t)}));var r,t,o}).catch($).catch(K)}});
--------------------------------------------------------------------------------
/index.d.ts:
--------------------------------------------------------------------------------
1 | declare module "cep-promise" {
2 | /** Represents the result of a CEP search */
3 | export interface CEP {
4 | /** The retrieved CEP number */
5 | cep: string;
6 | /** The state associated with the CEP */
7 | state: string;
8 | /** The city associated with the CEP */
9 | city: string;
10 | /** The street associated with the CEP */
11 | street: string;
12 | /** The neighborhood associated with the CEP */
13 | neighborhood: string;
14 | /** The provider which returned the result */
15 | service: string;
16 | }
17 |
18 | /**
19 | * Available providers:
20 | *
21 | * | Provider | Browser | Node.js |
22 | * | ------------ | ------- | ------- |
23 | * | brasilapi | ✅ | ✅ |
24 | * | viacep | ✅ | ✅ |
25 | * | widenet | ✅ | ✅ |
26 | * | correios | ❌ | ✅ |
27 | * | correios-alt | ❌ | ✅ |
28 | */
29 | export const AvailableProviders: {
30 | /** Supported in both **Node.js** and **Browser** environments. */
31 | readonly brasilapi: "brasilapi";
32 | /** Supported in both **Node.js** and **Browser** environments. */
33 | readonly viacep: "viacep";
34 | /** Supported in both **Node.js** and **Browser** environments. */
35 | readonly widenet: "widenet";
36 | /** Supported only in **Node.js** environment. */
37 | readonly correios: "correios";
38 | /** Supported only in **Node.js** environment. */
39 | readonly correiosAlt: "correios-alt";
40 | };
41 |
42 | /** Configuration options to customize the CEP search, by selecting specific providers and/or setting a timeout */
43 | export interface Configurations {
44 | /** Specifies the providers to be used for CEP searches, otherwise all available providers will be used.
45 | *
46 | * ---
47 | *
48 | * Available providers:
49 | *
50 | * | Provider | Browser | Node.js |
51 | * | ------------ | ------- | ------- |
52 | * | brasilapi | ✅ | ✅ |
53 | * | viacep | ✅ | ✅ |
54 | * | widenet | ✅ | ✅ |
55 | * | correios | ❌ | ✅ |
56 | * | correios-alt | ❌ | ✅ |
57 | */
58 | providers?: (typeof AvailableProviders)[keyof typeof AvailableProviders][];
59 | /** Timeout (in milliseconds) after which the CEP search will be cancelled. */
60 | timeout?: number;
61 | }
62 |
63 | /**
64 | * Searches for CEP directly integrated with the services of Correios, ViaCEP, and WideNet (Node.js and Browser).
65 | *
66 | * ---
67 | *
68 | * @param cep The CEP (postal code) to search for.
69 | * @param configurations Optional configurations to customize the CEP search.
70 | * @returns A promise that resolves with the CEP details.
71 | */
72 | export function cep(
73 | cep: string | number,
74 | configurations?: Configurations
75 | ): Promise;
76 |
77 | export default cep;
78 | }
79 |
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "cep-promise",
3 | "version": "4.4.1",
4 | "description": "Busca por CEP integrado diretamente aos serviços dos Correios e ViaCEP",
5 | "main": "dist/cep-promise.min.js",
6 | "module": "dist/cep-promise.min.js",
7 | "types": "./index.d.ts",
8 | "scripts": {
9 | "dev": "nodemon --watch src/ --exec \"npm run build\"",
10 | "test": "npm run coverage",
11 | "coverage": "babel-node node_modules/.bin/babel-istanbul cover _mocha -- test/**/*.spec.js",
12 | "test-unit": "mocha test/unit/**/*.spec.js",
13 | "test-unit-watch": "mocha --watch test/unit/**/*.spec.js",
14 | "test-e2e": "mocha test/e2e/**/*.spec.js",
15 | "test-e2e-watch": "mocha --watch test/e2e/**/*.spec.js",
16 | "lint-check": "standard",
17 | "lint-fix": "standard --fix",
18 | "build-browser": "rollup -c && uglifyjs dist/cep-promise-browser.js -cm -o dist/cep-promise-browser.min.js",
19 | "build-node": "rollup -c && uglifyjs dist/cep-promise.js -cm -o dist/cep-promise.min.js",
20 | "build": "npm run build-browser && npm run build-node",
21 | "prepublishOnly": "npm run build"
22 | },
23 | "browser": "dist/cep-promise-browser.min.js",
24 | "repository": {
25 | "type": "git",
26 | "url": "https://github.com/BrasilAPI/cep-promise.git"
27 | },
28 | "author": "Filipe Deschamps",
29 | "license": "MIT",
30 | "bugs": {
31 | "url": "https://github.com/BrasilAPI/cep-promise/issues"
32 | },
33 | "keywords": [
34 | "cep",
35 | "correios",
36 | "zipcode",
37 | "zip",
38 | "promise",
39 | "viacep",
40 | "brasilapi",
41 | "widenet",
42 | "apicep"
43 | ],
44 | "homepage": "https://github.com/BrasilAPI/cep-promise",
45 | "devDependencies": {
46 | "@babel/cli": "7.10.5",
47 | "@babel/core": "7.11.1",
48 | "@babel/node": "7.10.5",
49 | "@babel/plugin-transform-runtime": "^7.11.0",
50 | "@babel/preset-env": "7.11.0",
51 | "@babel/register": "7.10.5",
52 | "babel-core": "7.0.0-bridge.0",
53 | "babel-eslint": "10.1.0",
54 | "babel-istanbul": "0.12.2",
55 | "chai": "4.2.0",
56 | "chai-as-promised": "7.1.1",
57 | "chai-subset": "1.6.0",
58 | "mocha": "8.1.1",
59 | "nock": "13.0.2",
60 | "nodemon": "2.0.4",
61 | "rollup": "2.20.0",
62 | "rollup-plugin-babel": "4.4.0",
63 | "rollup-plugin-commonjs": "10.1.0",
64 | "rollup-plugin-node-resolve": "5.2.0",
65 | "rollup-plugin-replace": "2.2.0",
66 | "standard": "14.3.4",
67 | "uglify-js": "3.10.0"
68 | },
69 | "standard": {
70 | "parser": "babel-eslint",
71 | "globals": [
72 | "describe",
73 | "it",
74 | "afterEach"
75 | ]
76 | },
77 | "dependencies": {
78 | "node-fetch": "2.6.7",
79 | "unfetch": "4.1.0"
80 | },
81 | "files": [
82 | "dist",
83 | "index.d.ts"
84 | ]
85 | }
86 |
--------------------------------------------------------------------------------
/rollup.config.js:
--------------------------------------------------------------------------------
1 | import babel from 'rollup-plugin-babel'
2 | import commonjs from 'rollup-plugin-commonjs'
3 | import resolve from 'rollup-plugin-node-resolve'
4 | import replace from 'rollup-plugin-replace'
5 |
6 | const input = 'src/cep-promise.js'
7 | const defaultPlugins = [
8 | babel({
9 | babelrc: false,
10 | presets: [['@babel/preset-env', { modules: false }]]
11 | })
12 | ]
13 |
14 | export default [
15 | {
16 | input,
17 | plugins: [].concat(defaultPlugins, [
18 | commonjs()
19 | ]),
20 | output: {
21 | file: 'dist/cep-promise.js',
22 | format: 'umd',
23 | name: 'cep'
24 | }
25 | },
26 | {
27 | input,
28 | plugins: [
29 | replace({
30 | 'node-fetch': 'unfetch',
31 | })
32 | ].concat(defaultPlugins, [
33 | resolve({
34 | browser: true
35 | }),
36 | commonjs()
37 | ]),
38 | context: 'window',
39 | output: {
40 | file: 'dist/cep-promise-browser.js',
41 | format: 'umd',
42 | name: 'cep'
43 | }
44 | }
45 | ]
46 |
47 |
--------------------------------------------------------------------------------
/src/cep-promise.js:
--------------------------------------------------------------------------------
1 | 'use strict'
2 |
3 | import CepPromiseError from './errors/cep-promise.js'
4 | import { getAvailableServices } from './services/index.js'
5 | import Promise from './utils/promise-any.js'
6 |
7 | const CEP_SIZE = 8
8 |
9 | export default function (cepRawValue, configurations = {}) {
10 | return Promise.resolve(cepRawValue)
11 | .then(validateInputType)
12 | .then(cepRawValue => {
13 | configurations.providers = configurations.providers ? configurations.providers : []
14 | validateProviders(configurations.providers)
15 |
16 | return cepRawValue
17 | })
18 | .then(removeSpecialCharacters)
19 | .then(validateInputLength)
20 | .then(leftPadWithZeros)
21 | .then((cepWithLeftPad) => {
22 | return fetchCepFromServices(cepWithLeftPad, configurations)
23 | })
24 | .catch(handleServicesError)
25 | .catch(throwApplicationError)
26 | }
27 |
28 | function validateProviders (providers) {
29 | const availableProviders = Object.keys(getAvailableServices())
30 |
31 | if (!Array.isArray(providers)) {
32 | throw new CepPromiseError({
33 | message: 'Erro ao inicializar a instância do CepPromise.',
34 | type: 'validation_error',
35 | errors: [
36 | {
37 | message:
38 | 'O parâmetro providers deve ser uma lista.',
39 | service: 'providers_validation'
40 | }
41 | ]
42 | })
43 | }
44 |
45 | for (const provider of providers) {
46 | if (!availableProviders.includes(provider)) {
47 | throw new CepPromiseError({
48 | message: 'Erro ao inicializar a instância do CepPromise.',
49 | type: 'validation_error',
50 | errors: [
51 | {
52 | message:
53 | `O provider "${provider}" é inválido. Os providers disponíveis são: ["${availableProviders.join('", "')}"].`,
54 | service: 'providers_validation'
55 | }
56 | ]
57 | })
58 | }
59 | }
60 | }
61 |
62 | function validateInputType (cepRawValue) {
63 | const cepTypeOf = typeof cepRawValue
64 |
65 | if (cepTypeOf === 'number' || cepTypeOf === 'string') {
66 | return cepRawValue
67 | }
68 |
69 | throw new CepPromiseError({
70 | message: 'Erro ao inicializar a instância do CepPromise.',
71 | type: 'validation_error',
72 | errors: [
73 | {
74 | message:
75 | 'Você deve chamar o construtor utilizando uma String ou um Number.',
76 | service: 'cep_validation'
77 | }
78 | ]
79 | })
80 | }
81 |
82 | function removeSpecialCharacters (cepRawValue) {
83 | return cepRawValue.toString().replace(/\D+/g, '')
84 | }
85 |
86 | function leftPadWithZeros (cepCleanValue) {
87 | return '0'.repeat(CEP_SIZE - cepCleanValue.length) + cepCleanValue
88 | }
89 |
90 | function validateInputLength (cepWithLeftPad) {
91 | if (cepWithLeftPad.length <= CEP_SIZE) {
92 | return cepWithLeftPad
93 | }
94 |
95 | throw new CepPromiseError({
96 | message: `CEP deve conter exatamente ${CEP_SIZE} caracteres.`,
97 | type: 'validation_error',
98 | errors: [
99 | {
100 | message: `CEP informado possui mais do que ${CEP_SIZE} caracteres.`,
101 | service: 'cep_validation'
102 | }
103 | ]
104 | })
105 | }
106 |
107 | function fetchCepFromServices (cepWithLeftPad, configurations) {
108 | const providersServices = getAvailableServices()
109 |
110 | if (configurations.providers.length === 0) {
111 | return Promise.any(
112 | Object.values(providersServices).map(provider => provider(cepWithLeftPad, configurations))
113 | )
114 | }
115 |
116 | return Promise.any(
117 | configurations.providers.map(provider => {
118 | return providersServices[provider](cepWithLeftPad, configurations)
119 | })
120 | )
121 | }
122 |
123 | function handleServicesError (aggregatedErrors) {
124 | if (aggregatedErrors.length !== undefined) {
125 | throw new CepPromiseError({
126 | message: 'Todos os serviços de CEP retornaram erro.',
127 | type: 'service_error',
128 | errors: aggregatedErrors
129 | })
130 | }
131 | throw aggregatedErrors
132 | }
133 |
134 | function throwApplicationError ({ message, type, errors }) {
135 | throw new CepPromiseError({ message, type, errors })
136 | }
137 |
--------------------------------------------------------------------------------
/src/errors/cep-promise.js:
--------------------------------------------------------------------------------
1 | class CepPromiseError extends Error {
2 | constructor ({ message, type, errors } = {}) {
3 | super()
4 |
5 | this.name = 'CepPromiseError'
6 | this.message = message
7 | this.type = type
8 | this.errors = errors
9 | }
10 | }
11 |
12 | export default CepPromiseError
13 |
--------------------------------------------------------------------------------
/src/errors/service.js:
--------------------------------------------------------------------------------
1 | class ServiceError extends Error {
2 | constructor ({ message, service } = {}) {
3 | super()
4 |
5 | this.name = 'ServiceError'
6 | this.message = message
7 | this.service = service
8 | }
9 | }
10 |
11 | export default ServiceError
12 |
--------------------------------------------------------------------------------
/src/services/brasilapi.js:
--------------------------------------------------------------------------------
1 | 'use strict'
2 |
3 | import fetch from 'node-fetch'
4 | import ServiceError from '../errors/service.js'
5 |
6 | export default function fetchBrasilAPIService (cepWithLeftPad, configurations) {
7 | const url = `https://brasilapi.com.br/api/cep/v1/${cepWithLeftPad}`
8 | const options = {
9 | method: 'GET',
10 | mode: 'cors',
11 | headers: {
12 | 'content-type': 'application/json;charset=utf-8'
13 | },
14 | timeout: configurations.timeout || 30000
15 | }
16 |
17 | return fetch(url, options)
18 | .then(parseResponse)
19 | .then(extractCepValuesFromResponse)
20 | .catch(throwApplicationError)
21 | }
22 |
23 | function parseResponse (response) {
24 | if (response.ok === false || response.status !== 200) {
25 | throw new Error('CEP não encontrado na base do BrasilAPI.')
26 | }
27 |
28 | return response.json()
29 | }
30 |
31 | function extractCepValuesFromResponse (response) {
32 | return {
33 | cep: response.cep,
34 | state: response.state,
35 | city: response.city,
36 | neighborhood: response.neighborhood,
37 | street: response.street,
38 | service: 'brasilapi'
39 | }
40 | }
41 |
42 | function throwApplicationError (error) {
43 | const serviceError = new ServiceError({
44 | message: error.message,
45 | service: 'brasilapi'
46 | })
47 |
48 | if (error.name === 'FetchError') {
49 | serviceError.message = 'Erro ao se conectar com o serviço BrasilAPI.'
50 | }
51 |
52 | throw serviceError
53 | }
54 |
--------------------------------------------------------------------------------
/src/services/correios-alt.js:
--------------------------------------------------------------------------------
1 | 'use strict'
2 |
3 | import fetch from 'node-fetch'
4 | import ServiceError from '../errors/service.js'
5 |
6 | export default function fetchCorreiosAltAPIService(
7 | cepWithLeftPad,
8 | configurations
9 | ) {
10 | const url = 'https://buscacepinter.correios.com.br/app/endereco/carrega-cep-endereco.php'
11 | const options = {
12 | method: 'POST',
13 | mode: 'cors',
14 | headers: {
15 | 'content-type': 'application/x-www-form-urlencoded; charset=UTF-8',
16 | 'Referer': 'https://buscacepinter.correios.com.br/app/endereco/index.php',
17 | 'Referrer-Policy': 'strict-origin-when-cross-origin'
18 | },
19 | body: `endereco=${cepWithLeftPad}&tipoCEP=ALL`,
20 | timeout: configurations.timeout || 30000
21 | }
22 |
23 | return fetch(url, options)
24 | .then(parseResponse)
25 | .then(extractCepValuesFromResponse)
26 | .catch(throwApplicationError)
27 | }
28 |
29 | function parseResponse(response) {
30 | return response.json().then(result => {
31 | if (result.total === 0 || result.erro || result.dados[0].cep === "") {
32 | throw new Error('CEP não encontrado na base dos Correios.')
33 | }
34 | return result
35 | })
36 | }
37 |
38 | function extractCepValuesFromResponse(response) {
39 | const firstCep = response.dados[0]
40 | return {
41 | cep: firstCep.cep,
42 | state: firstCep.uf,
43 | city: firstCep.localidade,
44 | neighborhood: firstCep.bairro,
45 | street: firstCep.logradouroDNEC,
46 | service: 'correios-alt'
47 | }
48 | }
49 |
50 | function throwApplicationError(error) {
51 | const serviceError = new ServiceError({
52 | message: error.message,
53 | service: 'correios-alt'
54 | })
55 |
56 | if (error.name === 'FetchError') {
57 | serviceError.message = 'Erro ao se conectar com o serviço dos Correios Alt.'
58 | }
59 |
60 | throw serviceError
61 | }
62 |
--------------------------------------------------------------------------------
/src/services/correios.js:
--------------------------------------------------------------------------------
1 | 'use strict'
2 |
3 | import fetch from 'node-fetch'
4 | import ServiceError from '../errors/service.js'
5 |
6 | export default function fetchCorreiosService (cepWithLeftPad, configurations) {
7 | const url = 'https://apps.correios.com.br/SigepMasterJPA/AtendeClienteService/AtendeCliente'
8 | const options = {
9 | method: 'POST',
10 | body: `\n\n \n \n \n ${cepWithLeftPad}\n \n \n`,
11 | headers: {
12 | 'Content-Type': 'text/xml;charset=UTF-8',
13 | 'cache-control': 'no-cache'
14 | },
15 | timeout: configurations.timeout || 30000
16 | }
17 |
18 | return fetch(url, options)
19 | .then(analyzeAndParseResponse)
20 | .catch(throwApplicationError)
21 | }
22 |
23 | function analyzeAndParseResponse (response) {
24 | if (response.ok) {
25 | return response.text()
26 | .then(parseSuccessXML)
27 | .then(extractValuesFromSuccessResponse)
28 | }
29 |
30 | return response.text()
31 | .then(parseAndextractErrorMessage)
32 | .then(throwCorreiosError)
33 | }
34 |
35 | function parseSuccessXML (xmlString) {
36 | try {
37 | const returnStatement = xmlString.replace(/\r?\n|\r/g, '').match(/(.*)<\/return>/)[0] ?? ''
38 | const cleanReturnStatement = returnStatement.replace('', '').replace('', '')
39 | const parsedReturnStatement = cleanReturnStatement
40 | .split(/)
41 | .reduce((result, exp) => {
42 | const splittenExp = exp.split('>')
43 | if (splittenExp.length > 1 && splittenExp[1].length) {
44 | result[splittenExp[0]] = splittenExp[1]
45 | }
46 | return result
47 | }, {})
48 |
49 | return parsedReturnStatement
50 | } catch (e) {
51 | throw new Error('Não foi possível interpretar o XML de resposta.')
52 | }
53 | }
54 |
55 | function parseAndextractErrorMessage (xmlString) {
56 | try {
57 | const returnStatement = xmlString.match(/(.*)<\/faultstring>/)[0] ?? ''
58 | const cleanReturnStatement = returnStatement.replace('', '').replace('', '')
59 | return cleanReturnStatement
60 | } catch (e) {
61 | throw new Error('Não foi possível interpretar o XML de resposta.')
62 | }
63 | }
64 |
65 | function throwCorreiosError (translatedErrorMessage) {
66 | throw new Error(translatedErrorMessage)
67 | }
68 |
69 | function extractValuesFromSuccessResponse (xmlObject) {
70 | return {
71 | cep: xmlObject.cep,
72 | state: xmlObject.uf,
73 | city: xmlObject.cidade,
74 | neighborhood: xmlObject.bairro,
75 | street: xmlObject.end,
76 | service: 'correios'
77 | }
78 | }
79 |
80 | function throwApplicationError (error) {
81 | const serviceError = new ServiceError({
82 | message: error.message,
83 | service: 'correios'
84 | })
85 |
86 | if (error.name === 'FetchError') {
87 | serviceError.message = 'Erro ao se conectar com o serviço dos Correios.'
88 | }
89 |
90 | throw serviceError
91 | }
92 |
--------------------------------------------------------------------------------
/src/services/index.js:
--------------------------------------------------------------------------------
1 | import Correios from './correios'
2 | import CorreiosAlt from './correios-alt'
3 | import ViaCep from './viacep'
4 | import WideNet from './widenet'
5 | import BrasilAPI from './brasilapi.js'
6 |
7 | export function getAvailableServices () {
8 | const isBrowser = typeof window !== 'undefined'
9 |
10 | if (isBrowser) {
11 | return {
12 | viacep: ViaCep,
13 | widenet: WideNet,
14 | brasilapi: BrasilAPI
15 | }
16 | }
17 |
18 | return {
19 | correios: Correios,
20 | 'correios-alt': CorreiosAlt,
21 | viacep: ViaCep,
22 | widenet: WideNet,
23 | brasilapi: BrasilAPI
24 | }
25 | }
26 |
--------------------------------------------------------------------------------
/src/services/viacep.js:
--------------------------------------------------------------------------------
1 | 'use strict'
2 |
3 | import fetch from 'node-fetch'
4 | import ServiceError from '../errors/service.js'
5 |
6 | export default function fetchViaCepService (cepWithLeftPad, configurations) {
7 | const url = `https://viacep.com.br/ws/${cepWithLeftPad}/json/`
8 | const options = {
9 | method: 'GET',
10 | mode: 'cors',
11 | headers: {
12 | 'content-type': 'application/json;charset=utf-8'
13 | },
14 | timeout: configurations.timeout || 30000
15 | }
16 |
17 | if (typeof window == 'undefined') {
18 | options.headers['user-agent'] = 'cep-promise'
19 | }
20 |
21 | return fetch(url, options)
22 | .then(analyzeAndParseResponse)
23 | .then(checkForViaCepError)
24 | .then(extractCepValuesFromResponse)
25 | .catch(throwApplicationError)
26 | }
27 |
28 | function analyzeAndParseResponse (response) {
29 | if (response.ok) {
30 | return response.json()
31 | }
32 |
33 | throw Error('Erro ao se conectar com o serviço ViaCEP.')
34 | }
35 |
36 | function checkForViaCepError (responseObject) {
37 | if (responseObject.erro === true) {
38 | throw new Error('CEP não encontrado na base do ViaCEP.')
39 | }
40 |
41 | return responseObject
42 | }
43 |
44 | function extractCepValuesFromResponse (responseObject) {
45 | return {
46 | cep: responseObject.cep.replace('-', ''),
47 | state: responseObject.uf,
48 | city: responseObject.localidade,
49 | neighborhood: responseObject.bairro,
50 | street: responseObject.logradouro,
51 | service: 'viacep'
52 | }
53 | }
54 |
55 | function throwApplicationError (error) {
56 | const serviceError = new ServiceError({
57 | message: error.message,
58 | service: 'viacep'
59 | })
60 |
61 | if (error.name === 'FetchError') {
62 | serviceError.message = 'Erro ao se conectar com o serviço ViaCEP.'
63 | }
64 |
65 | throw serviceError
66 | }
67 |
--------------------------------------------------------------------------------
/src/services/widenet.js:
--------------------------------------------------------------------------------
1 | 'use strict'
2 |
3 | import fetch from 'node-fetch'
4 | import ServiceError from '../errors/service.js'
5 |
6 | export default function fetchWideNetService(cepWithLeftPad, configurations) {
7 | const cepWithDash = `${cepWithLeftPad.slice(0, 5)}-${cepWithLeftPad.slice(5)}`
8 | const url = `https://cdn.apicep.com/file/apicep/${cepWithDash}.json`
9 | const options = {
10 | method: 'GET',
11 | mode: 'cors',
12 | headers: {
13 | accept: 'application/json'
14 | },
15 | timeout: configurations.timeout || 30000
16 | }
17 |
18 | return fetch(url, options)
19 | .then(analyzeAndParseResponse)
20 | .then(checkForWideNetError)
21 | .then(extractCepValuesFromResponse)
22 | .catch(throwApplicationError)
23 | }
24 |
25 | function analyzeAndParseResponse(response) {
26 | if (response.ok) {
27 | return response.json()
28 | }
29 |
30 | throw Error('Erro ao se conectar com o serviço WideNet.')
31 | }
32 |
33 | function checkForWideNetError(object) {
34 | if (object.ok === false || object.status !== 200) {
35 | throw new Error('CEP não encontrado na base do WideNet.')
36 | }
37 |
38 | return object
39 | }
40 |
41 | function extractCepValuesFromResponse(object) {
42 | return {
43 | cep: object.code.replace('-', ''),
44 | state: object.state,
45 | city: object.city,
46 | neighborhood: object.district,
47 | street: object.address,
48 | service: 'widenet'
49 | }
50 | }
51 |
52 | function throwApplicationError(error) {
53 | const serviceError = new ServiceError({
54 | message: error.message,
55 | service: 'widenet'
56 | })
57 |
58 | if (error.name === 'FetchError') {
59 | serviceError.message = 'Erro ao se conectar com o serviço WideNet.'
60 | }
61 |
62 | throw serviceError
63 | }
64 |
--------------------------------------------------------------------------------
/src/utils/promise-any.js:
--------------------------------------------------------------------------------
1 | 'use strict'
2 |
3 | const reverse = (promise) => new Promise((resolve, reject) => Promise.resolve(promise).then(reject, resolve))
4 |
5 | Promise.any = (iterable) => reverse(Promise.all([...iterable].map(reverse)))
6 |
7 | export default Promise
8 |
--------------------------------------------------------------------------------
/test/e2e/cep-promise.spec.js:
--------------------------------------------------------------------------------
1 | 'use strict'
2 |
3 | import chai from 'chai'
4 | import chaiAsPromised from 'chai-as-promised'
5 | import chaiSubset from 'chai-subset'
6 | import nock from 'nock'
7 |
8 | import cep from '../../src/cep-promise.js'
9 | import CepPromiseError from '../../src/errors/cep-promise.js'
10 |
11 | chai.use(chaiAsPromised)
12 | chai.use(chaiSubset)
13 |
14 | let expect = chai.expect
15 |
16 | describe('[e2e] cep-promise', () => {
17 | before(() => {
18 | nock.enableNetConnect()
19 | })
20 |
21 | describe('when invoked with a valid "05010000" string', () => {
22 | it('should fulfill with correct address', () => cep('05010000')
23 | .then(address => {
24 | expect(address).to.deep.equal({
25 | cep: '05010000',
26 | state: 'SP',
27 | city: 'São Paulo',
28 | neighborhood: 'Perdizes',
29 | street: 'Rua Caiubi',
30 | service: address.service
31 | })})
32 | )
33 | })
34 |
35 | describe('when invoked with a valid 05010000 number', () => {
36 | it('should fulfill with correct address', async () => {
37 | const address = await cep(5010000)
38 |
39 | expect(address).to.deep.equal({
40 | cep: '05010000',
41 | state: 'SP',
42 | city: 'São Paulo',
43 | neighborhood: 'Perdizes',
44 | street: 'Rua Caiubi',
45 | service: address.service
46 | })
47 | })
48 | })
49 |
50 | describe('when invoked with an inexistent "99999999" CEP', () => {
51 | it('should reject with "service_error"', () => {
52 | return cep('99999999').catch(error => {
53 | return expect(error)
54 | .to.be.an.instanceOf(CepPromiseError)
55 | .and.containSubset({
56 | name: 'CepPromiseError',
57 | message: 'Todos os serviços de CEP retornaram erro.',
58 | type: 'service_error',
59 | errors: [
60 | {
61 | message: 'CEP INVÁLIDO',
62 | service: 'correios'
63 | },
64 | {
65 | message: 'Erro ao se conectar com o serviço dos Correios Alt.',
66 | service: 'correios-alt'
67 | },
68 | {
69 | message: 'CEP não encontrado na base do ViaCEP.',
70 | service: 'viacep'
71 | },
72 | {
73 | service: 'widenet'
74 | },
75 | {
76 | name: 'ServiceError',
77 | message: 'CEP não encontrado na base do BrasilAPI.',
78 | service: 'brasilapi'
79 | }
80 | ]
81 | })
82 | })
83 | })
84 | })
85 |
86 | describe('when invoked with an invalid "123456789" CEP', () => {
87 | it('should reject with "validation_error"', () => {
88 | return cep('123456789').catch(error => {
89 | return expect(error)
90 | .to.be.an.instanceOf(CepPromiseError)
91 | .and.containSubset({
92 | name: 'CepPromiseError',
93 | message: 'CEP deve conter exatamente 8 caracteres.',
94 | type: 'validation_error',
95 | errors: [
96 | {
97 | service: 'cep_validation',
98 | message: 'CEP informado possui mais do que 8 caracteres.'
99 | }
100 | ]
101 | })
102 | })
103 | })
104 | })
105 | })
106 |
--------------------------------------------------------------------------------
/test/unit/cep-promise-browser.spec.js:
--------------------------------------------------------------------------------
1 | 'use strict'
2 |
3 | import chai from 'chai'
4 | import chaiAsPromised from 'chai-as-promised'
5 | import chaiSubset from 'chai-subset'
6 | import nock from 'nock'
7 | import path from 'path'
8 |
9 | import cep from '../../src/cep-promise.js'
10 | import CepPromiseError from '../../src/errors/cep-promise.js'
11 |
12 | chai.use(chaiAsPromised)
13 | chai.use(chaiSubset)
14 |
15 | let expect = chai.expect
16 |
17 | describe('[unit] cep-promise for browser', () => {
18 | before(() => {
19 | // Mock browser behavior
20 | global.window = {}
21 | nock.disableNetConnect()
22 | })
23 |
24 | describe('when imported', () => {
25 | it('should return a Function', () => {
26 | expect(cep).to.be.a('function')
27 | })
28 | })
29 |
30 | describe('when invoked', () => {
31 | it('should return a Promise', () => {
32 | nock('https://viacep.com.br')
33 | .get('/ws/05010000/json/')
34 | .replyWithFile(
35 | 200,
36 | path.join(__dirname, '/fixtures/viacep-cep-05010000-found.json')
37 | )
38 |
39 | nock('https://cdn.apicep.com')
40 | .get('/file/apicep/05010-000.json')
41 | .replyWithFile(
42 | 200,
43 | path.join(__dirname, '/fixtures/widenet-cep-05010000-found.json')
44 | )
45 |
46 | nock('https://brasilapi.com.br/')
47 | .get('/api/cep/v1/05010000')
48 | .replyWithFile(
49 | 200,
50 | path.join(__dirname, '/fixtures/brasilapi-cep-05010000-found.json')
51 | )
52 |
53 | const cepPromise = cep('05010000')
54 | expect(cepPromise.then).to.be.a('function')
55 | expect(cepPromise.catch).to.be.a('function')
56 | })
57 | })
58 |
59 | describe('when invoked without arguments', () => {
60 | it('should reject with "validation_error"', () => {
61 | return cep().catch(error => {
62 | return expect(error)
63 | .to.be.an.instanceOf(CepPromiseError)
64 | .and.containSubset({
65 | name: 'CepPromiseError',
66 | message: 'Erro ao inicializar a instância do CepPromise.',
67 | type: 'validation_error',
68 | errors: [
69 | {
70 | message:
71 | 'Você deve chamar o construtor utilizando uma String ou um Number.',
72 | service: 'cep_validation'
73 | }
74 | ]
75 | })
76 | })
77 | })
78 | })
79 |
80 | describe('when invoked with an Array', () => {
81 | it('should reject with "validation_error"', () => {
82 | return cep([1, 2, 3]).catch(error => {
83 | return expect(error)
84 | .to.be.an.instanceOf(CepPromiseError)
85 | .and.containSubset({
86 | name: 'CepPromiseError',
87 | message: 'Erro ao inicializar a instância do CepPromise.',
88 | type: 'validation_error',
89 | errors: [
90 | {
91 | message:
92 | 'Você deve chamar o construtor utilizando uma String ou um Number.',
93 | service: 'cep_validation'
94 | }
95 | ]
96 | })
97 | })
98 | })
99 | })
100 |
101 | describe('when invoked with an Object', () => {
102 | it('should reject with "validation_error"', () => {
103 | return cep({ nintendo: true, ps: false, xbox: false }).catch(error => {
104 | return expect(error)
105 | .to.be.an.instanceOf(CepPromiseError)
106 | .and.containSubset({
107 | name: 'CepPromiseError',
108 | message: 'Erro ao inicializar a instância do CepPromise.',
109 | type: 'validation_error',
110 | errors: [
111 | {
112 | message:
113 | 'Você deve chamar o construtor utilizando uma String ou um Number.',
114 | service: 'cep_validation'
115 | }
116 | ]
117 | })
118 | })
119 | })
120 | })
121 |
122 | describe('when invoked with an Function', () => {
123 | it('should reject with "validation_error"', () => {
124 | return cep(function zelda() {
125 | return 'link'
126 | }).catch(error => {
127 | return expect(error)
128 | .to.be.an.instanceOf(CepPromiseError)
129 | .and.containSubset({
130 | name: 'CepPromiseError',
131 | message: 'Erro ao inicializar a instância do CepPromise.',
132 | type: 'validation_error',
133 | errors: [
134 | {
135 | message:
136 | 'Você deve chamar o construtor utilizando uma String ou um Number.',
137 | service: 'cep_validation'
138 | }
139 | ]
140 | })
141 | })
142 | })
143 | })
144 |
145 | describe('when invoked with a valid "05010000" String', () => {
146 | it('should fulfill with correct address', () => {
147 | nock('https://viacep.com.br')
148 | .get('/ws/05010000/json/')
149 | .replyWithFile(
150 | 200,
151 | path.join(__dirname, '/fixtures/viacep-cep-05010000-found.json')
152 | )
153 |
154 | nock('https://cdn.apicep.com')
155 | .get('/file/apicep/05010-000.json')
156 | .replyWithFile(
157 | 200,
158 | path.join(__dirname, '/fixtures/widenet-cep-05010000-found.json')
159 | )
160 |
161 | nock('https://brasilapi.com.br/')
162 | .get('/api/cep/v1/05010000')
163 | .replyWithFile(
164 | 200,
165 | path.join(__dirname, '/fixtures/brasilapi-cep-05010000-found.json')
166 | )
167 |
168 | return cep('05010000')
169 | .then(address => expect(address).to.deep.equal({
170 | cep: '05010000',
171 | state: 'SP',
172 | city: 'São Paulo',
173 | neighborhood: 'Perdizes',
174 | street: 'Rua Caiubi',
175 | service: address.service
176 | })
177 | )
178 | })
179 | })
180 |
181 | describe('when invoked with a valid 5010000 Number', () => {
182 | it('should fulfill with correct address', () => {
183 | nock('https://viacep.com.br')
184 | .get('/ws/05010000/json/')
185 | .replyWithFile(
186 | 200,
187 | path.join(__dirname, '/fixtures/viacep-cep-05010000-found.json')
188 | )
189 |
190 | nock('https://cdn.apicep.com')
191 | .get('/file/apicep/05010-000.json')
192 | .replyWithFile(
193 | 200,
194 | path.join(__dirname, '/fixtures/widenet-cep-05010000-found.json')
195 | )
196 |
197 | nock('https://brasilapi.com.br/')
198 | .get('/api/cep/v1/05010000')
199 | .replyWithFile(
200 | 200,
201 | path.join(__dirname, '/fixtures/brasilapi-cep-05010000-found.json')
202 | )
203 |
204 | return cep(5010000)
205 | .then(address => expect(address).to.deep.equal({
206 | cep: '05010000',
207 | state: 'SP',
208 | city: 'São Paulo',
209 | neighborhood: 'Perdizes',
210 | street: 'Rua Caiubi',
211 | service: address.service
212 | })
213 | )
214 | })
215 | })
216 |
217 | describe('Should succeed only with viacep service', () => {
218 | it('should fulfill with correct address', () => {
219 | nock('https://viacep.com.br')
220 | .get('/ws/05010000/json/')
221 | .replyWithFile(
222 | 200,
223 | path.join(__dirname, '/fixtures/viacep-cep-05010000-found.json')
224 | )
225 |
226 | nock('https://cdn.apicep.com')
227 | .get('/file/apicep/05010-000.json')
228 | .replyWithFile(
229 | 200,
230 | path.join(__dirname, '/fixtures/widenet-cep-99999999-error.json')
231 | )
232 |
233 | nock('https://brasilapi.com.br/')
234 | .get('/api/cep/v1/99999999')
235 | .replyWithFile(
236 | 404,
237 | path.join(__dirname, '/fixtures/brasilapi-cep-99999999-error.json')
238 | )
239 |
240 | return cep('05010000')
241 | .then(address => expect(address).to.deep.equal({
242 | cep: '05010000',
243 | state: 'SP',
244 | city: 'São Paulo',
245 | neighborhood: 'Perdizes',
246 | street: 'Rua Caiubi',
247 | service: 'viacep'
248 | })
249 | )
250 | })
251 | })
252 |
253 | describe('Should succeed only with widenet service', () => {
254 | it('should fulfill with correct address', () => {
255 | nock('https://viacep.com.br')
256 | .get('/ws/05010000/json/')
257 | .replyWithFile(
258 | 200,
259 | path.join(__dirname, '/fixtures/viacep-cep-99999999-error.json')
260 | )
261 |
262 | nock('https://cdn.apicep.com')
263 | .get('/file/apicep/05010-000.json')
264 | .replyWithFile(
265 | 200,
266 | path.join(__dirname, '/fixtures/widenet-cep-05010000-found.json')
267 | )
268 |
269 | nock('https://brasilapi.com.br/')
270 | .get('/api/cep/v1/99999999')
271 | .replyWithFile(
272 | 404,
273 | path.join(__dirname, '/fixtures/brasilapi-cep-99999999-error.json')
274 | )
275 |
276 | return cep('5010000')
277 | .then(address => expect(address).to.deep.equal({
278 | cep: '05010000',
279 | state: 'SP',
280 | city: 'São Paulo',
281 | neighborhood: 'Perdizes',
282 | street: 'Rua Caiubi',
283 | service: 'widenet'
284 | }))
285 | })
286 | })
287 |
288 | describe('Should succeed only with brasilapi service', () => {
289 | it('should fulfill with correct address', () => {
290 | nock('https://viacep.com.br')
291 | .get('/ws/05010000/json/')
292 | .replyWithFile(
293 | 200,
294 | path.join(__dirname, '/fixtures/viacep-cep-99999999-error.json')
295 | )
296 |
297 | nock('https://cdn.apicep.com')
298 | .get('/file/apicep/05010-000.json')
299 | .replyWithFile(
300 | 200,
301 | path.join(__dirname, '/fixtures/widenet-cep-99999999-error.json')
302 | )
303 |
304 | nock('https://brasilapi.com.br/')
305 | .get('/api/cep/v1/05010000')
306 | .replyWithFile(
307 | 200,
308 | path.join(__dirname, '/fixtures/brasilapi-cep-05010000-found.json')
309 | )
310 |
311 | return cep('5010000')
312 | .then(address => expect(address).to.deep.equal({
313 | cep: '05010000',
314 | state: 'SP',
315 | city: 'São Paulo',
316 | neighborhood: 'Perdizes',
317 | street: 'Rua Caiubi',
318 | service: 'brasilapi'
319 | }))
320 | })
321 | })
322 |
323 | describe('when invoked with an inexistent "99999999" CEP', () => {
324 | it('should reject with "service_error"', () => {
325 | nock('https://viacep.com.br')
326 | .get('/ws/99999999/json/')
327 | .replyWithFile(
328 | 200,
329 | path.join(__dirname, '/fixtures/viacep-cep-99999999-error.json')
330 | )
331 |
332 | nock('https://cdn.apicep.com')
333 | .get('/file/apicep/99999-999.json')
334 | .replyWithFile(
335 | 200,
336 | path.join(__dirname, '/fixtures/widenet-cep-99999999-error.json')
337 | )
338 |
339 | nock('https://brasilapi.com.br/')
340 | .get('/api/cep/v1/99999999')
341 | .replyWithFile(
342 | 404,
343 | path.join(__dirname, '/fixtures/brasilapi-cep-99999999-error.json')
344 | )
345 |
346 | return cep('99999999').catch(error => {
347 | return expect(error)
348 | .to.be.an.instanceOf(CepPromiseError)
349 | .and.containSubset({
350 | name: 'CepPromiseError',
351 | message: 'Todos os serviços de CEP retornaram erro.',
352 | type: 'service_error',
353 | errors: [
354 | {
355 | message: 'CEP não encontrado na base do ViaCEP.',
356 | service: 'viacep'
357 | },
358 | {
359 | message: 'CEP não encontrado na base do WideNet.',
360 | service: 'widenet'
361 | }
362 | ]
363 | })
364 | })
365 | })
366 | })
367 |
368 | describe('when invoked with an invalid "123456789" CEP', () => {
369 | it('should reject with "validation_error"', () => {
370 | return cep('123456789').catch(error => {
371 | return expect(error)
372 | .to.be.an.instanceOf(CepPromiseError)
373 | .and.containSubset({
374 | name: 'CepPromiseError',
375 | message: 'CEP deve conter exatamente 8 caracteres.',
376 | type: 'validation_error',
377 | errors: [
378 | {
379 | service: 'cep_validation',
380 | message: 'CEP informado possui mais do que 8 caracteres.'
381 | }
382 | ]
383 | })
384 | })
385 | })
386 | })
387 |
388 | describe('when http request fails both for all services with bad response', () => {
389 | it('should reject with "service_error"', () => {
390 | nock('https://viacep.com.br')
391 | .get('/ws/05010000/json/')
392 | .reply(400, 'Bad Request (400)
')
393 |
394 | nock('https://cdn.apicep.com')
395 | .get('/file/apicep/05010-000.json')
396 | .reply(400, 'Bad Request (400)
')
397 |
398 | nock('https://brasilapi.com.br/')
399 | .get('/api/cep/v1/05010000')
400 | .reply(400, 'Bad Request (400)
')
401 |
402 | return cep('05010000').catch(error => {
403 | return expect(error)
404 | .to.be.an.instanceOf(CepPromiseError)
405 | .and.containSubset({
406 | name: 'CepPromiseError',
407 | message: 'Todos os serviços de CEP retornaram erro.',
408 | type: 'service_error',
409 | errors: [
410 | {
411 | message: 'Erro ao se conectar com o serviço ViaCEP.',
412 | service: 'viacep'
413 | },
414 | {
415 | message: 'Erro ao se conectar com o serviço WideNet.',
416 | service: 'widenet'
417 | },
418 | {
419 | name: 'ServiceError',
420 | message: 'CEP não encontrado na base do BrasilAPI.',
421 | service: 'brasilapi'
422 | }
423 | ]
424 | })
425 | })
426 | })
427 | })
428 |
429 | afterEach(() => {
430 | nock.cleanAll()
431 | })
432 |
433 | after(() => {
434 | delete global.window
435 | })
436 | })
437 |
--------------------------------------------------------------------------------
/test/unit/cep-promise-node.spec.js:
--------------------------------------------------------------------------------
1 | 'use strict'
2 |
3 | import chai from 'chai'
4 | import chaiAsPromised from 'chai-as-promised'
5 | import chaiSubset from 'chai-subset'
6 | import nock from 'nock'
7 | import path from 'path'
8 |
9 | import cep from '../../src/cep-promise.js'
10 | import CepPromiseError from '../../src/errors/cep-promise.js'
11 |
12 | chai.use(chaiAsPromised)
13 | chai.use(chaiSubset)
14 |
15 | let expect = chai.expect
16 |
17 | describe('[unit] cep-promise for node', () => {
18 | before(() => {
19 | nock.disableNetConnect()
20 | })
21 |
22 | describe('when imported', () => {
23 | it('should return a Function', () => {
24 | expect(cep).to.be.a('function')
25 | })
26 | })
27 |
28 | describe('when invoked', () => {
29 | it('should return a Promise', () => {
30 | nock('https://apps.correios.com.br')
31 | .post('/SigepMasterJPA/AtendeClienteService/AtendeCliente')
32 | .replyWithFile(
33 | 200,
34 | path.join(__dirname, '/fixtures/response-cep-05010000-found.xml')
35 | )
36 |
37 | nock('https://buscacepinter.correios.com.br')
38 | .post('/app/endereco/carrega-cep-endereco.php')
39 | .replyWithFile(
40 | 200,
41 | path.join(__dirname, '/fixtures/correios-alt-cep-05010000-found.json')
42 | )
43 |
44 | nock('https://viacep.com.br')
45 | .get('/ws/05010000/json/')
46 | .replyWithFile(
47 | 200,
48 | path.join(__dirname, '/fixtures/viacep-cep-05010000-found.json')
49 | )
50 |
51 | nock('https://cdn.apicep.com')
52 | .get('/file/apicep/05010-000.json')
53 | .replyWithFile(
54 | 200,
55 | path.join(__dirname, '/fixtures/widenet-cep-05010000-found.json')
56 | )
57 |
58 | nock('https://brasilapi.com.br/')
59 | .get('/api/cep/v1/05010000')
60 | .replyWithFile(
61 | 200,
62 | path.join(__dirname, '/fixtures/brasilapi-cep-05010000-found.json')
63 | )
64 |
65 | const cepPromise = cep('05010000')
66 | expect(cepPromise.then).to.be.a('function')
67 | expect(cepPromise.catch).to.be.a('function')
68 | })
69 | })
70 |
71 | describe('when invoked without arguments', () => {
72 | it('should reject with "validation_error"', () => {
73 | return cep().catch(error => {
74 | return expect(error)
75 | .to.be.an.instanceOf(CepPromiseError)
76 | .and.containSubset({
77 | name: 'CepPromiseError',
78 | message: 'Erro ao inicializar a instância do CepPromise.',
79 | type: 'validation_error',
80 | errors: [
81 | {
82 | message:
83 | 'Você deve chamar o construtor utilizando uma String ou um Number.',
84 | service: 'cep_validation'
85 | }
86 | ]
87 | })
88 | })
89 | })
90 | })
91 |
92 | describe('when invoked with an Array', () => {
93 | it('should reject with "validation_error"', () => {
94 | return cep([1, 2, 3]).catch(error => {
95 | return expect(error)
96 | .to.be.an.instanceOf(CepPromiseError)
97 | .and.containSubset({
98 | name: 'CepPromiseError',
99 | message: 'Erro ao inicializar a instância do CepPromise.',
100 | type: 'validation_error',
101 | errors: [
102 | {
103 | message:
104 | 'Você deve chamar o construtor utilizando uma String ou um Number.',
105 | service: 'cep_validation'
106 | }
107 | ]
108 | })
109 | })
110 | })
111 | })
112 |
113 | describe('when invoked with an Object', () => {
114 | it('should reject with "validation_error"', () => {
115 | return cep({ nintendo: true, ps: false, xbox: false }).catch(error => {
116 | return expect(error)
117 | .to.be.an.instanceOf(CepPromiseError)
118 | .and.containSubset({
119 | name: 'CepPromiseError',
120 | message: 'Erro ao inicializar a instância do CepPromise.',
121 | type: 'validation_error',
122 | errors: [
123 | {
124 | message:
125 | 'Você deve chamar o construtor utilizando uma String ou um Number.',
126 | service: 'cep_validation'
127 | }
128 | ]
129 | })
130 | })
131 | })
132 | })
133 |
134 | describe('when invoked with an Function', () => {
135 | it('should reject with "validation_error"', () => {
136 | return cep(function zelda() {
137 | return 'link'
138 | }).catch(error => {
139 | return expect(error)
140 | .to.be.an.instanceOf(CepPromiseError)
141 | .and.containSubset({
142 | name: 'CepPromiseError',
143 | message: 'Erro ao inicializar a instância do CepPromise.',
144 | type: 'validation_error',
145 | errors: [
146 | {
147 | message:
148 | 'Você deve chamar o construtor utilizando uma String ou um Number.',
149 | service: 'cep_validation'
150 | }
151 | ]
152 | })
153 | })
154 | })
155 | })
156 |
157 | describe('when invoked with a valid "05010000" String', () => {
158 | it('should fulfill with correct address', () => {
159 | nock('https://apps.correios.com.br')
160 | .post('/SigepMasterJPA/AtendeClienteService/AtendeCliente')
161 | .replyWithFile(
162 | 200,
163 | path.join(__dirname, '/fixtures/response-cep-05010000-found.xml')
164 | )
165 |
166 | nock('https://buscacepinter.correios.com.br')
167 | .post('/app/endereco/carrega-cep-endereco.php')
168 | .replyWithFile(
169 | 200,
170 | path.join(__dirname, '/fixtures/correios-alt-cep-05010000-found.json')
171 | )
172 |
173 | nock('https://viacep.com.br')
174 | .get('/ws/05010000/json/')
175 | .replyWithFile(
176 | 200,
177 | path.join(__dirname, '/fixtures/viacep-cep-05010000-found.json')
178 | )
179 |
180 | nock('https://cdn.apicep.com')
181 | .get('/file/apicep/05010-000.json')
182 | .replyWithFile(
183 | 200,
184 | path.join(__dirname, '/fixtures/widenet-cep-05010000-found.json')
185 | )
186 |
187 | nock('https://brasilapi.com.br/')
188 | .get('/api/cep/v1/05010000')
189 | .replyWithFile(
190 | 200,
191 | path.join(__dirname, '/fixtures/brasilapi-cep-05010000-found.json')
192 | )
193 |
194 | return cep('05010000')
195 | .then(address => expect(address).to.deep.equal({
196 | cep: '05010000',
197 | state: 'SP',
198 | city: 'São Paulo',
199 | neighborhood: 'Perdizes',
200 | street: 'Rua Caiubi',
201 | service: address.service
202 | })
203 | )
204 | })
205 | })
206 |
207 | describe('when invoked with a valid 5010000 Number', () => {
208 | it('should fulfill with correct address', () => {
209 | nock('https://apps.correios.com.br')
210 | .post('/SigepMasterJPA/AtendeClienteService/AtendeCliente')
211 | .replyWithFile(
212 | 200,
213 | path.join(__dirname, '/fixtures/response-cep-05010000-found.xml')
214 | )
215 |
216 | nock('https://buscacepinter.correios.com.br')
217 | .post('/app/endereco/carrega-cep-endereco.php')
218 | .replyWithFile(
219 | 200,
220 | path.join(__dirname, '/fixtures/correios-alt-cep-05010000-found.json')
221 | )
222 |
223 | nock('https://viacep.com.br')
224 | .get('/ws/05010000/json/')
225 | .replyWithFile(
226 | 200,
227 | path.join(__dirname, '/fixtures/viacep-cep-05010000-found.json')
228 | )
229 |
230 | nock('https://cdn.apicep.com')
231 | .get('/file/apicep/05010-000.json')
232 | .replyWithFile(
233 | 200,
234 | path.join(__dirname, '/fixtures/widenet-cep-05010000-found.json')
235 | )
236 |
237 | nock('https://brasilapi.com.br/')
238 | .get('/api/cep/v1/05010000')
239 | .replyWithFile(
240 | 200,
241 | path.join(__dirname, '/fixtures/brasilapi-cep-05010000-found.json')
242 | )
243 |
244 | return cep(5010000)
245 | .then(address => expect(address).to.deep.equal({
246 | cep: '05010000',
247 | state: 'SP',
248 | city: 'São Paulo',
249 | neighborhood: 'Perdizes',
250 | street: 'Rua Caiubi',
251 | service: address.service
252 | })
253 | )
254 | })
255 | })
256 |
257 | describe('Should succeed only with correios service', () => {
258 | it('should fulfill with correct address', () => {
259 | nock('https://apps.correios.com.br')
260 | .post('/SigepMasterJPA/AtendeClienteService/AtendeCliente')
261 | .replyWithFile(
262 | 200,
263 | path.join(__dirname, '/fixtures/response-cep-05010000-found.xml')
264 | )
265 |
266 | nock('https://buscacepinter.correios.com.br')
267 | .post('/app/endereco/carrega-cep-endereco.php')
268 | .replyWithFile(
269 | 200,
270 | path.join(__dirname, '/fixtures/correios-alt-cep-99999999-error.json')
271 | )
272 |
273 | nock('https://viacep.com.br')
274 | .get('/ws/05010000/json/')
275 | .replyWithFile(
276 | 200,
277 | path.join(__dirname, '/fixtures/viacep-cep-99999999-error.json')
278 | )
279 |
280 | nock('https://cep.widenet.host')
281 | .get('/file/apicep/05010-000.json')
282 | .replyWithFile(
283 | 200,
284 | path.join(__dirname, '/fixtures/widenet-cep-99999999-error.json')
285 | )
286 |
287 | nock('https://brasilapi.com.br/')
288 | .get('/api/cep/v1/99999999')
289 | .replyWithFile(
290 | 404,
291 | path.join(__dirname, '/fixtures/brasilapi-cep-99999999-error.json')
292 | )
293 |
294 |
295 | return cep('05010000')
296 | .then(address => expect(address).to.deep.equal({
297 | cep: '05010000',
298 | state: 'SP',
299 | city: 'São Paulo',
300 | neighborhood: 'Perdizes',
301 | street: 'Rua Caiubi',
302 | service: 'correios'
303 | })
304 | )
305 | })
306 | })
307 |
308 | describe('Should succeed only with correios-alt service', () => {
309 | it('should fulfill with correct address', () => {
310 | nock('https://apps.correios.com.br')
311 | .post('/SigepMasterJPA/AtendeClienteService/AtendeCliente')
312 | .replyWithFile(
313 | 500,
314 | path.join(__dirname, '/fixtures/response-unknown-format.xml')
315 | )
316 |
317 | nock('https://buscacepinter.correios.com.br')
318 | .post('/app/endereco/carrega-cep-endereco.php')
319 | .replyWithFile(
320 | 200,
321 | path.join(__dirname, '/fixtures/correios-alt-cep-05010000-found.json')
322 | )
323 |
324 | nock('https://viacep.com.br')
325 | .get('/ws/05010000/json/')
326 | .replyWithFile(
327 | 200,
328 | path.join(__dirname, '/fixtures/viacep-cep-99999999-error.json')
329 | )
330 |
331 | nock('https://cdn.apicep.com')
332 | .get('/file/apicep/05010-000.json')
333 | .replyWithFile(
334 | 200,
335 | path.join(__dirname, '/fixtures/widenet-cep-99999999-error.json')
336 | )
337 |
338 | nock('https://brasilapi.com.br/')
339 | .get('/api/cep/v1/99999999')
340 | .replyWithFile(
341 | 404,
342 | path.join(__dirname, '/fixtures/brasilapi-cep-99999999-error.json')
343 | )
344 |
345 |
346 | return cep('05010000')
347 | .then(address => expect(address).to.deep.equal({
348 | cep: '05010000',
349 | state: 'SP',
350 | city: 'São Paulo',
351 | neighborhood: 'Perdizes',
352 | street: 'Rua Caiubi',
353 | service: 'correios-alt'
354 | })
355 | )
356 | })
357 | })
358 |
359 | describe('Should succeed only with viacep service', () => {
360 | it('should fulfill with correct address', () => {
361 | nock('https://apps.correios.com.br')
362 | .post('/SigepMasterJPA/AtendeClienteService/AtendeCliente')
363 | .replyWithFile(
364 | 500,
365 | path.join(__dirname, '/fixtures/response-unknown-format.xml')
366 | )
367 |
368 | nock('https://buscacepinter.correios.com.br')
369 | .post('/app/endereco/carrega-cep-endereco.php')
370 | .replyWithFile(
371 | 200,
372 | path.join(__dirname, '/fixtures/correios-alt-cep-99999999-error.json')
373 | )
374 |
375 | nock('https://viacep.com.br')
376 | .get('/ws/05010000/json/')
377 | .replyWithFile(
378 | 200,
379 | path.join(__dirname, '/fixtures/viacep-cep-05010000-found.json')
380 | )
381 |
382 | nock('https://cdn.apicep.com')
383 | .get('/file/apicep/05010-000.json')
384 | .replyWithFile(
385 | 200,
386 | path.join(__dirname, '/fixtures/widenet-cep-99999999-error.json')
387 | )
388 |
389 | nock('https://brasilapi.com.br/')
390 | .get('/api/cep/v1/99999999')
391 | .replyWithFile(
392 | 404,
393 | path.join(__dirname, '/fixtures/brasilapi-cep-99999999-error.json')
394 | )
395 |
396 | return cep('05010000')
397 | .then(address => expect(address).to.deep.equal({
398 | cep: '05010000',
399 | state: 'SP',
400 | city: 'São Paulo',
401 | neighborhood: 'Perdizes',
402 | street: 'Rua Caiubi',
403 | service: 'viacep'
404 | })
405 | )
406 | })
407 | })
408 |
409 | describe('Should succeed only with widenet service', () => {
410 | it('should fulfill with correct address', () => {
411 | nock('https://apps.correios.com.br')
412 | .post('/SigepMasterJPA/AtendeClienteService/AtendeCliente')
413 | .replyWithFile(
414 | 500,
415 | path.join(__dirname, '/fixtures/response-unknown-format.xml')
416 | )
417 |
418 | nock('https://buscacepinter.correios.com.br')
419 | .post('/app/endereco/carrega-cep-endereco.php')
420 | .replyWithFile(
421 | 200,
422 | path.join(__dirname, '/fixtures/correios-alt-cep-99999999-error.json')
423 | )
424 |
425 | nock('https://viacep.com.br')
426 | .get('/ws/05010000/json/')
427 | .replyWithFile(
428 | 200,
429 | path.join(__dirname, '/fixtures/viacep-cep-99999999-error.json')
430 | )
431 |
432 | nock('https://cdn.apicep.com')
433 | .get('/file/apicep/05010-000.json')
434 | .replyWithFile(
435 | 200,
436 | path.join(__dirname, '/fixtures/widenet-cep-05010000-found.json')
437 | )
438 |
439 | nock('https://brasilapi.com.br/')
440 | .get('/api/cep/v1/99999999')
441 | .replyWithFile(
442 | 404,
443 | path.join(__dirname, '/fixtures/brasilapi-cep-99999999-error.json')
444 | )
445 |
446 | return cep('5010000')
447 | .then(address => expect(address).to.deep.equal({
448 | cep: '05010000',
449 | state: 'SP',
450 | city: 'São Paulo',
451 | neighborhood: 'Perdizes',
452 | street: 'Rua Caiubi',
453 | service: 'widenet'
454 | }))
455 | })
456 | })
457 |
458 | describe('Should succeed only with brasilapi service', () => {
459 | it('should fulfill with correct address', () => {
460 | nock('https://apps.correios.com.br')
461 | .post('/SigepMasterJPA/AtendeClienteService/AtendeCliente')
462 | .replyWithFile(
463 | 500,
464 | path.join(__dirname, '/fixtures/response-unknown-format.xml')
465 | )
466 |
467 | nock('https://buscacepinter.correios.com.br')
468 | .post('/app/endereco/carrega-cep-endereco.php')
469 | .replyWithFile(
470 | 200,
471 | path.join(__dirname, '/fixtures/correios-alt-cep-99999999-error.json')
472 | )
473 |
474 | nock('https://viacep.com.br')
475 | .get('/ws/05010000/json/')
476 | .replyWithFile(
477 | 200,
478 | path.join(__dirname, '/fixtures/viacep-cep-99999999-error.json')
479 | )
480 |
481 | nock('https://cdn.apicep.com')
482 | .get('/file/apicep/05010-000.json')
483 | .replyWithFile(
484 | 200,
485 | path.join(__dirname, '/fixtures/widenet-cep-99999999-error.json')
486 | )
487 |
488 | nock('https://brasilapi.com.br/')
489 | .get('/api/cep/v1/05010000')
490 | .replyWithFile(
491 | 200,
492 | path.join(__dirname, '/fixtures/brasilapi-cep-05010000-found.json')
493 | )
494 |
495 | return cep('5010000')
496 | .then(address => expect(address).to.deep.equal({
497 | cep: '05010000',
498 | state: 'SP',
499 | city: 'São Paulo',
500 | neighborhood: 'Perdizes',
501 | street: 'Rua Caiubi',
502 | service: 'brasilapi'
503 | }))
504 | })
505 | })
506 |
507 | describe('when its not possible to parse the returned XML and then succeed to one failover service', () => {
508 | it('should fulfill with correct address', () => {
509 | nock('https://apps.correios.com.br')
510 | .post('/SigepMasterJPA/AtendeClienteService/AtendeCliente')
511 | .replyWithFile(
512 | 200,
513 | path.join(__dirname, '/fixtures/response-bad-xml.xml')
514 | )
515 |
516 | nock('https://buscacepinter.correios.com.br')
517 | .post('/app/endereco/carrega-cep-endereco.php')
518 | .replyWithFile(
519 | 200,
520 | path.join(__dirname, '/fixtures/correios-alt-cep-05010000-found.json')
521 | )
522 |
523 | nock('https://viacep.com.br')
524 | .get('/ws/05010000/json/')
525 | .replyWithFile(
526 | 200,
527 | path.join(__dirname, '/fixtures/viacep-cep-05010000-found.json')
528 | )
529 |
530 | nock('https://cdn.apicep.com')
531 | .get('/file/apicep/05010-000.json')
532 | .replyWithFile(
533 | 200,
534 | path.join(__dirname, '/fixtures/widenet-cep-05010000-found.json')
535 | )
536 |
537 | nock('https://brasilapi.com.br/')
538 | .get('/api/cep/v1/05010000')
539 | .replyWithFile(
540 | 200,
541 | path.join(__dirname, '/fixtures/brasilapi-cep-05010000-found.json')
542 | )
543 |
544 | return cep('5010000')
545 | .then(address => expect(address).to.deep.equal({
546 | cep: '05010000',
547 | state: 'SP',
548 | city: 'São Paulo',
549 | neighborhood: 'Perdizes',
550 | street: 'Rua Caiubi',
551 | service: address.service
552 | }))
553 | })
554 | })
555 |
556 | describe('when http request to Correios fails and then succeed to the failover service', () => {
557 | it('should fulfill with correct address', () => {
558 | nock('https://apps.correios.com.br')
559 | .post('/SigepMasterJPA/AtendeClienteService/AtendeCliente')
560 | .replyWithError(
561 | 'getaddrinfo ENOTFOUND apps.correios.com.br apps.correios.com.br:443'
562 | )
563 |
564 | nock('https://buscacepinter.correios.com.br')
565 | .post('/app/endereco/carrega-cep-endereco.php')
566 | .replyWithFile(
567 | 200,
568 | path.join(__dirname, '/fixtures/correios-alt-cep-05010000-found.json')
569 | )
570 |
571 | nock('https://viacep.com.br')
572 | .get('/ws/05010000/json/')
573 | .replyWithFile(
574 | 200,
575 | path.join(__dirname, '/fixtures/viacep-cep-05010000-found.json')
576 | )
577 |
578 | nock('https://cdn.apicep.com')
579 | .get('/file/apicep/05010-000.json')
580 | .replyWithFile(
581 | 200,
582 | path.join(__dirname, '/fixtures/widenet-cep-05010000-found.json')
583 | )
584 |
585 | nock('https://brasilapi.com.br/')
586 | .get('/api/cep/v1/05010000')
587 | .replyWithFile(
588 | 200,
589 | path.join(__dirname, '/fixtures/brasilapi-cep-05010000-found.json')
590 | )
591 |
592 | return cep('5010000')
593 | .then(address => expect(address).to.deep.equal({
594 | cep: '05010000',
595 | state: 'SP',
596 | city: 'São Paulo',
597 | neighborhood: 'Perdizes',
598 | street: 'Rua Caiubi',
599 | service: address.service
600 | }))
601 | })
602 | })
603 |
604 | describe('when invoked with an inexistent "99999999" CEP', () => {
605 | it('should reject with "service_error"', () => {
606 | nock('https://apps.correios.com.br')
607 | .post('/SigepMasterJPA/AtendeClienteService/AtendeCliente')
608 | .replyWithFile(
609 | 500,
610 | path.join(__dirname, '/fixtures/response-cep-not-found.xml')
611 | )
612 |
613 | nock('https://buscacepinter.correios.com.br')
614 | .post('/app/endereco/carrega-cep-endereco.php')
615 | .replyWithFile(
616 | 200,
617 | path.join(__dirname, '/fixtures/correios-alt-cep-99999999-error.json')
618 | )
619 |
620 | nock('https://viacep.com.br')
621 | .get('/ws/99999999/json/')
622 | .replyWithFile(
623 | 200,
624 | path.join(__dirname, '/fixtures/viacep-cep-99999999-error.json')
625 | )
626 |
627 | nock('https://cdn.apicep.com')
628 | .get('/file/apicep/99999-999.json')
629 | .replyWithFile(
630 | 200,
631 | path.join(__dirname, '/fixtures/widenet-cep-99999999-error.json')
632 | )
633 |
634 | nock('https://brasilapi.com.br/')
635 | .get('/api/cep/v1/99999999')
636 | .replyWithFile(
637 | 404,
638 | path.join(__dirname, '/fixtures/brasilapi-cep-99999999-error.json')
639 | )
640 |
641 | return cep('99999999').catch(error => {
642 | return expect(error)
643 | .to.be.an.instanceOf(CepPromiseError)
644 | .and.containSubset({
645 | name: 'CepPromiseError',
646 | message: 'Todos os serviços de CEP retornaram erro.',
647 | type: 'service_error',
648 | errors: [
649 | {
650 | message: 'CEP NAO ENCONTRADO',
651 | service: 'correios'
652 | },
653 | {
654 | message: 'CEP não encontrado na base dos Correios.',
655 | service: 'correios-alt'
656 | },
657 | {
658 | message: 'CEP não encontrado na base do ViaCEP.',
659 | service: 'viacep'
660 | },
661 | {
662 | message: 'CEP não encontrado na base do WideNet.',
663 | service: 'widenet'
664 | }
665 | ]
666 | })
667 | })
668 | })
669 | })
670 |
671 | describe('when invoked with an invalid "123456789" CEP', () => {
672 | it('should reject with "validation_error"', () => {
673 | return cep('123456789').catch(error => {
674 | return expect(error)
675 | .to.be.an.instanceOf(CepPromiseError)
676 | .and.containSubset({
677 | name: 'CepPromiseError',
678 | message: 'CEP deve conter exatamente 8 caracteres.',
679 | type: 'validation_error',
680 | errors: [
681 | {
682 | service: 'cep_validation',
683 | message: 'CEP informado possui mais do que 8 caracteres.'
684 | }
685 | ]
686 | })
687 | })
688 | })
689 | })
690 |
691 | describe('when http request fails both for primary and secondary service with bad response', () => {
692 | it('should reject with "service_error"', () => {
693 | nock('https://apps.correios.com.br')
694 | .post('/SigepMasterJPA/AtendeClienteService/AtendeCliente')
695 | .replyWithError(
696 | 'getaddrinfo ENOTFOUND apps.correios.com.br apps.correios.com.br:443'
697 | )
698 |
699 | nock('https://buscacepinter.correios.com.br')
700 | .post('/app/endereco/carrega-cep-endereco.php')
701 | .reply(400, 'Bad Request (400)
')
702 |
703 | nock('https://viacep.com.br')
704 | .get('/ws/05010000/json/')
705 | .reply(400, 'Bad Request (400)
')
706 |
707 | nock('https://cdn.apicep.com')
708 | .get('/file/apicep/05010-000.json')
709 | .reply(400, 'Bad Request (400)
')
710 |
711 | nock('https://brasilapi.com.br/')
712 | .get('/api/cep/v1/05010000')
713 | .reply(400, 'Bad Request (400)
')
714 |
715 | return cep('05010000').catch(error => {
716 | return expect(error)
717 | .to.be.an.instanceOf(CepPromiseError)
718 | .and.containSubset({
719 | name: 'CepPromiseError',
720 | message: 'Todos os serviços de CEP retornaram erro.',
721 | type: 'service_error',
722 | errors: [
723 | {
724 | message: 'Erro ao se conectar com o serviço dos Correios.',
725 | service: 'correios'
726 | },
727 | {
728 | message: 'Erro ao se conectar com o serviço dos Correios Alt.',
729 | service: 'correios-alt'
730 | },
731 | {
732 | message: 'Erro ao se conectar com o serviço ViaCEP.',
733 | service: 'viacep'
734 | },
735 | {
736 | message: 'Erro ao se conectar com o serviço WideNet.',
737 | service: 'widenet'
738 | },
739 | {
740 | name: 'ServiceError',
741 | message: 'CEP não encontrado na base do BrasilAPI.',
742 | service: 'brasilapi'
743 | }
744 | ]
745 | })
746 | })
747 | })
748 | })
749 |
750 | describe('when http request has unformatted xml and alternatives services fails', () => {
751 | it('should reject with "service_error"', () => {
752 | nock('https://apps.correios.com.br')
753 | .post('/SigepMasterJPA/AtendeClienteService/AtendeCliente')
754 | .replyWithFile(
755 | 200,
756 | path.join(__dirname, '/fixtures/response-bad-xml.xml')
757 | )
758 |
759 | nock('https://buscacepinter.correios.com.br')
760 | .post('/app/endereco/carrega-cep-endereco.php')
761 | .reply(200, {erro:true})
762 |
763 | nock('https://viacep.com.br')
764 | .get('/ws/05010000/json/')
765 | .reply(400, 'Bad Request (400)
')
766 |
767 | nock('https://cdn.apicep.com')
768 | .get('/file/apicep/05010-000.json')
769 | .reply(400, 'Bad Request (400)
')
770 |
771 | nock('https://brasilapi.com.br/')
772 | .get('/api/cep/v1/05010000')
773 | .reply(400, 'Bad Request (400)
')
774 |
775 | return cep('05010000').catch(error => {
776 | return expect(error)
777 | .to.be.an.instanceOf(CepPromiseError)
778 | .and.containSubset({
779 | name: 'CepPromiseError',
780 | message: 'Todos os serviços de CEP retornaram erro.',
781 | type: 'service_error',
782 | errors: [
783 | {
784 | message: 'Não foi possível interpretar o XML de resposta.',
785 | service: 'correios'
786 | },
787 | {
788 | message: 'CEP não encontrado na base dos Correios.',
789 | service: 'correios-alt'
790 | },
791 | {
792 | message: 'Erro ao se conectar com o serviço ViaCEP.',
793 | service: 'viacep'
794 | },
795 | {
796 | message: 'Erro ao se conectar com o serviço WideNet.',
797 | service: 'widenet'
798 | },
799 | {
800 | name: 'ServiceError',
801 | message: 'CEP não encontrado na base do BrasilAPI.',
802 | service: 'brasilapi'
803 | }
804 | ]
805 | })
806 | })
807 | })
808 | })
809 |
810 | describe('when http request fails both for primary and secondary service with error', () => {
811 | it('should reject with "service_error"', () => {
812 | nock('https://apps.correios.com.br')
813 | .post('/SigepMasterJPA/AtendeClienteService/AtendeCliente')
814 | .replyWithError(
815 | 'getaddrinfo ENOTFOUND apps.correios.com.br apps.correios.com.br:443'
816 | )
817 |
818 | nock('https://buscacepinter.correios.com.br')
819 | .post('/app/endereco/carrega-cep-endereco.php')
820 | .reply(200, {erro:true})
821 |
822 | nock('https://viacep.com.br')
823 | .get('/ws/05010000/json/')
824 | .replyWithError(
825 | 'getaddrinfo ENOTFOUND apps.correios.com.br apps.correios.com.br:443'
826 | )
827 |
828 | nock('https://cdn.apicep.com')
829 | .get('/file/apicep/05010-000.json')
830 | .replyWithError(
831 | 'getaddrinfo ENOTFOUND apps.correios.com.br apps.correios.com.br:443'
832 | )
833 |
834 | nock('https://brasilapi.com.br/')
835 | .get('/api/cep/v1/05010000')
836 | .replyWithError(
837 | 'getaddrinfo ENOTFOUND apps.correios.com.br apps.correios.com.br:443'
838 | )
839 |
840 | return cep('05010000').catch(error => {
841 | return expect(error)
842 | .to.be.an.instanceOf(CepPromiseError)
843 | .and.containSubset({
844 | name: 'CepPromiseError',
845 | message: 'Todos os serviços de CEP retornaram erro.',
846 | type: 'service_error',
847 | errors: [
848 | {
849 | message: 'Erro ao se conectar com o serviço dos Correios.',
850 | service: 'correios'
851 | },
852 | {
853 | message: 'CEP não encontrado na base dos Correios.',
854 | service: 'correios-alt'
855 | },
856 | {
857 | message: 'Erro ao se conectar com o serviço ViaCEP.',
858 | service: 'viacep'
859 | },
860 | {
861 | message: 'Erro ao se conectar com o serviço WideNet.',
862 | service: 'widenet'
863 | },
864 | {
865 | message: 'Erro ao se conectar com o serviço BrasilAPI.',
866 | service: 'brasilapi'
867 | }
868 | ]
869 | })
870 | })
871 | })
872 | })
873 |
874 | afterEach(() => {
875 | nock.cleanAll()
876 | })
877 | })
878 |
--------------------------------------------------------------------------------
/test/unit/cep-promise-providers.spec.js:
--------------------------------------------------------------------------------
1 | 'use strict'
2 |
3 | import chai from 'chai'
4 | import chaiSubset from 'chai-subset'
5 | import nock from 'nock'
6 | import path from 'path'
7 |
8 | import cep from '../../src/cep-promise.js'
9 | import CepPromiseError from '../../src/errors/cep-promise.js'
10 | import { getAvailableServices } from '../../src/services/index.js'
11 |
12 | chai.use(chaiSubset)
13 |
14 | let expect = chai.expect
15 |
16 | describe('when invoked with providers parameter', () => {
17 | before(() => {
18 | nock.disableNetConnect()
19 | })
20 |
21 | describe('and the providers param is a string', () => {
22 | it('should reject with "validation_error"', () => {
23 | return cep('05010000', { providers: 'viacep' }).catch(error => {
24 | return expect(error)
25 | .to.be.an.instanceOf(CepPromiseError)
26 | .and.containSubset({
27 | name: 'CepPromiseError',
28 | message: 'Erro ao inicializar a instância do CepPromise.',
29 | type: 'validation_error',
30 | errors: [
31 | {
32 | service: 'providers_validation',
33 | message: 'O parâmetro providers deve ser uma lista.'
34 | }
35 | ]
36 | })
37 | })
38 | })
39 | })
40 |
41 | describe('and the providers param is a integer', () => {
42 | it('should reject with "validation_error"', () => {
43 | return cep('05010000', { providers: 123 }).catch(error => {
44 | return expect(error)
45 | .to.be.an.instanceOf(CepPromiseError)
46 | .and.containSubset({
47 | name: 'CepPromiseError',
48 | message: 'Erro ao inicializar a instância do CepPromise.',
49 | type: 'validation_error',
50 | errors: [
51 | {
52 | service: 'providers_validation',
53 | message: 'O parâmetro providers deve ser uma lista.'
54 | }
55 | ]
56 | })
57 | })
58 | })
59 | })
60 |
61 | describe('and the providers param is a object', () => {
62 | it('should reject with "validation_error"', () => {
63 | return cep('05010000', { providers: {} }).catch(error => {
64 | return expect(error)
65 | .to.be.an.instanceOf(CepPromiseError)
66 | .and.containSubset({
67 | name: 'CepPromiseError',
68 | message: 'Erro ao inicializar a instância do CepPromise.',
69 | type: 'validation_error',
70 | errors: [
71 | {
72 | service: 'providers_validation',
73 | message: 'O parâmetro providers deve ser uma lista.'
74 | }
75 | ]
76 | })
77 | })
78 | })
79 | })
80 |
81 | describe('and the providers param is a function', () => {
82 | it('should reject with "validation_error"', () => {
83 | return cep('05010000', { providers: () => () => { } }).catch(error => {
84 | return expect(error)
85 | .to.be.an.instanceOf(CepPromiseError)
86 | .and.containSubset({
87 | name: 'CepPromiseError',
88 | message: 'Erro ao inicializar a instância do CepPromise.',
89 | type: 'validation_error',
90 | errors: [
91 | {
92 | service: 'providers_validation',
93 | message: 'O parâmetro providers deve ser uma lista.'
94 | }
95 | ]
96 | })
97 | })
98 | })
99 | })
100 |
101 | describe('and the providers param is a invalid array', () => {
102 | it('should reject with "validation_error"', () => {
103 | const availableProviders = Object.keys(getAvailableServices())
104 |
105 | return cep('05010000', { providers: [123, 'viacep'] }).catch(error => {
106 | return expect(error)
107 | .to.be.an.instanceOf(CepPromiseError)
108 | .and.containSubset({
109 | message: 'Erro ao inicializar a instância do CepPromise.',
110 | type: 'validation_error',
111 | errors: [
112 | {
113 | message:
114 | `O provider "123" é inválido. Os providers disponíveis são: ["${availableProviders.join('", "')}"].`,
115 | service: 'providers_validation'
116 | }
117 | ]
118 | })
119 | })
120 | })
121 | })
122 |
123 | describe('and the providers param is [\'viacep\']', () => {
124 | it('should call only viacep service', () => {
125 | const correiosMock = nock('https://apps.correios.com.br')
126 | .post('/SigepMasterJPA/AtendeClienteService/AtendeCliente')
127 | .replyWithFile(
128 | 200,
129 | path.join(__dirname, '/fixtures/response-cep-05010000-found.xml')
130 | )
131 |
132 | const correiosAltMock = nock('https://buscacepinter.correios.com.br')
133 | .post('/app/endereco/carrega-cep-endereco.php')
134 | .replyWithFile(
135 | 200,
136 | path.join(__dirname, '/fixtures/correios-alt-cep-05010000-found.json')
137 | )
138 |
139 | const viaCepMock = nock('https://viacep.com.br')
140 | .get('/ws/05010000/json/')
141 | .replyWithFile(
142 | 200,
143 | path.join(__dirname, '/fixtures/viacep-cep-05010000-found.json')
144 | )
145 |
146 | const wideNetMock = nock('https://cdn.apicep.com')
147 | .get('/file/apicep/05010-000.json')
148 | .replyWithFile(
149 | 200,
150 | path.join(__dirname, '/fixtures/widenet-cep-05010000-found.json')
151 | )
152 |
153 | return cep('05010000', { providers: ['viacep'] })
154 | .then(address => {
155 | expect(address).to.deep.equal({
156 | cep: '05010000',
157 | state: 'SP',
158 | city: 'São Paulo',
159 | neighborhood: 'Perdizes',
160 | street: 'Rua Caiubi',
161 | service: 'viacep'
162 | })
163 |
164 | expect(viaCepMock.isDone()).to.be.equal(true)
165 | expect(correiosMock.isDone()).to.be.equal(false)
166 | expect(correiosAltMock.isDone()).to.be.equal(false)
167 | expect(wideNetMock.isDone()).to.be.equal(false)
168 | })
169 | })
170 | })
171 |
172 | describe('and the providers param is [\'widenet\']', () => {
173 | it('should call only widenet service', () => {
174 | const correiosMock = nock('https://apps.correios.com.br')
175 | .post('/SigepMasterJPA/AtendeClienteService/AtendeCliente')
176 | .replyWithFile(
177 | 200,
178 | path.join(__dirname, '/fixtures/response-cep-05010000-found.xml')
179 | )
180 |
181 | const correiosAltMock = nock('https://buscacepinter.correios.com.br')
182 | .post('/app/endereco/carrega-cep-endereco.php')
183 | .replyWithFile(
184 | 200,
185 | path.join(__dirname, '/fixtures/correios-alt-cep-05010000-found.json')
186 | )
187 |
188 | const viaCepMock = nock('https://viacep.com.br')
189 | .get('/ws/05010000/json/')
190 | .replyWithFile(
191 | 200,
192 | path.join(__dirname, '/fixtures/viacep-cep-05010000-found.json')
193 | )
194 |
195 | const wideNetMock = nock('https://cdn.apicep.com')
196 | .get('/file/apicep/05010-000.json')
197 | .replyWithFile(
198 | 200,
199 | path.join(__dirname, '/fixtures/widenet-cep-05010000-found.json')
200 | )
201 |
202 | return cep('05010000', { providers: ['widenet'] })
203 | .then(address => {
204 | expect(address).to.deep.equal({
205 | cep: '05010000',
206 | state: 'SP',
207 | city: 'São Paulo',
208 | neighborhood: 'Perdizes',
209 | street: 'Rua Caiubi',
210 | service: 'widenet'
211 | })
212 |
213 | expect(wideNetMock.isDone()).to.be.equal(true)
214 | expect(viaCepMock.isDone()).to.be.equal(false)
215 | expect(correiosMock.isDone()).to.be.equal(false)
216 | expect(correiosAltMock.isDone()).to.be.equal(false)
217 | })
218 | })
219 | })
220 |
221 | describe('and the providers param is [\'correios\']', () => {
222 | it('should call only correios service', () => {
223 | const correiosMock = nock('https://apps.correios.com.br')
224 | .post('/SigepMasterJPA/AtendeClienteService/AtendeCliente')
225 | .replyWithFile(
226 | 200,
227 | path.join(__dirname, '/fixtures/response-cep-05010000-found.xml')
228 | )
229 |
230 | const correiosAltMock = nock('https://buscacepinter.correios.com.br')
231 | .post('/app/endereco/carrega-cep-endereco.php')
232 | .replyWithFile(
233 | 200,
234 | path.join(__dirname, '/fixtures/correios-alt-cep-05010000-found.json')
235 | )
236 |
237 | const viaCepMock = nock('https://viacep.com.br')
238 | .get('/ws/05010000/json/')
239 | .replyWithFile(
240 | 200,
241 | path.join(__dirname, '/fixtures/viacep-cep-05010000-found.json')
242 | )
243 |
244 | const wideNetMock = nock('https://cdn.apicep.com')
245 | .get('/file/apicep/05010-000.json')
246 | .replyWithFile(
247 | 200,
248 | path.join(__dirname, '/fixtures/widenet-cep-05010000-found.json')
249 | )
250 |
251 | return cep('05010000', { providers: ['correios'] })
252 | .then(address => {
253 | expect(address).to.deep.equal({
254 | cep: '05010000',
255 | state: 'SP',
256 | city: 'São Paulo',
257 | neighborhood: 'Perdizes',
258 | street: 'Rua Caiubi',
259 | service: 'correios'
260 | })
261 |
262 | expect(correiosMock.isDone()).to.be.equal(true)
263 | expect(correiosAltMock.isDone()).to.be.equal(false)
264 | expect(viaCepMock.isDone()).to.be.equal(false)
265 | expect(wideNetMock.isDone()).to.be.equal(false)
266 | })
267 | })
268 | })
269 |
270 | describe('and the providers param is [\'correios-alt\']', () => {
271 | it('should call only correios service', () => {
272 | const correiosMock = nock('https://apps.correios.com.br')
273 | .post('/SigepMasterJPA/AtendeClienteService/AtendeCliente')
274 | .replyWithFile(
275 | 200,
276 | path.join(__dirname, '/fixtures/response-cep-05010000-found.xml')
277 | )
278 |
279 | const correiosAltMock = nock('https://buscacepinter.correios.com.br')
280 | .post('/app/endereco/carrega-cep-endereco.php')
281 | .replyWithFile(
282 | 200,
283 | path.join(__dirname, '/fixtures/correios-alt-cep-05010000-found.json')
284 | )
285 |
286 | const viaCepMock = nock('https://viacep.com.br')
287 | .get('/ws/05010000/json/')
288 | .replyWithFile(
289 | 200,
290 | path.join(__dirname, '/fixtures/viacep-cep-05010000-found.json')
291 | )
292 |
293 | const wideNetMock = nock('https://cep.widenet.host')
294 | .get('/file/apicep/05010-000.json')
295 | .replyWithFile(
296 | 200,
297 | path.join(__dirname, '/fixtures/widenet-cep-05010000-found.json')
298 | )
299 |
300 | return cep('05010000', { providers: ['correios-alt']})
301 | .then(address => {
302 | expect(address).to.deep.equal({
303 | cep: '05010000',
304 | state: 'SP',
305 | city: 'São Paulo',
306 | neighborhood: 'Perdizes',
307 | street: 'Rua Caiubi',
308 | service: 'correios-alt'
309 | })
310 |
311 | expect(correiosMock.isDone()).to.be.equal(false)
312 | expect(correiosAltMock.isDone()).to.be.equal(true)
313 | expect(viaCepMock.isDone()).to.be.equal(false)
314 | expect(wideNetMock.isDone()).to.be.equal(false)
315 | })
316 | })
317 | })
318 |
319 | describe('and the providers param is [\'brasilapi\']', () => {
320 | it('should call only brasilapi service', () => {
321 | const correiosMock = nock('https://apps.correios.com.br')
322 | .post('/SigepMasterJPA/AtendeClienteService/AtendeCliente')
323 | .replyWithFile(
324 | 200,
325 | path.join(__dirname, '/fixtures/response-cep-05010000-found.xml')
326 | )
327 |
328 | const correiosAltMock = nock('https://buscacepinter.correios.com.br')
329 | .post('/app/endereco/carrega-cep-endereco.php')
330 | .replyWithFile(
331 | 200,
332 | path.join(__dirname, '/fixtures/correios-alt-cep-05010000-found.json')
333 | )
334 |
335 | const viaCepMock = nock('https://viacep.com.br')
336 | .get('/ws/05010000/json/')
337 | .replyWithFile(
338 | 200,
339 | path.join(__dirname, '/fixtures/viacep-cep-05010000-found.json')
340 | )
341 |
342 | const wideNetMock = nock('https://cdn.apicep.com')
343 | .get('/file/apicep/05010-000.json')
344 | .replyWithFile(
345 | 200,
346 | path.join(__dirname, '/fixtures/widenet-cep-05010000-found.json')
347 | )
348 |
349 | const brasilAPIMock = nock('https://brasilapi.com.br/')
350 | .get('/api/cep/v1/05010000')
351 | .replyWithFile(
352 | 200,
353 | path.join(__dirname, '/fixtures/brasilapi-cep-05010000-found.json')
354 | )
355 |
356 | return cep('05010000', { providers: ['brasilapi'] })
357 | .then(address => {
358 | expect(address).to.deep.equal({
359 | cep: '05010000',
360 | state: 'SP',
361 | city: 'São Paulo',
362 | neighborhood: 'Perdizes',
363 | street: 'Rua Caiubi',
364 | service: 'brasilapi'
365 | })
366 |
367 | expect(correiosMock.isDone()).to.be.equal(false)
368 | expect(correiosAltMock.isDone()).to.be.equal(false)
369 | expect(viaCepMock.isDone()).to.be.equal(false)
370 | expect(wideNetMock.isDone()).to.be.equal(false)
371 | expect(brasilAPIMock.isDone()).to.be.equal(true)
372 | })
373 | })
374 | })
375 |
376 | describe('and the providers param is [\'correios, viacep\']', () => {
377 | it('should call only correios and viacep services', () => {
378 | const correiosMock = nock('https://apps.correios.com.br')
379 | .post('/SigepMasterJPA/AtendeClienteService/AtendeCliente')
380 | .replyWithFile(
381 | 200,
382 | path.join(__dirname, '/fixtures/response-cep-05010000-found.xml')
383 | )
384 |
385 | const correiosAltMock = nock('https://buscacepinter.correios.com.br')
386 | .post('/app/endereco/carrega-cep-endereco.php')
387 | .replyWithFile(
388 | 200,
389 | path.join(__dirname, '/fixtures/correios-alt-cep-05010000-found.json')
390 | )
391 |
392 | const viaCepMock = nock('https://viacep.com.br')
393 | .get('/ws/05010000/json/')
394 | .replyWithFile(
395 | 200,
396 | path.join(__dirname, '/fixtures/viacep-cep-05010000-found.json')
397 | )
398 |
399 | const wideNetMock = nock('https://cdn.apicep.com')
400 | .get('/file/apicep/05010-000.json')
401 | .replyWithFile(
402 | 200,
403 | path.join(__dirname, '/fixtures/widenet-cep-05010000-found.json')
404 | )
405 |
406 | return cep('05010000', { providers: ['correios', 'viacep'] })
407 | .then(address => {
408 | expect(address).to.deep.equal({
409 | cep: '05010000',
410 | state: 'SP',
411 | city: 'São Paulo',
412 | neighborhood: 'Perdizes',
413 | street: 'Rua Caiubi',
414 | service: address.service
415 | })
416 |
417 | expect(viaCepMock.isDone()).to.be.equal(true)
418 | expect(correiosMock.isDone()).to.be.equal(true)
419 | expect(correiosAltMock.isDone()).to.be.equal(false)
420 | expect(wideNetMock.isDone()).to.be.equal(false)
421 | })
422 | })
423 | })
424 |
425 | describe('and the providers param is []', () => {
426 | it('should call all services', () => {
427 | const correiosMock = nock('https://apps.correios.com.br')
428 | .post('/SigepMasterJPA/AtendeClienteService/AtendeCliente')
429 | .replyWithFile(
430 | 200,
431 | path.join(__dirname, '/fixtures/response-cep-05010000-found.xml')
432 | )
433 |
434 | const correiosAltMock = nock('https://buscacepinter.correios.com.br')
435 | .post('/app/endereco/carrega-cep-endereco.php')
436 | .replyWithFile(
437 | 200,
438 | path.join(__dirname, '/fixtures/correios-alt-cep-05010000-found.json')
439 | )
440 |
441 | const viaCepMock = nock('https://viacep.com.br')
442 | .get('/ws/05010000/json/')
443 | .replyWithFile(
444 | 200,
445 | path.join(__dirname, '/fixtures/viacep-cep-05010000-found.json')
446 | )
447 |
448 | const wideNetMock = nock('https://cdn.apicep.com')
449 | .get('/file/apicep/05010-000.json')
450 | .replyWithFile(
451 | 200,
452 | path.join(__dirname, '/fixtures/widenet-cep-05010000-found.json')
453 | )
454 |
455 | return cep('05010000', { providers: [] })
456 | .then(address => {
457 | expect(address).to.deep.equal({
458 | cep: '05010000',
459 | state: 'SP',
460 | city: 'São Paulo',
461 | neighborhood: 'Perdizes',
462 | street: 'Rua Caiubi',
463 | service: address.service
464 | })
465 |
466 | expect(viaCepMock.isDone()).to.be.equal(true)
467 | expect(correiosMock.isDone()).to.be.equal(true)
468 | expect(correiosAltMock.isDone()).to.be.equal(true)
469 | expect(wideNetMock.isDone()).to.be.equal(true)
470 | })
471 | })
472 | })
473 |
474 | afterEach(() => {
475 | nock.cleanAll()
476 | })
477 | })
478 |
--------------------------------------------------------------------------------
/test/unit/cep-promise-timeout.spec.js:
--------------------------------------------------------------------------------
1 | 'use strict'
2 |
3 | import chai from 'chai'
4 | import chaiSubset from 'chai-subset'
5 | import nock from 'nock'
6 | import path from 'path'
7 |
8 | import cep from '../../src/cep-promise.js'
9 | import CepPromiseError from '../../src/errors/cep-promise.js'
10 |
11 | chai.use(chaiSubset)
12 |
13 | let expect = chai.expect
14 |
15 | describe('when invoked with timeout parameter', () => {
16 | before(() => {
17 | nock.disableNetConnect()
18 | })
19 |
20 | describe('and the providers exceed the timeout', () => {
21 | it('should reject with "service_error"', () => {
22 | nock('https://brasilapi.com.br/')
23 | .get('/api/cep/v1/05010000')
24 | .delay(3)
25 | .replyWithFile(
26 | 200,
27 | path.join(__dirname, '/fixtures/brasilapi-cep-05010000-found.json')
28 | )
29 | return cep('05010000', {timeout: 1, providers: ['brasilapi']})
30 | .then(() => expect(true).to.be.equal(false))
31 | .catch(error => {
32 | return expect(error)
33 | .to.be.an.instanceOf(CepPromiseError)
34 | .and.containSubset({
35 | name: 'CepPromiseError',
36 | message: 'Todos os serviços de CEP retornaram erro.',
37 | type: 'service_error',
38 | errors: [
39 | {
40 | message: 'Erro ao se conectar com o serviço BrasilAPI.',
41 | service: 'brasilapi'
42 | }
43 | ]
44 | })
45 | })
46 |
47 | })
48 | })
49 |
50 | afterEach(() => {
51 | nock.cleanAll()
52 | })
53 | })
54 |
--------------------------------------------------------------------------------
/test/unit/fixtures/brasilapi-cep-05010000-found.json:
--------------------------------------------------------------------------------
1 | {
2 | "cep": "05010000",
3 | "state": "SP",
4 | "city": "São Paulo",
5 | "neighborhood": "Perdizes",
6 | "street": "Rua Caiubi"
7 | }
--------------------------------------------------------------------------------
/test/unit/fixtures/brasilapi-cep-99999999-error.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "CepPromiseError",
3 | "message": "Todos os serviços de CEP retornaram erro.",
4 | "type": "service_error",
5 | "errors": [
6 | {
7 | "name": "ServiceError",
8 | "message": "CEP INVÁLIDO",
9 | "service": "correios"
10 | },
11 | {
12 | "name": "ServiceError",
13 | "message": "CEP não encontrado na base do ViaCEP.",
14 | "service": "viacep"
15 | }
16 | ]
17 | }
--------------------------------------------------------------------------------
/test/unit/fixtures/cep-aberto-05010000-found.json:
--------------------------------------------------------------------------------
1 | {
2 | "altitude": null,
3 | "bairro": "Perdizes",
4 | "cep": "05010000",
5 | "latitude": null,
6 | "longitude": null,
7 | "logradouro": "Rua Caiubi",
8 | "cidade": "São Paulo",
9 | "ddd": 11,
10 | "ibge": "3550308",
11 | "estado": "SP"
12 | }
--------------------------------------------------------------------------------
/test/unit/fixtures/cep-aberto-99999999-error.json:
--------------------------------------------------------------------------------
1 | {}
--------------------------------------------------------------------------------
/test/unit/fixtures/correios-alt-cep-05010000-found.json:
--------------------------------------------------------------------------------
1 | {
2 | "erro": false,
3 | "mensagem": "DADOS LOCALIZADOS COM SUCESSO.",
4 | "total": 1,
5 | "dados": [
6 | {
7 | "uf": "SP",
8 | "localidade": "São Paulo",
9 | "locNoSem": "",
10 | "locNu": "96681",
11 | "localidadeSubordinada": "",
12 | "logradouroDNEC": "Rua Caiubi",
13 | "logradouroTextoAdicional": "",
14 | "logradouroTexto": "",
15 | "bairro": "Perdizes",
16 | "baiNu": "",
17 | "nomeUnidade": "",
18 | "cep": "05010000",
19 | "tipoCep": "2",
20 | "numeroLocalidade": "96681",
21 | "situacao": "",
22 | "faixasCaixaPostal": [],
23 | "faixasCep": []
24 | }
25 | ]
26 | }
--------------------------------------------------------------------------------
/test/unit/fixtures/correios-alt-cep-99999999-error.json:
--------------------------------------------------------------------------------
1 | {
2 | "erro": false,
3 | "mensagem": "DADOS LOCALIZADOS COM SUCESSO.",
4 | "total": 1,
5 | "dados": [
6 | {
7 | "uf": "",
8 | "localidade": "",
9 | "locNoSem": "",
10 | "locNu": "",
11 | "localidadeSubordinada": "",
12 | "logradouroDNEC": "O CEP 99999-999 NAO FOI ENCONTRADO",
13 | "logradouroTextoAdicional": "",
14 | "logradouroTexto": "",
15 | "bairro": "",
16 | "baiNu": "",
17 | "nomeUnidade": "",
18 | "cep": "",
19 | "tipoCep": "",
20 | "numeroLocalidade": "",
21 | "situacao": "",
22 | "faixasCaixaPostal": [],
23 | "faixasCep": []
24 | }
25 | ]
26 | }
--------------------------------------------------------------------------------
/test/unit/fixtures/response-bad-xml.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
--------------------------------------------------------------------------------
/test/unit/fixtures/response-cep-05010000-found.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | Perdizes
6 | 05010000
7 | São Paulo
8 |
9 |
10 | Rua Caiubi
11 | 0
12 | SP
13 |
14 |
15 |
16 |
17 |
--------------------------------------------------------------------------------
/test/unit/fixtures/response-cep-invalid-format.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | soap:Server
5 | BUSCA DEFINIDA COMO EXATA, 0 CEP DEVE TER 8 DIGITOS
6 |
7 | BUSCA DEFINIDA COMO EXATA, 0 CEP DEVE TER 8 DIGITOS
8 |
9 |
10 |
11 |
12 |
--------------------------------------------------------------------------------
/test/unit/fixtures/response-cep-not-found.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | soap:Server
5 | CEP NAO ENCONTRADO
6 |
7 | CEP NAO ENCONTRADO
8 |
9 |
10 |
11 |
12 |
--------------------------------------------------------------------------------
/test/unit/fixtures/response-unknown-format.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | 9.7/10
5 | 9.2/10
6 | 5/5
7 |
8 |
9 |
10 |
--------------------------------------------------------------------------------
/test/unit/fixtures/viacep-cep-05010000-found.json:
--------------------------------------------------------------------------------
1 | {
2 | "cep": "05010-000",
3 | "logradouro": "Rua Caiubi",
4 | "complemento": "",
5 | "bairro": "Perdizes",
6 | "localidade": "São Paulo",
7 | "uf": "SP",
8 | "unidade": "",
9 | "ibge": "3550308",
10 | "gia": "1004"
11 | }
--------------------------------------------------------------------------------
/test/unit/fixtures/viacep-cep-99999999-error.json:
--------------------------------------------------------------------------------
1 | {
2 | "erro": true
3 | }
--------------------------------------------------------------------------------
/test/unit/fixtures/widenet-cep-05010000-found.json:
--------------------------------------------------------------------------------
1 | {
2 | "status": 200,
3 | "ok": true,
4 | "code": "05010-000",
5 | "state": "SP",
6 | "city": "São Paulo",
7 | "district": "Perdizes",
8 | "address": "Rua Caiubi",
9 | "statusText": "ok"
10 | }
11 |
--------------------------------------------------------------------------------
/test/unit/fixtures/widenet-cep-99999999-error.json:
--------------------------------------------------------------------------------
1 | {
2 | "status": 404,
3 | "ok": false,
4 | "message": "CEP não encontrado",
5 | "statusText": "not_found"
6 | }
7 |
--------------------------------------------------------------------------------