Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
45 changes: 45 additions & 0 deletions docs/pt-br/utilities.md
Original file line number Diff line number Diff line change
Expand Up @@ -432,3 +432,48 @@ getHolidays(2024);
getHolidays({ year: 2024, stateCode: 'SP' });
// Inclui feriados nacionais mais feriados estaduais (ex: "Revolução Constitucionalista")
```

## isValidPassport

Verifica se um número de passaporte brasileiro é válido (2 letras maiúsculas seguidas de 6 dígitos).

```javascript
import { isValidPassport } from '@brazilian-utils/brazilian-utils';

isValidPassport('AB123456'); // true
isValidPassport('Ab123456'); // false
isValidPassport('12345678'); // false
```

## formatPassport

Formata um número de passaporte brasileiro (maiúsculas, sem símbolos).

```javascript
import { formatPassport } from '@brazilian-utils/brazilian-utils';

formatPassport('ab123456'); // 'AB123456'
formatPassport('AB-123.456'); // 'AB123456'
formatPassport('12345678'); // null
```

## generatePassport

Gera um número de passaporte brasileiro válido aleatoriamente.

```javascript
import { generatePassport } from '@brazilian-utils/brazilian-utils';

generatePassport(); // 'RY393097'
```

## parsePassport

Remove símbolos ('-', '.' e espaços) de um número de passaporte.

```javascript
import { parsePassport } from '@brazilian-utils/brazilian-utils';

parsePassport('AB-123.456'); // 'AB123456'
parsePassport(' AB 123 456 '); // 'AB123456'
```
45 changes: 45 additions & 0 deletions docs/utilities.md
Original file line number Diff line number Diff line change
Expand Up @@ -432,3 +432,48 @@ getHolidays(2024);
getHolidays({ year: 2024, stateCode: 'SP' });
// Includes national holidays plus state-specific holidays (e.g., "Revolução Constitucionalista")
```

## isValidPassport

Check if a Brazilian passport number is valid (2 uppercase letters followed by 6 digits).

```javascript
import { isValidPassport } from '@brazilian-utils/brazilian-utils';

isValidPassport('AB123456'); // true
isValidPassport('Ab123456'); // false
isValidPassport('12345678'); // false
```

## formatPassport

Format a Brazilian passport number (uppercase, without symbols).

```javascript
import { formatPassport } from '@brazilian-utils/brazilian-utils';

formatPassport('ab123456'); // 'AB123456'
formatPassport('AB-123.456'); // 'AB123456'
formatPassport('12345678'); // null
```

## generatePassport

Generate a random valid Brazilian passport number.

```javascript
import { generatePassport } from '@brazilian-utils/brazilian-utils';

generatePassport(); // 'RY393097'
```

## parsePassport

Remove symbols ('-', '.', and whitespaces) from a passport number.

```javascript
import { parsePassport } from '@brazilian-utils/brazilian-utils';

parsePassport('AB-123.456'); // 'AB123456'
parsePassport(' AB 123 456 '); // 'AB123456'
```
23 changes: 23 additions & 0 deletions src/format-passport/format-passport.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
import { beforeEach, describe, expect, test, vi } from "vitest";
import { isValidPassport } from "../is-valid-passport/is-valid-passport";
import { formatPassport } from "./format-passport";

describe("formatPassport", () => {
beforeEach(() => {
vi.restoreAllMocks();
});

describe("should return the formatted passport", () => {
test("when passport is valid", () => {
vi.spyOn({ isValidPassport }, "isValidPassport").mockReturnValue(true);
expect(formatPassport("yz 987654")).toBe("YZ987654");
});
});

describe("should return null", () => {
test("when passport is not valid", () => {
vi.spyOn({ isValidPassport }, "isValidPassport").mockReturnValue(false);
expect(formatPassport("acd12736")).toBeNull();
});
});
});
Comment on lines +5 to +23
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

tem como tu tirar o mock aqui?

19 changes: 19 additions & 0 deletions src/format-passport/format-passport.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
import { isValidPassport } from "../is-valid-passport/is-valid-passport";
import { parsePassport } from "../parse-passport/parse-passport";

/**
* Formats a Brazilian passport number for display.
* Returns the passport uppercased and without symbols, or null if invalid.
*
* @param passport - A Brazilian passport number (any case, possibly with symbols).
* @returns The formatted passport number (uppercase, no symbols), or null if invalid.
*
* @example
* formatPassport("Ab123456") // "AB123456"
* formatPassport("Ab-123456") // "AB123456"
* formatPassport("111111") // null
*/
export const formatPassport = (passport: string): string | null => {
const cleaned = parsePassport(passport.toUpperCase());
return isValidPassport(cleaned) ? cleaned : null;
Comment on lines +16 to +18
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nao acho que o format tenha q validar ou parsear, se fizer isso nao eh possivel fazer um format parcial como a gente permite nos outros formatters

};
11 changes: 11 additions & 0 deletions src/generate-passport/generate-passport.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
import { describe, expect, test } from "vitest";
import { isValidPassport } from "../is-valid-passport/is-valid-passport";
import { generatePassport } from "./generate-passport";

describe("generatePassport", () => {
test("should always generate a valid passport", () => {
for (let i = 0; i < 10_000; i++) {
expect(isValidPassport(generatePassport())).toBe(true);
}
});
});
Comment on lines +1 to +11
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

talvez seja um numero mt grande, n sei quanto a gente utilizou nos outros generates, mas seria bom dar uma olhada e usar o mesmo

