npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@hed-hog/contact

v0.0.304

Published

```markdown # @hed-hog/contact

Readme

# @hed-hog/contact

## 1. Visão geral do módulo

O módulo `@hed-hog/contact` gerencia informações relacionadas a contatos, documentos, pessoas e seus tipos, além das relações entre pessoas. Ele oferece funcionalidades completas de CRUD para tipos de contato, tipos de documento, pessoas e suas relações, com suporte a internacionalização (locales), paginação e controle de acesso baseado em roles.

## 2. Escopo e responsabilidades

- Gerenciar tipos de contato (`contact_type`).
- Gerenciar tipos de documento (`document_type`).
- Gerenciar pessoas (`person`), incluindo contatos, documentos, endereços e metadados.
- Gerenciar tipos de relação entre pessoas (`person_relation_type`), que são fixos e imutáveis via API.
- Validar regras específicas de negócio, como unicidade de contatos primários e restrições para registro de empresas.
- Suportar autenticação e autorização baseada em roles (`admin`, `admin-contact`).
- Suportar internacionalização para mensagens e dados localizados.
- Integrar com serviços de paginação, banco de dados Prisma e envio de emails.

## 3. Endpoints

### Person Contact Type (`/person-contact-type`)

| Método | Path                   | Autenticação                          | Descrição                          |
|--------|------------------------|-------------------------------------|----------------------------------|
| GET    | `/person-contact-type` | Autenticado (roles: admin, admin-contact) | Lista tipos de contato com paginação e locale. |
| GET    | `/person-contact-type/:id` | Autenticado (roles: admin, admin-contact) | Obtém tipo de contato por ID com locale. |
| POST   | `/person-contact-type` | Autenticado (roles: admin, admin-contact) | Cria um novo tipo de contato. |
| PATCH  | `/person-contact-type/:id` | Autenticado (roles: admin, admin-contact) | Atualiza um tipo de contato existente. |
| DELETE | `/person-contact-type` | Autenticado (roles: admin, admin-contact) | Exclui tipos de contato por IDs. |

**Parâmetros e corpo:**

- `CreateDTO` para criação:
  - `code` (string): código do tipo de contato.
  - `locale` (objeto): nomes localizados, ex: `{ "pt": { "name": "Telefone" }, "en": { "name": "Phone" } }`.

- `UpdateDTO` para atualização: campos parciais de `CreateDTO`, `locale` opcional.

**Resposta:**

- Listagem paginada ou objeto do tipo criado/atualizado.
- Erros:
  - 400 Bad Request: dados inválidos, `locale` vazio, IDs para exclusão não informados.
  - 404 Not Found: tipo de contato não encontrado.

---

### Person Document Type (`/person-document-type`)

| Método | Path                   | Autenticação                          | Descrição                          |
|--------|------------------------|-------------------------------------|----------------------------------|
| GET    | `/person-document-type` | Autenticado (roles: admin, admin-contact) | Lista tipos de documento com paginação e locale. |
| GET    | `/person-document-type/:id` | Autenticado (roles: admin, admin-contact) | Obtém tipo de documento por ID com locale. |
| POST   | `/person-document-type` | Autenticado (roles: admin, admin-contact) | Cria um novo tipo de documento. |
| PATCH  | `/person-document-type/:id` | Autenticado (roles: admin, admin-contact) | Atualiza um tipo de documento existente. |
| DELETE | `/person-document-type` | Autenticado (roles: admin, admin-contact) | Exclui tipos de documento por IDs. |

**Parâmetros e corpo:**

- `CreateDTO` para criação:
  - `code` (string): código do tipo de documento.
  - `country_code` (string): código do país.
  - `is_unique` (boolean): indica se o documento é único.
  - `locale` (objeto): nomes localizados.

- `UpdateDTO` para atualização: campos parciais de `CreateDTO`, `locale` opcional.

**Resposta:**

- Listagem paginada ou objeto do tipo criado/atualizado.
- Erros:
  - 400 Bad Request: dados inválidos, `locale` vazio, IDs para exclusão não informados.
  - 404 Not Found: tipo de documento não encontrado.

---

### Person (`/person`)

| Método | Path                   | Autenticação                          | Descrição                          |
|--------|------------------------|-------------------------------------|----------------------------------|
| GET    | `/person`              | Autenticado (roles: admin, admin-contact) | Lista pessoas com filtros e paginação. |
| GET    | `/person/stats`        | Autenticado (roles: admin, admin-contact) | Estatísticas de pessoas. |
| GET    | `/person/owner-options`| Autenticado (roles: admin, admin-contact) | Lista usuários possíveis para atribuição como responsáveis. |
| GET    | `/person/:id`          | Autenticado (roles: admin, admin-contact) | Obtém pessoa por ID com detalhes. |
| GET    | `/person/avatar/:id`   | Pública                             | Abre avatar público pelo ID do arquivo. |
| POST   | `/person`              | Autenticado (roles: admin, admin-contact) | Cria uma nova pessoa. |
| PATCH  | `/person/:id`          | Autenticado (roles: admin, admin-contact) | Atualiza pessoa existente. |
| DELETE | `/person`              | Autenticado (roles: admin, admin-contact) | Exclui pessoas por IDs. |

**Parâmetros e corpo:**

- `CreateDTO` para criação:
  - `name` (string): nome da pessoa.
  - `type` (enum: individual, company): tipo da pessoa.
  - `status` (enum: active, inactive): status da pessoa.
  - Campos opcionais: `avatar_id`, `birth_date`, `gender`, `job_title`, `trade_name`, `foundation_date`, `legal_nature`, `notes`, `employer_company_id`.

- `UpdateAllPersonDTO` para atualização:
  - Inclui todos os campos do `CreateDTO`.
  - Arrays para `contacts`, `addresses`, `documents` com seus respectivos campos e validações.
  - Validação para garantir apenas um contato, endereço ou documento primário por tipo.
  - Campos opcionais `branch_ids` (array de números) e `headquarter_id` (número).

**Resposta:**

- Listagem paginada, objeto da pessoa criada/atualizada, ou estatísticas.
- Erros:
  - 400 Bad Request: dados inválidos, mais de um primário por tipo, referência inválida, registro de empresa desabilitado, IDs para exclusão não informados.
  - 404 Not Found: pessoa não encontrada, avatar não encontrado.

---

### Person Relation Type (`/person-relation-type`)

| Método | Path                   | Autenticação                          | Descrição                          |
|--------|------------------------|-------------------------------------|----------------------------------|
| GET    | `/person-relation-type` | Autenticado (roles: admin, admin-contact) | Lista tipos fixos de relação entre pessoas. |
| GET    | `/person-relation-type/:id` | Autenticado (roles: admin, admin-contact) | Obtém tipo de relação por ID. |
| POST   | `/person-relation-type` | Autenticado (roles: admin, admin-contact) | **Não suportado** (tipos fixos). |
| PATCH  | `/person-relation-type/:id` | Autenticado (roles: admin, admin-contact) | **Não suportado** (tipos fixos). |
| DELETE | `/person-relation-type` | Autenticado (roles: admin, admin-contact) | **Não suportado** (tipos fixos). |

**Observação:** Tipos de relação são fixos e não podem ser criados, atualizados ou deletados via API. Tentativas resultam em erro 400.

---

## 4. Regras de autenticação e autorização

- A maioria dos endpoints requer autenticação via JWT.
- Acesso restrito a usuários com roles `admin` ou `admin-contact`.
- O endpoint de avatar (`/person/avatar/:id`) é público.
- Tentativas de criar, atualizar ou deletar tipos de relação entre pessoas resultam em erro 400, pois são fixos.

## 5. Estruturas de request/response

### CreateDTO (Person Contact Type)

```json
{
  "code": "string",
  "locale": {
    "pt": { "name": "string" },
    "en": { "name": "string" }
  }
}

