@eusilvio/cep-lookup 1.1.0 → 1.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -21,6 +21,7 @@ Its agnostic design allows it to be used in any JavaScript environment with any
21
21
  - **HTTP Client Agnostic**: You provide the fetch function, giving you full control over the requests. Defaults to global `fetch` if not provided.
22
22
  - **Modular and Extensible Architecture**: Adding a new CEP data source is trivial.
23
23
  - **Fully Typed**: Developed with TypeScript to ensure type safety and a great developer experience.
24
+ - **Caching**: Built-in support for caching to avoid repeated requests for the same CEP.
24
25
 
25
26
  ## Installation
26
27
 
@@ -30,6 +31,8 @@ npm install @eusilvio/cep-lookup
30
31
 
31
32
  ## How to Use
32
33
 
34
+ `@eusilvio/cep-lookup` is designed to be straightforward. You can create a reusable instance of the `CepLookup` class with your desired settings or use the `lookupCep` function for a quick, one-off lookup. The library also includes a simple in-memory cache to avoid repeated requests, which you can use or replace with your own implementation.
35
+
33
36
  ### Example 1: Basic Usage
34
37
 
35
38
  ```typescript
@@ -105,6 +108,7 @@ Creates a new `CepLookup` instance.
105
108
  - `options`: A configuration object.
106
109
  - `providers` (Provider[], **required**): An array of providers that will be queried.
107
110
  - `fetcher` (Fetcher, _optional_): Your asynchronous function that fetches data from a URL. Defaults to global `fetch` if not provided.
111
+ - `cache` (Cache, _optional_): An instance of a cache that implements the `Cache` interface. Use `InMemoryCache` for a simple in-memory cache.
108
112
 
109
113
  ### `cepLookup.lookup<T = Address>(cep, mapper?): Promise<T>`
110
114
 
@@ -123,14 +127,7 @@ You can find more detailed examples in the `examples/` directory:
123
127
  - **React Component**: `examples/react-example.tsx`
124
128
  - **React Hook**: `examples/react-hook-example.ts`
125
129
  - **Angular Component/Service**: `examples/angular-example.ts`
126
-
127
- To run the examples, use the following commands:
128
-
129
- ```bash
130
- npm run example
131
- npm run custom-example
132
- npm run node-example
133
- ```
130
+ - **Cache Usage**: `examples/cache-example.ts`
134
131
 
135
132
  ## Creating a Custom Provider
136
133
 
@@ -0,0 +1,36 @@
1
+ import { Address } from '../types';
2
+ /**
3
+ * @interface Cache
4
+ * @description Defines the contract for a cache implementation.
5
+ */
6
+ export interface Cache {
7
+ get(key: string): Address | undefined;
8
+ set(key: string, value: Address): void;
9
+ clear(): void;
10
+ }
11
+ /**
12
+ * @class InMemoryCache
13
+ * @description A simple in-memory cache implementation for storing CEP lookups.
14
+ */
15
+ export declare class InMemoryCache implements Cache {
16
+ private cache;
17
+ /**
18
+ * @method get
19
+ * @description Retrieves an address from the cache.
20
+ * @param {string} key - The CEP to look up.
21
+ * @returns {Address | undefined} The cached address or undefined if not found.
22
+ */
23
+ get(key: string): Address | undefined;
24
+ /**
25
+ * @method set
26
+ * @description Stores an address in the cache.
27
+ * @param {string} key - The CEP to use as the cache key.
28
+ * @param {Address} value - The address to store.
29
+ */
30
+ set(key: string, value: Address): void;
31
+ /**
32
+ * @method clear
33
+ * @description Clears the entire cache.
34
+ */
35
+ clear(): void;
36
+ }
package/dist/index.d.ts CHANGED
@@ -1,5 +1,6 @@
1
1
  import { Address, Fetcher, Provider, CepLookupOptions } from "./types";
2
- export { Address, Fetcher, Provider, CepLookupOptions };
2
+ import { Cache, InMemoryCache } from "./cache";
3
+ export { Address, Fetcher, Provider, CepLookupOptions, Cache, InMemoryCache };
3
4
  /**
4
5
  * @class CepLookup
5
6
  * @description A class for looking up Brazilian postal codes (CEPs) using multiple providers.
@@ -8,6 +9,7 @@ export { Address, Fetcher, Provider, CepLookupOptions };
8
9
  export declare class CepLookup {
9
10
  private providers;
10
11
  private fetcher;
12
+ private cache?;
11
13
  /**
12
14
  * @constructor
13
15
  * @param {CepLookupOptions} options - The options for initializing the CepLookup instance.
@@ -32,6 +34,7 @@ export declare class CepLookup {
32
34
  * @param {string} options.cep - The CEP to be queried.
33
35
  * @param {Provider[]} options.providers - An array of `Provider` instances.
34
36
  * @param {Fetcher} [options.fetcher] - The `Fetcher` function. Defaults to global `fetch` if not provided.
37
+ * @param {Cache} [options.cache] - The `Cache` instance.
35
38
  * @param {(address: Address) => T} [options.mapper] - An optional function to transform the `Address` object.
36
39
  * @returns {Promise<T>} A Promise that resolves to the address.
37
40
  * @throws {Error} If the CEP is invalid or if all providers fail.
package/dist/index.js CHANGED
@@ -1 +1 @@
1
- "use strict";var c=Object.defineProperty;var a=Object.getOwnPropertyDescriptor;var u=Object.getOwnPropertyNames;var h=Object.prototype.hasOwnProperty;var l=(e,r)=>{for(var s in r)c(e,s,{get:r[s],enumerable:!0})},f=(e,r,s,t)=>{if(r&&typeof r=="object"||typeof r=="function")for(let o of u(r))!h.call(e,o)&&o!==s&&c(e,o,{get:()=>r[o],enumerable:!(t=a(r,o))||t.enumerable});return e};var v=e=>f(c({},"__esModule",{value:!0}),e);var T={};l(T,{CepLookup:()=>p,lookupCep:()=>k});module.exports=v(T);function m(e){let r=e.replace(/\D/g,"");if(r.length!==8)throw new Error("Invalid CEP. It must have 8 digits.");return r}var p=class{constructor(r){this.providers=r.providers,this.fetcher=r.fetcher||(async s=>{let t=await fetch(s);if(!t.ok)throw new Error(`HTTP error! status: ${t.status}`);return t.json()})}async lookup(r,s){let t=m(r),o=this.providers.map(i=>{let d=i.buildUrl(t);return this.fetcher(d).then(n=>i.transform(n)).then(n=>s?s(n):n)});return Promise.any(o)}};function k(e){let{cep:r,providers:s,fetcher:t,mapper:o}=e;return new p({providers:s,fetcher:t}).lookup(r,o)}0&&(module.exports={CepLookup,lookupCep});
1
+ import{Address as f,Fetcher as v,Provider as T,CepLookupOptions as w}from"./types";import{Cache as C,InMemoryCache as k}from"./cache";function P(i){const e=i.replace(/\D/g,"");if(e.length!==8)throw new Error("Invalid CEP. It must have 8 digits.");return e}class g{constructor(e){this.providers=e.providers,this.fetcher=e.fetcher||(async(r,s)=>{const o=await fetch(r,{signal:s});if(!o.ok)throw new Error(`HTTP error! status: ${o.status}`);return o.json()}),this.cache=e.cache}async lookup(e,r){const s=P(e);if(this.cache){const t=this.cache.get(s);if(t)return Promise.resolve(r?r(t):t)}const o=new AbortController,{signal:n}=o,h=this.providers.map(t=>{const d=t.buildUrl(s),m=new Promise((c,u)=>{let p;const a=()=>{clearTimeout(p),u(new DOMException("Aborted","AbortError"))};t.timeout?(p=setTimeout(()=>{n.removeEventListener("abort",a),u(new Error(`Timeout from ${t.name}`))},t.timeout),n.addEventListener("abort",a,{once:!0})):n.addEventListener("abort",a,{once:!0})}),l=this.fetcher(d,n).then(c=>t.transform(c)).then(c=>(this.cache&&this.cache.set(s,c),r?r(c):c));return Promise.race([l,m])});try{return await Promise.any(h)}finally{o.abort()}}}function E(i){const{cep:e,providers:r,fetcher:s,mapper:o,cache:n}=i;return new g({providers:r,fetcher:s,cache:n}).lookup(e,o)}export{f as Address,C as Cache,g as CepLookup,w as CepLookupOptions,v as Fetcher,k as InMemoryCache,T as Provider,E as lookupCep};
@@ -1 +1 @@
1
- "use strict";var e=Object.defineProperty;var a=Object.getOwnPropertyDescriptor;var c=Object.getOwnPropertyNames;var s=Object.prototype.hasOwnProperty;var m=(r,t)=>{for(var o in t)e(r,o,{get:t[o],enumerable:!0})},p=(r,t,o,d)=>{if(t&&typeof t=="object"||typeof t=="function")for(let i of c(t))!s.call(r,i)&&i!==o&&e(r,i,{get:()=>t[i],enumerable:!(d=a(t,i))||d.enumerable});return r};var P=r=>p(e({},"__esModule",{value:!0}),r);var f={};m(f,{apicepProvider:()=>l,brasilApiProvider:()=>v,viaCepProvider:()=>n});module.exports=P(f);var n={name:"ViaCEP",buildUrl:r=>`https://viacep.com.br/ws/${r}/json/`,transform:r=>{if(r.erro)throw new Error("CEP not found");return{cep:r.cep,state:r.uf,city:r.localidade,neighborhood:r.bairro,street:r.logradouro,service:"ViaCEP"}}};var v={name:"BrasilAPI",buildUrl:r=>`https://brasilapi.com.br/api/cep/v1/${r}`,transform:r=>({cep:r.cep,state:r.state,city:r.city,neighborhood:r.neighborhood,street:r.street,service:"BrasilAPI"})};var l={name:"ApiCEP",buildUrl:r=>`https://cdn.apicep.com/file/apicep/${r}.json`,transform:r=>({cep:r.code,state:r.state,city:r.city,neighborhood:r.district,street:r.address,service:"ApiCEP"})};0&&(module.exports={apicepProvider,brasilApiProvider,viaCepProvider});
1
+ export*from"./viacep";export*from"./brasil-api";export*from"./apicep";
package/dist/types.d.ts CHANGED
@@ -25,21 +25,24 @@ export interface Address {
25
25
  */
26
26
  export interface Provider {
27
27
  name: string;
28
+ timeout?: number;
28
29
  buildUrl: (cep: string) => string;
29
30
  transform: (response: any) => Address;
30
31
  }
31
32
  /**
32
- * @typedef {function(url: string): Promise<any>}
33
+ * @typedef {function(url: string, signal?: AbortSignal): Promise<any>}
33
34
  * @description A function that fetches data from a given URL and returns a Promise resolving to the response data.
34
35
  */
35
- export type Fetcher = (url: string) => Promise<any>;
36
+ export type Fetcher = (url: string, signal?: AbortSignal) => Promise<any>;
36
37
  /**
37
38
  * @interface CepLookupOptions
38
39
  * @description Options for initializing the `CepLookup` class.
39
40
  * @property {Provider[]} providers - An array of `Provider` instances to be used for CEP lookup.
40
41
  * @property {Fetcher} [fetcher] - The `Fetcher` function to be used for making HTTP requests. Defaults to global `fetch` if not provided.
41
42
  */
43
+ import { Cache } from "./cache";
42
44
  export interface CepLookupOptions {
43
45
  providers: Provider[];
44
46
  fetcher?: Fetcher;
47
+ cache?: Cache;
45
48
  }
package/package.json CHANGED
@@ -1,27 +1,34 @@
1
1
  {
2
2
  "name": "@eusilvio/cep-lookup",
3
- "version": "1.1.0",
3
+ "version": "1.2.0",
4
4
  "description": "A modern, flexible, and agnostic CEP lookup library written in TypeScript.",
5
- "main": "dist/index.js",
6
- "types": "dist/index.d.ts",
5
+ "main": "./dist/index.js",
6
+ "types": "./dist/index.d.ts",
7
+ "exports": {
8
+ ".": {
9
+ "import": "./dist/index.js",
10
+ "types": "./dist/index.d.ts"
11
+ },
12
+ "./providers": {
13
+ "import": "./dist/providers/index.js",
14
+ "types": "./dist/providers/index.d.ts"
15
+ }
16
+ },
17
+ "sideEffects": false,
7
18
  "files": [
8
19
  "dist"
9
20
  ],
10
21
  "publishConfig": {
11
22
  "access": "public"
12
23
  },
13
- "exports": {
14
- ".": "./dist/index.js",
15
- "./providers": "./dist/providers/index.js"
16
- },
17
24
  "scripts": {
18
25
  "clean": "rm -rf dist",
19
- "build": "npm run clean && tsc --emitDeclarationOnly --outDir dist && esbuild src/index.ts src/providers/index.ts --outdir=dist --bundle --platform=node --format=cjs",
20
- "build:prod": "npm run clean && tsc --emitDeclarationOnly --outDir dist && esbuild src/index.ts src/providers/index.ts --outdir=dist --bundle --platform=node --format=cjs --minify",
26
+ "type:check": "tsc --noEmit",
27
+ "build": "npm run clean && npm run type:check && npm run build:types && npm run build:js",
28
+ "build:types": "tsc --emitDeclarationOnly --outDir dist --rootDir src",
29
+ "build:js": "esbuild src/index.ts src/providers/index.ts --outdir=dist --outbase=src --format=esm --platform=neutral --target=esnext --minify",
21
30
  "test": "jest",
22
- "example": "ts-node -r tsconfig-paths/register examples/example.ts",
23
- "custom-example": "ts-node -r tsconfig-paths/register examples/custom-provider-example.ts",
24
- "node-example": "ts-node -r tsconfig-paths/register examples/node-example.ts"
31
+ "cache-example": "ts-node -r tsconfig-paths/register examples/cache-example.ts"
25
32
  },
26
33
  "keywords": [
27
34
  "cep",
@@ -44,6 +51,7 @@
44
51
  "@types/jest": "^30.0.0",
45
52
  "esbuild": "^0.20.2",
46
53
  "jest": "^30.1.3",
54
+ "p-limit": "^2.3.0",
47
55
  "ts-jest": "^29.4.4",
48
56
  "ts-node": "^10.9.2",
49
57
  "tsconfig-paths": "^4.2.0",