20 changes: 20 additions & 0 deletions src/generate-passport/generate-passport.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
/**
* Generates a random valid Brazilian passport number.
*
* @returns A random valid passport number string (e.g. "RY393097").
*
* @example
* generatePassport() // "RY393097"
* generatePassport() // "ZS840088"
*/
export const generatePassport = (): string => {
const letters = Array.from({ length: 2 }, () =>
String.fromCharCode(65 + Math.floor(Math.random() * 26)),
).join("");

const digits = Array.from({ length: 6 }, () =>
Math.floor(Math.random() * 10),
).join("");

return `${letters}${digits}`;
};
4 changes: 4 additions & 0 deletions src/index.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,10 @@ const PUBLIC = [
"formatCurrency",
"formatPhone",
"parseCurrency",
"isValidPassport",
"generatePassport",
"parsePassport",
"formatPassport",
"formatPis",
"getStates",
"getCities",
Expand Down
4 changes: 4 additions & 0 deletions src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ export {
type FormatCurrencyOptions,
formatCurrency,
} from "./format-currency/format-currency";
export { formatPassport } from "./format-passport/format-passport";
export {
type FormatPhoneOptions,
formatPhone,
Expand All @@ -34,6 +35,7 @@ export {
export { generateBoleto } from "./generate-boleto/generate-boleto";
export { generateCnpj } from "./generate-cnpj/generate-cnpj";
export { generateCpf } from "./generate-cpf/generate-cpf";
export { generatePassport } from "./generate-passport/generate-passport";
export {
GetAddressInfoByCepError,
GetAddressInfoByCepNotFoundError,
Expand Down Expand Up @@ -65,6 +67,7 @@ export {
type IsValidMobilePhoneOptions,
isValidMobilePhone,
} from "./is-valid-mobile-phone/is-valid-mobile-phone";
export { isValidPassport } from "./is-valid-passport/is-valid-passport";
export {
type IsValidPhoneOptions,
isValidPhone,
Expand All @@ -73,6 +76,7 @@ export { isValidPis } from "./is-valid-pis/is-valid-pis";
export { isValidProcessoJuridico } from "./is-valid-processo-juridico/is-valid-processo-juridico";
export { isValidRenavam } from "./is-valid-renavam/is-valid-renavam";
export { parseCurrency } from "./parse-currency/parse-currency";
export { parsePassport } from "./parse-passport/parse-passport";

// ============================================================================
// DEPRECATED EXPORTS - Will be removed in v3.0.0
Expand Down
25 changes: 25 additions & 0 deletions src/is-valid-passport/is-valid-passport.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
import { describe, expect, test } from "vitest";
import { isValidPassport } from "./is-valid-passport";

describe("isValidPassport", () => {
describe("should return false", () => {
test("when passport is not a string", () => {
expect(isValidPassport(1 as unknown as string)).toBe(false);
});

test("when passport length is different from 8", () => {
expect(isValidPassport("1")).toBe(false);
});

test("when passport does not match the expected format", () => {
expect(isValidPassport("1112223334-")).toBe(false);
});
});

describe("should return true", () => {
test("when passport is valid", () => {
expect(isValidPassport("AA111111")).toBe(true);
expect(isValidPassport("CL125167")).toBe(true);
});
});
});
20 changes: 20 additions & 0 deletions src/is-valid-passport/is-valid-passport.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
/**
* Checks if a Brazilian passport number is valid.
* To be considered valid, the input must be a string containing exactly two
* alphabetical characters followed by exactly six numerical digits.
* This function does not verify if the input is a real passport number,
* as there are no checksums for the Brazilian passport.
*
* @param passport - The string containing the passport number to be checked.
* @returns True if the passport number is valid (2 letters followed by 6 digits).
*
* @example
* isValidPassport("Ab123456") // false - must be uppercase
* isValidPassport("AB123456") // true
* isValidPassport("12345678") // false
* isValidPassport("DC-221345") // false
*/
export const isValidPassport = (passport: string): boolean => {
if (typeof passport !== "string") return false;
return /^[A-Z]{2}[0-9]{6}$/.test(passport);
};
Comment on lines +17 to +20
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

aqui o passport pode ser string ou number, verifica como estao os outros

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

aqui como fazemos no formatCnpj for exemplo:

export const formatCnpj = (
	value: string | number,
	options?: FormatCnpjOptions,
): string =>
	format({
		pad: options?.pad,
		value: sanitize(value, options?.version),
		pattern: "00.000.000/0000-00",
	});

26 changes: 26 additions & 0 deletions src/parse-passport/parse-passport.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
import { describe, expect, test } from "vitest";
import { parsePassport } from "./parse-passport";

describe("parsePassport", () => {
describe("should return the string without symbols", () => {
test("when there are no symbols, returns the same string", () => {
expect(parsePassport("Ab123456")).toBe("Ab123456");
});

test("when there are spaces", () => {
expect(parsePassport(" AB 123 456 ")).toBe("AB123456");
});

test("when there are dashes", () => {
expect(parsePassport("-AB1-23-4-56-")).toBe("AB123456");
});

test("when there are dots", () => {
expect(parsePassport(".AB.1.23.456.")).toBe("AB123456");
});

test("when there are multiple symbols", () => {
expect(parsePassport(".A B.1.2-3.45 -. 6.")).toBe("AB123456");
});
});
});
13 changes: 13 additions & 0 deletions src/parse-passport/parse-passport.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
/**
* Removes symbols ('-', '.', and whitespaces) from a passport number.
*
* @param passport - The string containing a passport number.
* @returns The passport number with dashes, dots, and whitespaces removed.
*
* @example
* parsePassport("Ab123456") // "Ab123456"
* parsePassport("Ab-123456") // "Ab123456"
* parsePassport("Ab -. 123456") // "Ab123456"
*/
export const parsePassport = (passport: string): string =>
passport.replace(/[\s.-]/g, "");