UpdateDTO (Person Contact Type)

Campos parciais de CreateDTO, locale opcional.


CreateDTO (Person Document Type)

{
  "code": "string",
  "country_code": "string",
  "is_unique": true,
  "locale": {
    "pt": { "name": "string" },
    "en": { "name": "string" }
  }
}

UpdateDTO (Person Document Type)

Campos parciais de CreateDTO, locale opcional.


CreateDTO (Person)

{
  "name": "string",
  "type": "individual | company",
  "status": "active | inactive",
  "avatar_id": "number | null",
  "birth_date": "string (date) | null",
  "gender": "male | female | other | null",
  "job_title": "string | null",
  "trade_name": "string | null",
  "foundation_date": "string (date) | null",
  "legal_nature": "string | null",
  "notes": "string | null",
  "employer_company_id": "number | null"
}

UpdateAllPersonDTO (Person)

Inclui todos os campos do CreateDTO e:

  • contacts: array de objetos com id?, value, is_primary, contact_type_id.
  • addresses: array de objetos com id?, line1, line2?, city, state, country_code?, postal_code?, is_primary, address_type.
  • documents: array de objetos com id?, value, document_type_id.
  • branch_ids?: array de números.
  • headquarter_id?: número opcional para empresa.

6. Erros comuns

  • 400 Bad Request

    • Falta de campos obrigatórios (ex: locale vazio).
    • Tentativa de criar/atualizar tipos de relação (não suportado).
    • Mais de um contato, endereço ou documento primário do mesmo tipo.
    • Tentativa de registrar empresa quando registro está desabilitado.
    • Referência inválida para empresa ou endereço.
    • IDs para exclusão não informados.
  • 404 Not Found

    • Entidade não encontrada por ID (pessoa, tipo de contato, tipo de documento).
    • Pessoa do tipo empresa não encontrada quando registro está desabilitado.
    • Avatar não encontrado.

