@cactus-agents/country-config
Registry de configuracoes por pais: validacao de documentos, mascaras de telefone, formatos de endereco, metodos de pagamento, requisitos legais e operadores KYC.
Instalacao
pnpm add @cactus-agents/country-config
Uso basico
import { getCountryConfig, hasCountryConfig } from "@cactus-agents/country-config";
const config = getCountryConfig("BRA");
// Validar documento
config.document.validate("123.456.789-09"); // true/false
config.document.format("12345678909"); // "123.456.789-09"
config.document.strip("123.456.789-09"); // "12345678909"
// Informacoes do pais
config.currency; // "BRL"
config.currencySymbol; // "R$"
config.phone.ddi; // "55"
config.phone.masks; // ["(00) 0000-0000", "(00) 00000-0000"]
config.legal.dataProtectionName; // "LGPD"
API publica
Funcoes do Registry
| Funcao | Descricao |
|---|---|
getCountryConfig(code) | Retorna CountryConfig pelo codigo alpha-3. Fallback para BRA com warning. |
getAllCountryCodes() | Retorna todos os codigos registrados: ["BRA", "CHL", "MEX", "PER", "FIN", "XYZ"] |
hasCountryConfig(code) | Verifica se um codigo esta registrado |
Catalogo global de paises
Funcoes para consultar o catalogo mundial de paises (250+ entradas, incluindo territorios, geradas a partir de dados ISO). Util para resolucao de alpha2/alpha3, moeda, DDI e outros metadados sem depender de maps hardcoded no template.
import {
getCountryCatalog,
getCountryByAlpha2,
getCountryByAlpha3,
getCountryByCode,
getCountriesByCurrency,
getCountryName,
getLocalizedCountryName,
getCurrencyByCountry,
getCurrentDdiByCountry,
} from "@cactus-agents/country-config";
| Funcao | Descricao |
|---|---|
getCountryCatalog() | Retorna o array completo de CountryCatalogEntry[] (250+ paises) |
getCountryByAlpha2(code) | Busca por alpha-2 (ex: "BR" → entry do Brasil) |
getCountryByAlpha3(code) | Busca por alpha-3 (ex: "BRA" → entry do Brasil) |
getCountryByCode(code) | Busca por alpha-2 ou alpha-3 (detecta automaticamente pelo tamanho) |
getCountriesByCurrency(currency) | Retorna todos os paises que usam a moeda (ex: "USD" → [USA, ECU, ...]) |
getCountryName(code) | Retorna nome padrao em ingles do pais (ex: "BRA" → "Brazil") |
getLocalizedCountryName(code, locale) | Retorna nome localizado via Intl.DisplayNames com fallback para ingles |
getCurrencyByCountry(alpha3) | Retorna a primeira moeda do pais (ex: "BRA" → "BRL") |
getCurrentDdiByCountry(alpha3) | Retorna o primeiro DDI do pais (ex: "BRA" → "55") |
Exemplo de uso no template:
// Antes: map hardcoded em app/config/payments/deposit.ts
const CURRENCY_COUNTRY_MAP = { BRL: "BRA", MXN: "MEX", ... };
// Agora: via SDK
import { getCountriesByCurrency, getCountryByAlpha3 } from "@cactus-agents/country-config";
const byCurrency = getCountriesByCurrency("BRL"); // → [{ alpha2: "BR", alpha3: "BRA", ... }]
const country = getCountryByAlpha3("BRA"); // → { alpha2: "BR", name: "Brazil", ... }
Helpers de telefone / DDI
Funcoes para listar DDIs mundiais, buscar DDI por pais, aplicar mascaras de telefone. Antes estavam em app/config/phone.config.ts no template — agora vivem no SDK.
import {
getDdiList,
findDdiByCountry,
findDdiByNumber,
applyPhoneMask,
getBestMask,
type DdiEntry,
} from "@cactus-agents/country-config";
| Funcao | Descricao |
|---|---|
getDdiList() | Retorna DdiEntry[] com todos os DDIs mundiais (gerado a partir do catalogo) |
findDdiByCountry(alpha3) | Busca DdiEntry pelo codigo alpha-3 do pais |
findDdiByNumber(ddi, countryCode?) | Busca DdiEntry por DDI exato (ex: "55"). countryCode e opcional para desambiguar DDI compartilhado |
applyPhoneMask(value, mask) | Aplica mascara de telefone (ex: "11999990000" + "(##) #####-####" → "(11) 99999-0000") |
getBestMask(masks, digitsLength) | Seleciona a melhor mascara para o tamanho dos digitos informados |
Exemplo de uso no template:
import { getDdiList, findDdiByCountry, applyPhoneMask, getBestMask } from "@cactus-agents/country-config";
const allDdis = getDdiList(); // lista completa para DdiSelect
const brazil = findDdiByCountry("BRA"); // { code: "BRA", ddi: "55", masks: [...] }
const mask = getBestMask(brazil.masks, 11); // "(##) #####-####"
const formatted = applyPhoneMask("11999990000", mask); // "(11) 99999-0000"
Helpers de nacionalidade (registro)
Funcoes para obter lista completa de nacionalidades (alpha-3 + OTHER) e default por pais da brand.
import {
getRegistrationNationalityCodes,
getDefaultRegistrationNationalityCode,
isRegistrationNationalityCode,
} from "@cactus-agents/country-config";
| Funcao | Descricao |
|---|---|
getRegistrationNationalityCodes() | Retorna lista completa de codigos alpha-3 (prioriza BRA/CHL/MEX/ARG/COL/PER/URY no topo) + OTHER |
getDefaultRegistrationNationalityCode(countryCode) | Retorna default de nacionalidade para o pais da brand ("CHL" → "CHL", desconhecido → "OTHER") |
isRegistrationNationalityCode(value) | Valida se o valor e um codigo aceito |
No template, os labels da lista devem vir do namespace countries no SDK de i18n (countries.nationalities.<ISO3>).
Validadores (uso direto)
Cada país tem funções validate, format e strip para seu tipo de documento ou campo bancário:
| País / Campo | Exports |
|---|---|
| Brasil (CPF) | validateCpf, formatCpf, stripCpf, CPF_MASK |
| Chile (RUT) | validateRut, formatRut, stripRut, RUT_MASK |
| México (CURP) | validateCurp, formatCurp, stripCurp, CURP_MASK |
| Peru (DNI) | validateDni, formatDni, stripDni, DNI_MASK |
| México (CLABE) | validateClabe, stripClabe, CLABE_LENGTH |
| Generic | validateGeneric, formatGeneric, stripGeneric |
CLABE (México)
A CLABE é o identificador bancário padrão mexicano — 18 dígitos numéricos.
import { validateClabe, stripClabe, CLABE_LENGTH } from "@cactus-agents/country-config";
validateClabe("032180000118359719") // → true
validateClabe("123") // → false (menos de 18 dígitos)
stripClabe("032-180-0001183-59719") // → "032180000118359719"
CLABE_LENGTH // → 18
Regra: Validadores bancários (CLABE, etc.) ficam no @cactus-agents/country-config, não no componente de UI. O template importa e usa — nunca redefine a regex.
Configs individuais (tree-shakeable)
braConfig, chlConfig, mexConfig, perConfig, finConfig, xyzConfig
Tipos
CountryConfig
interface CountryConfig {
code: string; // ISO 3166-1 alpha-3 (ex: "BRA")
alpha2: string; // ISO 3166-1 alpha-2 (ex: "BR")
currency: string; // ISO 4217 (ex: "BRL")
timezone: string; // IANA (ex: "America/Sao_Paulo")
languages: string[]; // Idiomas suportados
currencySymbol: string; // Simbolo (ex: "R$")
intlLocale: string; // BCP 47 (ex: "pt-BR")
displayDecimalDigits: number; // Casas decimais em valores monetarios (0 ou 2)
document: DocumentConfig;
address: AddressConfig;
phone: PhoneConfig;
payments: PaymentFeatures;
legal: LegalConfig;
kycOperators: string[];
}
DocumentConfig
type DocumentStoreEndpoint = "store-user-document" | "store-mex-document";
interface DocumentConfig {
name: string; // Label (ex: "CPF")
mask?: string; // Mascara (ex: "000.000.000-00")
placeholder?: string;
maxLength?: number;
validate: (value: string) => boolean;
format: (value: string) => string; // Raw → formatado
strip: (value: string) => string; // Formatado → raw
storeEndpoint: DocumentStoreEndpoint; // API endpoint para salvar documento
canRegisterFromAccount: boolean; // Se o usuario pode cadastrar documento na pagina de conta
}
storeEndpoint: Define qual endpoint da API usar para salvar o documento."store-user-document"para CPF (BRA),"store-mex-document"para todos os outros (RUT, CURP, DNI, Generic).canRegisterFromAccount: Controla se o formulario de cadastro de documento aparece na pagina de dados da conta. Todos os paises atualmente temtrue.
CountryCatalogEntry
interface CountryCatalogEntry {
name: string; // Nome comum em ingles (ex: "Brazil")
officialName: string; // Nome oficial (ex: "Federative Republic of Brazil")
alpha2: string; // ISO 3166-1 alpha-2 (ex: "BR")
alpha3: string; // ISO 3166-1 alpha-3 (ex: "BRA")
numericCode: string; // ISO 3166-1 numerico (ex: "076")
ddis: string[]; // Codigos de discagem sem "+" (ex: ["55"])
currencies: string[]; // ISO 4217 (ex: ["BRL"])
timezones: string[]; // IANA (ex: ["America/Sao_Paulo", ...])
region?: string; // Regiao (ex: "Americas")
subregion?: string; // Sub-regiao (ex: "South America")
emoji?: string; // Emoji da bandeira (ex: "🇧🇷")
}
DdiEntry
interface DdiEntry {
code: string; // ISO 3166-1 alpha-3 (ex: "BRA")
alpha2: string; // ISO 3166-1 alpha-2 (ex: "BR")
name: string; // Nome do pais (ex: "Brazil")
ddi: string; // DDI sem "+" (ex: "55")
masks: string[]; // Mascaras de telefone onde "#" = digito
}
Outros tipos
| Tipo | Descricao |
|---|---|
AddressConfig | Label/mascara do CEP, lista de estados, statesRequired |
StateEntry | { code: string; name: string } |
PhoneConfig | DDI e array de mascaras |
PaymentFeatures | Flags booleanas: pix, spei, oxxo, cryptoWallet, redirect, bankAccountSection |
LegalConfig | Lei de protecao de dados, termos obrigatorios, flag IRPF |
Paises suportados
| Pais | Codigo | Documento | Mascara | DDI | Pagamentos | Estados | Protecao | Decimais |
|---|---|---|---|---|---|---|---|---|
| Brasil | BRA | CPF | 000.000.000-00 | 55 | PIX, Redirect | 27 (obrigatorio) | LGPD | 2 |
| Chile | CHL | RUT | 00.000.000-X | 56 | Redirect | — | — | 0 |
| Mexico | MEX | CURP | AAAA000000AAAAAA00 | 52 | SPEI, OXXO, Redirect | 32 (obrigatorio) | Ley de Datos | 2 |
| Peru | PER | DNI | 00000000 | 51 | Redirect | 25 (opcional) | Ley de Datos | 2 |
| Finlandia | FIN | Passport/ID | — | 358 | Redirect | — | GDPR | 2 |
| Nigeria | NGA | NIN | 00000000000 | 234 | Crypto, Redirect | 37 (obrigatorio) | NDPA | 0 |
| Filipinas | PHL | Passport/ID | — | 63 | Redirect | — | — | 2 |
| Portugal | PRT | NIF | 000000000 | 351 | Redirect | — | GDPR | 2 |
| XYZ (generico) | XYZ | Passport/ID | — | 971 | Crypto, Redirect | — | — | 2 |
A coluna Decimais corresponde ao novo campo displayDecimalDigits: define quantas casas decimais aparecem em valores monetarios renderizados pelo formatMoney e pelos hooks useFormatMoney / useTransactions / useBalance do @cactus-agents/accounts/react. Backend continua armazenando em unidades menores (kobo para NGN, centavos para CLP/BRL, etc.) — a mudanca eh apenas de display. Nigeria e Chile usam 0 porque na pratica esses paises nao mostram subunidades; demais paises usam 2.
Algoritmos de validacao
CPF (Brasil)
Validacao modulo-11 com dois digitos verificadores. Pesos 10-2 para o primeiro digito e 11-2 para o segundo. Rejeita sequencias com todos os digitos iguais.
RUT (Chile)
Modulo-11 com multiplicadores ciclicos 2-7. Digito verificador pode ser 0-9 ou K. Aceita 7 a 9 caracteres (sem pontuacao).
CURP (Mexico)
Regex: ^[A-Z]{4}\d{6}[HM][A-Z]{2}[B-DF-HJ-NP-TV-Z]{3}[A-Z0-9]\d$
Estrutura: 4 letras (iniciais) + 6 digitos (nascimento YYMMDD) + sexo (H/M) + 2 letras (estado) + 3 consoantes + homoclave + digito verificador.
DNI (Peru)
Exatamente 8 digitos. Rejeita todos zeros.
Generic (Finlandia, XYZ)
Aceita qualquer valor nao vazio. Validacao real delegada ao backend/KYC.
Geracao do catalogo mundial
O arquivo src/world-catalog.data.ts contem os dados de 250+ paises e e gerado automaticamente a partir de fontes ISO:
pnpm generate:world-catalog
O script gera alpha2, alpha3, numericCode, DDIs, moedas, timezones, regiao e emoji para cada pais. Nao edite o arquivo manualmente — rode o script para regenerar.
Adicionando um novo país
- Criar
src/countries/xxx.tscom aCountryConfigcompleta - (Opcional) Criar validador em
src/validators/xxx.ts— ex: validador de conta bancária local - Registrar no
src/registry.ts - Re-exportar no
src/index.ts
O restante do sistema (front-web-base, validations, payments) pega automaticamente.
Arquivos relevantes
| Arquivo | Conteudo |
|---|---|
src/index.ts | Exports publicos (registry, catalog, phone, validators) |
src/registry.ts | Registry de CountryConfig por alpha-3 |
src/catalog.ts | Funcoes de busca no catalogo mundial |
src/phone.ts | Helpers de DDI e mascaras de telefone |
src/world-catalog.data.ts | Dados do catalogo mundial (gerado automaticamente) |
src/types.ts | Interfaces: CountryConfig, CountryCatalogEntry, DdiEntry, etc. |
src/countries/*.ts | Configs individuais por pais (BRA, CHL, MEX, PER, FIN, XYZ) |
src/validators/*.ts | Validadores de documentos (CPF, RUT, CURP, DNI, generic) |
scripts/generate-world-catalog.mjs | Script de geracao do catalogo |