Integracao ViaCEP
Service de consulta de enderecos brasileiros por CEP.
A integracao ViaCEP gera um service para consultar enderecos brasileiros a partir de um CEP. Usa a API publica viacep.com.br com cache Redis opcional.
ViaCEP Service
// apps/api/src/integrations/viacep/viacep.service.ts
export interface ViaCepAddress {
cep: string;
logradouro: string;
complemento: string;
bairro: string;
localidade: string;
uf: string;
ibge: string;
}
export class ViaCepService {
private baseUrl = 'https://viacep.com.br/ws';
constructor(private redis?: RedisService) {}
async findByCep(cep: string): Promise<ViaCepAddress> {
const cleaned = cep.replace(/\D/g, '');
if (cleaned.length !== 8) {
throw new Error('CEP deve ter 8 digitos');
}
// Cache (se Redis disponivel)
if (this.redis) {
const cached = await this.redis.get(`cep:${cleaned}`);
if (cached) return JSON.parse(cached);
}
const response = await fetch(`${this.baseUrl}/${cleaned}/json/`);
const data = await response.json();
if (data.erro) {
throw new Error('CEP nao encontrado');
}
// Cachear por 30 dias
if (this.redis) {
await this.redis.set(`cep:${cleaned}`, JSON.stringify(data), 'EX', 2592000);
}
return data;
}
}
Controller / Rota
// apps/api/src/integrations/viacep/viacep.controller.ts
// NestJS:
@Controller('api/cep')
export class ViaCepController {
constructor(private viaCepService: ViaCepService) {}
@Get(':cep')
async findByCep(@Param('cep') cep: string) {
return this.viaCepService.findByCep(cep);
}
}
// Express / Fastify:
app.get('/api/cep/:cep', async (req, res) => {
try {
const address = await viaCepService.findByCep(req.params.cep);
res.json(address);
} catch (error) {
res.status(400).json({ error: error.message });
}
});
Uso no frontend
// apps/web/src/hooks/useCep.ts
import { useState } from 'react';
export function useCep() {
const [address, setAddress] = useState(null);
const [loading, setLoading] = useState(false);
async function fetchCep(cep: string) {
if (cep.replace(/\D/g, '').length !== 8) return;
setLoading(true);
try {
const res = await fetch(`/api/cep/${cep}`);
const data = await res.json();
setAddress(data);
} catch {
setAddress(null);
} finally {
setLoading(false);
}
}
return { address, loading, fetchCep };
}
// Em um formulario:
function AddressForm() {
const { address, loading, fetchCep } = useCep();
return (
<div>
<input
placeholder="CEP"
onBlur={(e) => fetchCep(e.target.value)}
/>
{address && (
<>
<input value={address.logradouro} readOnly />
<input value={address.bairro} readOnly />
<input value={address.localidade} readOnly />
<input value={address.uf} readOnly />
</>
)}
</div>
);
}