7. Banco de dados (tabelas YAML)

contact

  • Finalidade: Armazena contatos associados a pessoas.
  • Colunas:
    • id (PK)
    • person_id (FK para person.id)
    • contact_type_id (FK para contact_type.id)
    • value (string)
    • is_primary (boolean, default: false)
    • created_at, updated_at
  • Índices:
    • Único em (person_id, contact_type_id, is_primary) onde is_primary = true.

contact_type

  • Finalidade: Define tipos de contato.
  • Colunas:
    • id (PK)
    • name (locale_varchar, com traduções pt/en)
    • code (string)
    • created_at, updated_at

document

  • Finalidade: Armazena documentos associados a pessoas.
  • Colunas:
    • id (PK)
    • person_id (FK para person.id)
    • document_type_id (FK para document_type.id)
    • value (string)
    • created_at, updated_at

document_type

  • Finalidade: Define tipos de documento.
  • Colunas:
    • id (PK)
    • name (locale_varchar, pt/en)
    • code (string)
    • country_code (string)
    • is_unique (boolean)
    • created_at, updated_at

person

  • Finalidade: Armazena pessoas (indivíduos e empresas).
  • Colunas:
    • id (PK)
    • name (string)
    • type (enum: individual, company)
    • status (enum: active, inactive)
    • avatar_id (FK para file.id, nullable, onDelete SET NULL)
    • created_at, updated_at

person_address

  • Finalidade: Associação entre pessoas e endereços.
  • Colunas:
    • id (PK)
    • person_id (FK para person.id)
    • address_id (FK para address.id)
    • created_at, updated_at
  • Índices:
    • Único em address_id.

person_company

  • Finalidade: Dados específicos para pessoas do tipo empresa.
  • Colunas:
    • id (PK, FK para person.id)
    • trade_name (string, nullable)
    • foundation_date (date, nullable)
    • legal_nature (string, nullable)
    • headquarter_id (FK para person_company.id, nullable, onDelete SET NULL, onUpdate CASCADE)
    • created_at, updated_at
  • Índices:
    • Em headquarter_id

person_individual

  • Finalidade: Dados específicos para pessoas do tipo indivíduo.
  • Colunas:
    • id (PK, FK para person.id)
    • birth_date (date, nullable)
    • gender (enum: male, female, other, nullable)
    • job_title (string, nullable)
    • created_at, updated_at

