From 839c9f56f50e12c9585aa85cb457fed020809463 Mon Sep 17 00:00:00 2001 From: jvictordev1 Date: Fri, 24 Oct 2025 14:10:17 -0300 Subject: [PATCH 1/3] feat: adiciona validador de cpf --- package-lock.json | 4 +-- package.json | 2 +- src/index.ts | 1 + src/utils/cpfValidator.ts | 55 ++++++++++++++++++++++++++++++++++++++ tests/cpfValidator.test.ts | 32 ++++++++++++++++++++++ 5 files changed, 91 insertions(+), 3 deletions(-) create mode 100644 src/utils/cpfValidator.ts create mode 100644 tests/cpfValidator.test.ts diff --git a/package-lock.json b/package-lock.json index e9a6e8a..ca94521 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "@sysvale/foundry", - "version": "1.0.0", + "version": "1.5.1", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "@sysvale/foundry", - "version": "1.0.0", + "version": "1.5.1", "license": "Apache-2.0", "devDependencies": { "@eslint/js": "^9.32.0", diff --git a/package.json b/package.json index 363141f..9ce040e 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@sysvale/foundry", - "version": "1.5.1", + "version": "1.6.0", "description": "A forge for composables, helpers, and front-end utilities.", "type": "module", "main": "./dist/foundry.cjs.js", diff --git a/src/index.ts b/src/index.ts index 49cfc76..d4501ee 100644 --- a/src/index.ts +++ b/src/index.ts @@ -1,6 +1,7 @@ export * from './utils/pluralize'; export * from './utils/commaline'; export * from './utils/sanitizeForm'; +export * from './utils/cpfValidator'; export { maskCpf, removeCpfMask } from './formatters/cpf'; export { maskCns, removeCnsMask } from './formatters/cns'; export { maskPhone, removePhoneMask } from './formatters/phone'; diff --git a/src/utils/cpfValidator.ts b/src/utils/cpfValidator.ts new file mode 100644 index 0000000..d416581 --- /dev/null +++ b/src/utils/cpfValidator.ts @@ -0,0 +1,55 @@ +/* eslint-disable no-plusplus */ +function calcChecker1(firstNineDigits: string) { + let sum = 0; + + for (let j = 0; j < 9; ++j) { + sum += Number(firstNineDigits.charAt(j)) * (10 - j); + } + + const lastSumChecker1 = sum % 11; + const checker1 = lastSumChecker1 < 2 ? 0 : 11 - lastSumChecker1; + + return checker1; +} + +function calcChecker2(cpfWithChecker1: string) { + let sum = 0; + + for (let k = 0; k < 10; ++k) { + sum += Number(cpfWithChecker1.charAt(k)) * (11 - k); + } + const lastSumChecker2 = sum % 11; + const checker2 = lastSumChecker2 < 2 ? 0 : 11 - lastSumChecker2; + + return checker2; +} + +function cleaner(value: string) { + return value.replace(/[^\d]/g, ''); +} + +export function cpfValidator(value: string) { + if (!value) { + return true; + } + const cleanCPF = cleaner(value); + const firstNineDigits = cleanCPF.substring(0, 9); + const checker = cleanCPF.substring(9, 11); + let result = false; + + for (let i = 0; i < 10; i++) { + if (firstNineDigits + checker === Array(12).join(i.toString())) { + return false; + } + } + + const checker1 = calcChecker1(firstNineDigits); + const checker2 = calcChecker2(`${firstNineDigits}${checker1}`); + + if (checker.toString() === checker1.toString() + checker2.toString()) { + result = true; + } else { + result = false; + } + return result; +} diff --git a/tests/cpfValidator.test.ts b/tests/cpfValidator.test.ts new file mode 100644 index 0000000..69e152d --- /dev/null +++ b/tests/cpfValidator.test.ts @@ -0,0 +1,32 @@ +import { describe, expect, test } from 'vitest'; +import { cpfValidator } from '../src/utils/cpfValidator'; + +describe('cpfValidator()', () => { + test('retorna true quando string vazia é passada', () => { + expect(cpfValidator('')).toBe(true); + }); + + test('retorna false quando cpf inválido com máscara é passado', () => { + expect(cpfValidator('111.111.111-11')).toBe(false); + }); + + test('retorna true quando cpf válido com máscara é passado', () => { + expect(cpfValidator('252.512.510-09')).toBe(true); + }); + + test('retorna false quando cpf inválido sem máscara é passado', () => { + expect(cpfValidator('11111111111')).toBe(false); + }); + + test('retorna true quando cpf válido sem máscara é passado', () => { + expect(cpfValidator('25251251009')).toBe(true); + }); + + test('retorna false quando cpf possui menos que 11 dígitos', () => { + expect(cpfValidator('2525125100')).toBe(false); + }); + + test('retorna false quando cpf possui uma letra', () => { + expect(cpfValidator('25251251a09')).toBe(false); + }); +}); From 9e98b291e5a828454e3482718f6a5aafb2350133 Mon Sep 17 00:00:00 2001 From: jvictordev1 Date: Fri, 24 Oct 2025 14:48:00 -0300 Subject: [PATCH 2/3] =?UTF-8?q?docs:=20adiciona=20documenta=C3=A7=C3=A3o?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- docs/utils/cpfValidator.md | 74 ++++++++++++++++++++++++++++++++++++++ docs/utils/index.md | 6 ++++ src/utils/cpfValidator.ts | 9 +++-- 3 files changed, 87 insertions(+), 2 deletions(-) create mode 100644 docs/utils/cpfValidator.md diff --git a/docs/utils/cpfValidator.md b/docs/utils/cpfValidator.md new file mode 100644 index 0000000..bcf90bb --- /dev/null +++ b/docs/utils/cpfValidator.md @@ -0,0 +1,74 @@ +# CpfValidator + +Utilitário para validar CPFs com e sem máscara. + +## Instalação e Importação + +```typescript +import { cpfValidator } from '@sysvale/foundry'; +``` + +## Função + +### `cpfValidator()` + +Valida CPFs com e sem máscara, indicando se os mesmos são válidos. + +#### Sintaxes + +```typescript +cpfValidator(value: string): boolean +``` + +#### Parâmetros + +**Assinatura 1:** + +- **`value`** (`string`): CPF (com ou sem máscara) a ser validado + +
+ +#### Retorno + +`boolean` - Resultado da validação, `true` para CPF válido e `false` para inválido + +
+ +#### Exemplos + +**Usando CPF com máscara:** + +```typescript +cpfValidator('252.512.510-09'); // → true + +cpfValidator('000.000.000-00'); // → false +``` + +
+ +**Usando CPF sem máscara:** + +```typescript +cpfValidator('25251251009'); // → true + +cpfValidator('00000000000'); // → false +``` + +
+ +#### Tratamento de Erros + +A função lança um erro quando os parâmetros obrigatórios não são fornecidos: + +```typescript +// ❌ Erro: tipagem do parâmetro é inválida +cpfValidator(71234567823); +// → Error: Argument of type 'number' is not assignable to parameter of type 'string'. + +// ✅ Correto +cpfValidator('71234567823'); // → false +``` + +## Notas + +- A função é **type-safe** diff --git a/docs/utils/index.md b/docs/utils/index.md index 6230e10..c15b6b9 100644 --- a/docs/utils/index.md +++ b/docs/utils/index.md @@ -17,3 +17,9 @@ Função para formatar listas de strings com vírgulas e conjunção "e". Função para sanitizar dados de formulário e aplicar transformações antes de enviá-los ao backend. - [Documentação](./sanitizeForm.md) + +### cpfValidator() + +Função para validar CPFs com e sem máscara. + +- [Documentação](./cpfValidator.md) diff --git a/src/utils/cpfValidator.ts b/src/utils/cpfValidator.ts index d416581..cf18fe3 100644 --- a/src/utils/cpfValidator.ts +++ b/src/utils/cpfValidator.ts @@ -1,4 +1,3 @@ -/* eslint-disable no-plusplus */ function calcChecker1(firstNineDigits: string) { let sum = 0; @@ -28,7 +27,13 @@ function cleaner(value: string) { return value.replace(/[^\d]/g, ''); } -export function cpfValidator(value: string) { +/** + * Valida CPFs com e sem máscara. + * + * @param { string } value + * @returns { boolean } + */ +export function cpfValidator(value: string): boolean { if (!value) { return true; } From f637ac1df8e03529c0e649903009421dbdc6eeed Mon Sep 17 00:00:00 2001 From: jvictordev1 Date: Fri, 24 Oct 2025 15:19:24 -0300 Subject: [PATCH 3/3] =?UTF-8?q?feat:=20adiciona=20valida=C3=A7=C3=A3o=20de?= =?UTF-8?q?=20tipo=20durante=20execu=C3=A7=C3=A3o=20da=20fun=C3=A7=C3=A3o?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- docs/utils/cpfValidator.md | 2 +- src/utils/cpfValidator.ts | 5 +++++ tests/cpfValidator.test.ts | 4 ++++ 3 files changed, 10 insertions(+), 1 deletion(-) diff --git a/docs/utils/cpfValidator.md b/docs/utils/cpfValidator.md index bcf90bb..6eabd55 100644 --- a/docs/utils/cpfValidator.md +++ b/docs/utils/cpfValidator.md @@ -63,7 +63,7 @@ A função lança um erro quando os parâmetros obrigatórios não são fornecid ```typescript // ❌ Erro: tipagem do parâmetro é inválida cpfValidator(71234567823); -// → Error: Argument of type 'number' is not assignable to parameter of type 'string'. +// → Error: O tipo do parâmetro passado é inválido. // ✅ Correto cpfValidator('71234567823'); // → false diff --git a/src/utils/cpfValidator.ts b/src/utils/cpfValidator.ts index cf18fe3..9ba8842 100644 --- a/src/utils/cpfValidator.ts +++ b/src/utils/cpfValidator.ts @@ -34,9 +34,14 @@ function cleaner(value: string) { * @returns { boolean } */ export function cpfValidator(value: string): boolean { + if (typeof value !== 'string') { + throw new Error('O tipo do parâmetro passado é inválido.'); + } + if (!value) { return true; } + const cleanCPF = cleaner(value); const firstNineDigits = cleanCPF.substring(0, 9); const checker = cleanCPF.substring(9, 11); diff --git a/tests/cpfValidator.test.ts b/tests/cpfValidator.test.ts index 69e152d..e15e750 100644 --- a/tests/cpfValidator.test.ts +++ b/tests/cpfValidator.test.ts @@ -29,4 +29,8 @@ describe('cpfValidator()', () => { test('retorna false quando cpf possui uma letra', () => { expect(cpfValidator('25251251a09')).toBe(false); }); + + test('lança erro quando parâmetro é do tipo number', () => { + expect(() => cpfValidator(12341789324)).toThrowError(); + }); });