person_individual_relation

  • Finalidade: Relações entre pessoas do tipo indivíduo.
  • Colunas:
    • id (PK)
    • person_individual_id (FK para person_individual.id, onDelete CASCADE, onUpdate CASCADE)
    • related_person_individual_id (FK para person_individual.id, onDelete CASCADE, onUpdate CASCADE)
    • relation_type (enum: parent, child, spouse, sibling, guardian, dependent, partner, responsible, emergency_contact, other)
    • created_at, updated_at
  • Índices:
    • Em person_individual_id, related_person_individual_id, relation_type
    • Único em (person_individual_id, related_person_individual_id, relation_type)

person_metadata

  • Finalidade: Metadados arbitrários associados a pessoas.
  • Colunas:
    • id (PK)
    • person_id (FK para person.id)
    • key (string)
    • value (json)
    • created_at, updated_at

8. Regras de negócio relevantes

  • Tipos de relação entre pessoas são fixos e não podem ser alterados via API.
  • Apenas um contato, endereço ou documento pode ser marcado como primário por tipo para uma pessoa.
  • Registro de pessoas do tipo empresa pode ser desabilitado via configuração contact-allow-company-registration.
  • Ao criar ou atualizar pessoa, validações garantem integridade das relações e dados.
  • Exclusão de pessoas remove em cascata contatos, documentos, endereços, relações e metadados associados.
  • Avatar público pode ser acessado via endpoint público, com cache control configurado.
  • Ao criar pessoa sem usuário, é enviado email com link para criação de conta, com token JWT válido por 1 dia.
  • Metadados como notes e employer_company_id são armazenados separadamente e sincronizados.
  • Empresas não podem ser vinculadas como sua própria matriz (headquarter).
  • Apenas empresas podem ser vinculadas como matriz ou filial.
  • Validações específicas impedem inconsistências nas relações de empresas e indivíduos.
  • Atualização de pessoa sincroniza contatos, endereços e documentos, criando, atualizando ou removendo conforme necessário.
  • Pesquisa de pessoas suporta filtros por nome, tipo, status, e busca por dados normalizados em contatos, documentos e endereços.

9. Guia rápido de uso (exemplos)

Criar tipo de contato

POST /person-contact-type
Authorization: Bearer <token>
Content-Type: application/json

{
  "code": "phone",
  "locale": {
    "pt": { "name": "Telefone" },
    "en": { "name": "Phone" }
  }
}

Atualizar tipo de documento

PATCH /person-document-type/3
Authorization: Bearer <token>
Content-Type: application/json

{
  "is_unique": true,
  "locale": {
    "pt": { "name": "CPF" },
    "en": { "name": "CPF" }
  }
}

Listar pessoas com filtro e paginação

GET /person?search=joao&type=individual&status=active&page=1&pageSize=20
Authorization: Bearer <token>

Criar pessoa

POST /person
Authorization: Bearer <token>
Content-Type: application/json

{
  "name": "João Silva",
  "type": "individual",
  "status": "active",
  "birth_date": "1980-05-10",
  "gender": "male",
  "contacts": [
    {
      "value": "[email protected]",
      "is_primary": true,
      "contact_type_id": 1
    }
  ],
  "addresses": [
    {
      "line1": "Rua A, 123",
      "city": "São Paulo",
      "state": "SP",
      "country_code": "BRA",
      "postal_code": "01000-000",
      "is_primary": true,
      "address_type": "residential"
    }
  ],
  "documents": [
    {
      "value": "123.456.789-00",
      "document_type_id": 1
    }
  ]
}

Atualizar pessoa

PATCH /person/10
Authorization: Bearer <token>
Content-Type: application/json

{
  "name": "João da Silva",
  "status": "active",
  "contacts": [
    {
      "id": 5,
      "value": "[email protected]",
      "is_primary": true,
      "contact_type_id": 1
    }
  ]
}

Excluir pessoas

DELETE /person
Authorization: Bearer <token>
Content-Type: application/json

{
  "ids": [10, 11, 12]
}

Este README documenta as funcionalidades principais do módulo @hed-hog/contact com base no código e definições atuais. Para detalhes adicionais, consulte o código fonte e as definições de DTOs.