@azify/cpf-cnpj 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md ADDED
@@ -0,0 +1,43 @@
1
+ # @azify/cpf-cnpj
2
+
3
+ Validation, formatting, and comparison of CPF/CNPJ, including support for alphanumeric CNPJ (effective Jul/2026).
4
+
5
+ ## Installation
6
+
7
+ ```
8
+ npm install @azify/cpf-cnpj
9
+ ```
10
+
11
+ ## Usage
12
+
13
+ ```ts
14
+ import { cpf, cnpj, taxpayer } from '@azify/cpf-cnpj'
15
+
16
+ cpf.isValid('529.982.247-25') // true
17
+ cpf.isValid('111.111.111-11') // false (invalid check digit)
18
+ cpf.format('52998224725') // '529.982.247-25'
19
+ cpf.format('123') // null (doesn't have 11 digits)
20
+ cpf.compare(a, b) // true | false | null (null if a or b is invalid)
21
+ cpf.clean('529.982.247-25') // '52998224725'
22
+
23
+ cnpj.isValid('11.444.777/0001-61') // true
24
+ cnpj.isValid('AB123CD4501E66') // true (alphanumeric CNPJ)
25
+ cnpj.isValid('11.111.111/1111-11') // false (invalid check digit)
26
+ cnpj.format('11444777000161') // '11.444.777/0001-61'
27
+ cnpj.format('AB123CD4501E66') // 'AB.123.CD4/501E-66'
28
+ cnpj.format('123') // null (doesn't have 14 positions)
29
+ cnpj.compare(a, b) // true | false | null (null if a or b is invalid)
30
+ cnpj.clean('11.444.777/0001-61') // '11444777000161'
31
+
32
+ taxpayer.type('52998224725') // 'cpf' | 'cnpj' | null (null if it's not a valid CPF or CNPJ)
33
+ taxpayer.isValid('invalid') // false
34
+ taxpayer.format('invalid') // null
35
+ taxpayer.compare(a, b) // true | false | null (null if a or b is invalid)
36
+ taxpayer.clean(value) // normalizes CPF or CNPJ (alphanumeric)
37
+ ```
38
+
39
+ ### About `null` returns
40
+
41
+ - `format` returns `null` when the value doesn't have the expected length (CPF: 11 digits; CNPJ: 14 positions). It **does not** check the verification digit — a well-formed CPF/CNPJ with an invalid checksum is still formatted (e.g., `cpf.format('00000000000')` returns `'000.000.000-00'`). Use `isValid` when you need to guarantee the document is actually valid.
42
+ - `compare` returns `null` (not `false`) when **either** of the two values is invalid — this lets you distinguish "different documents" from "cannot compare".
43
+ - `taxpayer.type` returns `null` when the value is neither a valid CPF nor a valid CNPJ (it doesn't distinguish "not a CPF" from "not a CNPJ").
@@ -0,0 +1,100 @@
1
+ /**
2
+ * CPF/CNPJ utilities.
3
+ *
4
+ * Exposes the `cpf` / `cnpj` objects (with `isValid`, `format`, `compare`, `clean`),
5
+ * plus a `taxpayer` object for documents of unknown type (`type`, `isValid`, `format`, `compare`,
6
+ * `clean`). CNPJ validation and formatting also support the alphanumeric CNPJ
7
+ * (effective Jul/2026). CPF stays numeric.
8
+ */
9
+ declare function keepDigits(value: string): string;
10
+ declare function keepAlphanumeric(value: string): string;
11
+ /**
12
+ * @description Validates a CPF (always numeric), including the check digits.
13
+ * @param value - CPF with or without mask
14
+ * @returns true if the CPF is valid
15
+ */
16
+ declare function isValidCpf(value: string): boolean;
17
+ /**
18
+ * @description Masks a CPF as `XXX.XXX.XXX-XX`.
19
+ * @param value - CPF with or without mask
20
+ * @returns Masked CPF, or null if it is not a well-formed (11-digit) CPF
21
+ */
22
+ declare function formatCpf(value: string): string | null;
23
+ /**
24
+ * @description Compares two CPFs, returning null if either is invalid.
25
+ * @param cpf1 - First CPF to compare
26
+ * @param cpf2 - Second CPF to compare
27
+ * @returns true if equal, false if different, null if either CPF is invalid
28
+ */
29
+ declare function compareCpf(cpf1: string, cpf2: string): boolean | null;
30
+ /**
31
+ * @description Validates a numeric or alphanumeric CNPJ, including the check
32
+ * digits (mod-11 calc with character value = ASCII - 48).
33
+ * @param value - CNPJ with or without mask
34
+ * @returns true if the CNPJ is valid
35
+ */
36
+ declare function isValidCnpj(value: string): boolean;
37
+ /**
38
+ * @description Masks a numeric or alphanumeric CNPJ as `XX.XXX.XXX/XXXX-XX`.
39
+ * @param value - CNPJ with or without mask
40
+ * @returns Masked CNPJ, or null if it is not a well-formed (14-position) CNPJ
41
+ */
42
+ declare function formatCnpj(value: string): string | null;
43
+ /**
44
+ * @description Compares two CNPJs, returning null if either is invalid.
45
+ * @param cnpj1 - First CNPJ to compare
46
+ * @param cnpj2 - Second CNPJ to compare
47
+ * @returns true if equal, false if different, null if either CNPJ is invalid
48
+ */
49
+ declare function compareCnpj(cnpj1: string, cnpj2: string): boolean | null;
50
+ /**
51
+ * @description Compare two CPF or CNPJ
52
+ * @param taxpayer1 - CPF or CNPJ to compare
53
+ * @param taxpayer2 - CPF or CNPJ to compare
54
+ * @returns true if CPF or CNPJ are equal, false if not, null if either is invalid
55
+ */
56
+ declare function compareTaxpayer(taxpayer1: string, taxpayer2: string): boolean | null;
57
+ /**
58
+ * @description Determines the type of a taxpayer document, validating it.
59
+ *
60
+ * Returns the type in lowercase by convention within this module (and the
61
+ * blacklist subsystem that consumes it). This is intentionally distinct from
62
+ * the uppercase Pix key-type enum (`'CPF' | 'CNPJ' | 'EVP' | ...`), which is a
63
+ * different concept — do not compare the two directly.
64
+ * @param cpfCnpj - CPF or CNPJ to inspect
65
+ * @returns 'cpf' if a valid CPF, 'cnpj' if a valid CNPJ, null if neither
66
+ */
67
+ declare function getTaxpayerType(cpfCnpj: string): 'cpf' | 'cnpj' | null;
68
+ /**
69
+ * @description Validates a taxpayer document (CPF or CNPJ).
70
+ * @param cpfCnpj - CPF or CNPJ to validate
71
+ * @returns true if it is a valid CPF or CNPJ
72
+ */
73
+ declare function isValidTaxpayer(cpfCnpj: string): boolean;
74
+ /**
75
+ * @description Format CPF or CNPJ
76
+ * @param cpfCnpj - CPF or CNPJ to format
77
+ * @returns Formatted CPF or CNPJ or null if CPF or CNPJ is invalid
78
+ */
79
+ declare function formatTaxpayer(cpfCnpj: string): string | null;
80
+ declare const cpf: {
81
+ isValid: typeof isValidCpf;
82
+ format: typeof formatCpf;
83
+ compare: typeof compareCpf;
84
+ clean: typeof keepDigits;
85
+ };
86
+ declare const cnpj: {
87
+ isValid: typeof isValidCnpj;
88
+ format: typeof formatCnpj;
89
+ compare: typeof compareCnpj;
90
+ clean: typeof keepAlphanumeric;
91
+ };
92
+ declare const taxpayer: {
93
+ type: typeof getTaxpayerType;
94
+ isValid: typeof isValidTaxpayer;
95
+ format: typeof formatTaxpayer;
96
+ compare: typeof compareTaxpayer;
97
+ clean: typeof keepAlphanumeric;
98
+ };
99
+
100
+ export { cnpj, cpf, taxpayer };
@@ -0,0 +1,100 @@
1
+ /**
2
+ * CPF/CNPJ utilities.
3
+ *
4
+ * Exposes the `cpf` / `cnpj` objects (with `isValid`, `format`, `compare`, `clean`),
5
+ * plus a `taxpayer` object for documents of unknown type (`type`, `isValid`, `format`, `compare`,
6
+ * `clean`). CNPJ validation and formatting also support the alphanumeric CNPJ
7
+ * (effective Jul/2026). CPF stays numeric.
8
+ */
9
+ declare function keepDigits(value: string): string;
10
+ declare function keepAlphanumeric(value: string): string;
11
+ /**
12
+ * @description Validates a CPF (always numeric), including the check digits.
13
+ * @param value - CPF with or without mask
14
+ * @returns true if the CPF is valid
15
+ */
16
+ declare function isValidCpf(value: string): boolean;
17
+ /**
18
+ * @description Masks a CPF as `XXX.XXX.XXX-XX`.
19
+ * @param value - CPF with or without mask
20
+ * @returns Masked CPF, or null if it is not a well-formed (11-digit) CPF
21
+ */
22
+ declare function formatCpf(value: string): string | null;
23
+ /**
24
+ * @description Compares two CPFs, returning null if either is invalid.
25
+ * @param cpf1 - First CPF to compare
26
+ * @param cpf2 - Second CPF to compare
27
+ * @returns true if equal, false if different, null if either CPF is invalid
28
+ */
29
+ declare function compareCpf(cpf1: string, cpf2: string): boolean | null;
30
+ /**
31
+ * @description Validates a numeric or alphanumeric CNPJ, including the check
32
+ * digits (mod-11 calc with character value = ASCII - 48).
33
+ * @param value - CNPJ with or without mask
34
+ * @returns true if the CNPJ is valid
35
+ */
36
+ declare function isValidCnpj(value: string): boolean;
37
+ /**
38
+ * @description Masks a numeric or alphanumeric CNPJ as `XX.XXX.XXX/XXXX-XX`.
39
+ * @param value - CNPJ with or without mask
40
+ * @returns Masked CNPJ, or null if it is not a well-formed (14-position) CNPJ
41
+ */
42
+ declare function formatCnpj(value: string): string | null;
43
+ /**
44
+ * @description Compares two CNPJs, returning null if either is invalid.
45
+ * @param cnpj1 - First CNPJ to compare
46
+ * @param cnpj2 - Second CNPJ to compare
47
+ * @returns true if equal, false if different, null if either CNPJ is invalid
48
+ */
49
+ declare function compareCnpj(cnpj1: string, cnpj2: string): boolean | null;
50
+ /**
51
+ * @description Compare two CPF or CNPJ
52
+ * @param taxpayer1 - CPF or CNPJ to compare
53
+ * @param taxpayer2 - CPF or CNPJ to compare
54
+ * @returns true if CPF or CNPJ are equal, false if not, null if either is invalid
55
+ */
56
+ declare function compareTaxpayer(taxpayer1: string, taxpayer2: string): boolean | null;
57
+ /**
58
+ * @description Determines the type of a taxpayer document, validating it.
59
+ *
60
+ * Returns the type in lowercase by convention within this module (and the
61
+ * blacklist subsystem that consumes it). This is intentionally distinct from
62
+ * the uppercase Pix key-type enum (`'CPF' | 'CNPJ' | 'EVP' | ...`), which is a
63
+ * different concept — do not compare the two directly.
64
+ * @param cpfCnpj - CPF or CNPJ to inspect
65
+ * @returns 'cpf' if a valid CPF, 'cnpj' if a valid CNPJ, null if neither
66
+ */
67
+ declare function getTaxpayerType(cpfCnpj: string): 'cpf' | 'cnpj' | null;
68
+ /**
69
+ * @description Validates a taxpayer document (CPF or CNPJ).
70
+ * @param cpfCnpj - CPF or CNPJ to validate
71
+ * @returns true if it is a valid CPF or CNPJ
72
+ */
73
+ declare function isValidTaxpayer(cpfCnpj: string): boolean;
74
+ /**
75
+ * @description Format CPF or CNPJ
76
+ * @param cpfCnpj - CPF or CNPJ to format
77
+ * @returns Formatted CPF or CNPJ or null if CPF or CNPJ is invalid
78
+ */
79
+ declare function formatTaxpayer(cpfCnpj: string): string | null;
80
+ declare const cpf: {
81
+ isValid: typeof isValidCpf;
82
+ format: typeof formatCpf;
83
+ compare: typeof compareCpf;
84
+ clean: typeof keepDigits;
85
+ };
86
+ declare const cnpj: {
87
+ isValid: typeof isValidCnpj;
88
+ format: typeof formatCnpj;
89
+ compare: typeof compareCnpj;
90
+ clean: typeof keepAlphanumeric;
91
+ };
92
+ declare const taxpayer: {
93
+ type: typeof getTaxpayerType;
94
+ isValid: typeof isValidTaxpayer;
95
+ format: typeof formatTaxpayer;
96
+ compare: typeof compareTaxpayer;
97
+ clean: typeof keepAlphanumeric;
98
+ };
99
+
100
+ export { cnpj, cpf, taxpayer };
package/dist/index.js ADDED
@@ -0,0 +1,167 @@
1
+ "use strict";
2
+ var __defProp = Object.defineProperty;
3
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
4
+ var __getOwnPropNames = Object.getOwnPropertyNames;
5
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
6
+ var __export = (target, all) => {
7
+ for (var name in all)
8
+ __defProp(target, name, { get: all[name], enumerable: true });
9
+ };
10
+ var __copyProps = (to, from, except, desc) => {
11
+ if (from && typeof from === "object" || typeof from === "function") {
12
+ for (let key of __getOwnPropNames(from))
13
+ if (!__hasOwnProp.call(to, key) && key !== except)
14
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
15
+ }
16
+ return to;
17
+ };
18
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
19
+
20
+ // src/index.ts
21
+ var index_exports = {};
22
+ __export(index_exports, {
23
+ cnpj: () => cnpj,
24
+ cpf: () => cpf,
25
+ taxpayer: () => taxpayer
26
+ });
27
+ module.exports = __toCommonJS(index_exports);
28
+ function keepDigits(value) {
29
+ return String(value).replace(/\D/g, "");
30
+ }
31
+ function keepAlphanumeric(value) {
32
+ return String(value).toUpperCase().replace(/[^0-9A-Z]/g, "");
33
+ }
34
+ var CPF_LENGTH = 11;
35
+ var CPF_CHECK_DIGITS = 2;
36
+ function cpfCheckDigit(base) {
37
+ const length = base.length;
38
+ const sum = base.split("").reduce((acc, digit, i) => acc + Number(digit) * (length + 1 - i), 0);
39
+ const remainder = sum % 11;
40
+ return remainder < 2 ? 0 : 11 - remainder;
41
+ }
42
+ function isValidCpf(value) {
43
+ if (/[A-Za-z]/.test(String(value))) {
44
+ return false;
45
+ }
46
+ const clean = keepDigits(value);
47
+ if (clean.length !== CPF_LENGTH) {
48
+ return false;
49
+ }
50
+ if (/^(\d)\1{10}$/.test(clean)) {
51
+ return false;
52
+ }
53
+ const baseLength = CPF_LENGTH - CPF_CHECK_DIGITS;
54
+ const base = clean.slice(0, baseLength);
55
+ const dv1 = cpfCheckDigit(base);
56
+ const dv2 = cpfCheckDigit(base + String(dv1));
57
+ return clean.slice(baseLength) === `${dv1}${dv2}`;
58
+ }
59
+ function formatCpf(value) {
60
+ const clean = keepDigits(value);
61
+ if (clean.length !== CPF_LENGTH) {
62
+ return null;
63
+ }
64
+ return clean.replace(/^(\d{3})(\d{3})(\d{3})(\d{2})$/, "$1.$2.$3-$4");
65
+ }
66
+ function compareCpf(cpf1, cpf2) {
67
+ if (!isValidCpf(cpf1) || !isValidCpf(cpf2)) {
68
+ return null;
69
+ }
70
+ return keepDigits(cpf1) === keepDigits(cpf2);
71
+ }
72
+ var CNPJ_LENGTH = 14;
73
+ var CNPJ_CHECK_DIGITS = 2;
74
+ var CNPJ_FIRST_DV_WEIGHTS = [5, 4, 3, 2, 9, 8, 7, 6, 5, 4, 3, 2];
75
+ var CNPJ_SECOND_DV_WEIGHTS = [6, 5, 4, 3, 2, 9, 8, 7, 6, 5, 4, 3, 2];
76
+ function cnpjCharValue(char) {
77
+ return char.charCodeAt(0) - 48;
78
+ }
79
+ function cnpjCheckDigit(base, weights) {
80
+ const sum = base.split("").reduce((acc, char, i) => acc + cnpjCharValue(char) * weights[i], 0);
81
+ const remainder = sum % 11;
82
+ return remainder < 2 ? 0 : 11 - remainder;
83
+ }
84
+ function isValidCnpj(value) {
85
+ const clean = keepAlphanumeric(value);
86
+ if (clean.length !== CNPJ_LENGTH || !/^[0-9A-Z]{12}[0-9]{2}$/.test(clean)) {
87
+ return false;
88
+ }
89
+ if (/^(.)\1{13}$/.test(clean)) {
90
+ return false;
91
+ }
92
+ const baseLength = CNPJ_LENGTH - CNPJ_CHECK_DIGITS;
93
+ const base = clean.slice(0, baseLength);
94
+ const dv1 = cnpjCheckDigit(base, CNPJ_FIRST_DV_WEIGHTS);
95
+ const dv2 = cnpjCheckDigit(base + String(dv1), CNPJ_SECOND_DV_WEIGHTS);
96
+ return clean.slice(baseLength) === `${dv1}${dv2}`;
97
+ }
98
+ function formatCnpj(value) {
99
+ const clean = keepAlphanumeric(value);
100
+ if (!/^[0-9A-Z]{12}[0-9]{2}$/.test(clean)) {
101
+ return null;
102
+ }
103
+ return clean.replace(
104
+ /^([0-9A-Z]{2})([0-9A-Z]{3})([0-9A-Z]{3})([0-9A-Z]{4})(\d{2})$/,
105
+ "$1.$2.$3/$4-$5"
106
+ );
107
+ }
108
+ function compareCnpj(cnpj1, cnpj2) {
109
+ if (!isValidCnpj(cnpj1) || !isValidCnpj(cnpj2)) {
110
+ return null;
111
+ }
112
+ return keepAlphanumeric(cnpj1) === keepAlphanumeric(cnpj2);
113
+ }
114
+ function compareTaxpayer(taxpayer1, taxpayer2) {
115
+ if (!getTaxpayerType(taxpayer1) || !getTaxpayerType(taxpayer2)) {
116
+ return null;
117
+ }
118
+ return keepAlphanumeric(taxpayer1) === keepAlphanumeric(taxpayer2);
119
+ }
120
+ function getTaxpayerType(cpfCnpj) {
121
+ if (isValidCpf(cpfCnpj)) {
122
+ return "cpf";
123
+ }
124
+ if (isValidCnpj(cpfCnpj)) {
125
+ return "cnpj";
126
+ }
127
+ return null;
128
+ }
129
+ function isValidTaxpayer(cpfCnpj) {
130
+ return Boolean(getTaxpayerType(cpfCnpj));
131
+ }
132
+ function formatTaxpayer(cpfCnpj) {
133
+ const type = getTaxpayerType(cpfCnpj);
134
+ if (type === "cpf") {
135
+ return formatCpf(cpfCnpj);
136
+ } else if (type === "cnpj") {
137
+ return formatCnpj(cpfCnpj);
138
+ }
139
+ return null;
140
+ }
141
+ var cpf = {
142
+ isValid: isValidCpf,
143
+ format: formatCpf,
144
+ compare: compareCpf,
145
+ clean: keepDigits
146
+ };
147
+ var cnpj = {
148
+ isValid: isValidCnpj,
149
+ format: formatCnpj,
150
+ compare: compareCnpj,
151
+ clean: keepAlphanumeric
152
+ };
153
+ var taxpayer = {
154
+ type: getTaxpayerType,
155
+ isValid: isValidTaxpayer,
156
+ format: formatTaxpayer,
157
+ compare: compareTaxpayer,
158
+ // unknown type → alphanumeric is the safe normalization: works for both a
159
+ // numeric CPF and an alphanumeric CNPJ, and their lengths never collide
160
+ clean: keepAlphanumeric
161
+ };
162
+ // Annotate the CommonJS export names for ESM import in node:
163
+ 0 && (module.exports = {
164
+ cnpj,
165
+ cpf,
166
+ taxpayer
167
+ });
package/dist/index.mjs ADDED
@@ -0,0 +1,140 @@
1
+ // src/index.ts
2
+ function keepDigits(value) {
3
+ return String(value).replace(/\D/g, "");
4
+ }
5
+ function keepAlphanumeric(value) {
6
+ return String(value).toUpperCase().replace(/[^0-9A-Z]/g, "");
7
+ }
8
+ var CPF_LENGTH = 11;
9
+ var CPF_CHECK_DIGITS = 2;
10
+ function cpfCheckDigit(base) {
11
+ const length = base.length;
12
+ const sum = base.split("").reduce((acc, digit, i) => acc + Number(digit) * (length + 1 - i), 0);
13
+ const remainder = sum % 11;
14
+ return remainder < 2 ? 0 : 11 - remainder;
15
+ }
16
+ function isValidCpf(value) {
17
+ if (/[A-Za-z]/.test(String(value))) {
18
+ return false;
19
+ }
20
+ const clean = keepDigits(value);
21
+ if (clean.length !== CPF_LENGTH) {
22
+ return false;
23
+ }
24
+ if (/^(\d)\1{10}$/.test(clean)) {
25
+ return false;
26
+ }
27
+ const baseLength = CPF_LENGTH - CPF_CHECK_DIGITS;
28
+ const base = clean.slice(0, baseLength);
29
+ const dv1 = cpfCheckDigit(base);
30
+ const dv2 = cpfCheckDigit(base + String(dv1));
31
+ return clean.slice(baseLength) === `${dv1}${dv2}`;
32
+ }
33
+ function formatCpf(value) {
34
+ const clean = keepDigits(value);
35
+ if (clean.length !== CPF_LENGTH) {
36
+ return null;
37
+ }
38
+ return clean.replace(/^(\d{3})(\d{3})(\d{3})(\d{2})$/, "$1.$2.$3-$4");
39
+ }
40
+ function compareCpf(cpf1, cpf2) {
41
+ if (!isValidCpf(cpf1) || !isValidCpf(cpf2)) {
42
+ return null;
43
+ }
44
+ return keepDigits(cpf1) === keepDigits(cpf2);
45
+ }
46
+ var CNPJ_LENGTH = 14;
47
+ var CNPJ_CHECK_DIGITS = 2;
48
+ var CNPJ_FIRST_DV_WEIGHTS = [5, 4, 3, 2, 9, 8, 7, 6, 5, 4, 3, 2];
49
+ var CNPJ_SECOND_DV_WEIGHTS = [6, 5, 4, 3, 2, 9, 8, 7, 6, 5, 4, 3, 2];
50
+ function cnpjCharValue(char) {
51
+ return char.charCodeAt(0) - 48;
52
+ }
53
+ function cnpjCheckDigit(base, weights) {
54
+ const sum = base.split("").reduce((acc, char, i) => acc + cnpjCharValue(char) * weights[i], 0);
55
+ const remainder = sum % 11;
56
+ return remainder < 2 ? 0 : 11 - remainder;
57
+ }
58
+ function isValidCnpj(value) {
59
+ const clean = keepAlphanumeric(value);
60
+ if (clean.length !== CNPJ_LENGTH || !/^[0-9A-Z]{12}[0-9]{2}$/.test(clean)) {
61
+ return false;
62
+ }
63
+ if (/^(.)\1{13}$/.test(clean)) {
64
+ return false;
65
+ }
66
+ const baseLength = CNPJ_LENGTH - CNPJ_CHECK_DIGITS;
67
+ const base = clean.slice(0, baseLength);
68
+ const dv1 = cnpjCheckDigit(base, CNPJ_FIRST_DV_WEIGHTS);
69
+ const dv2 = cnpjCheckDigit(base + String(dv1), CNPJ_SECOND_DV_WEIGHTS);
70
+ return clean.slice(baseLength) === `${dv1}${dv2}`;
71
+ }
72
+ function formatCnpj(value) {
73
+ const clean = keepAlphanumeric(value);
74
+ if (!/^[0-9A-Z]{12}[0-9]{2}$/.test(clean)) {
75
+ return null;
76
+ }
77
+ return clean.replace(
78
+ /^([0-9A-Z]{2})([0-9A-Z]{3})([0-9A-Z]{3})([0-9A-Z]{4})(\d{2})$/,
79
+ "$1.$2.$3/$4-$5"
80
+ );
81
+ }
82
+ function compareCnpj(cnpj1, cnpj2) {
83
+ if (!isValidCnpj(cnpj1) || !isValidCnpj(cnpj2)) {
84
+ return null;
85
+ }
86
+ return keepAlphanumeric(cnpj1) === keepAlphanumeric(cnpj2);
87
+ }
88
+ function compareTaxpayer(taxpayer1, taxpayer2) {
89
+ if (!getTaxpayerType(taxpayer1) || !getTaxpayerType(taxpayer2)) {
90
+ return null;
91
+ }
92
+ return keepAlphanumeric(taxpayer1) === keepAlphanumeric(taxpayer2);
93
+ }
94
+ function getTaxpayerType(cpfCnpj) {
95
+ if (isValidCpf(cpfCnpj)) {
96
+ return "cpf";
97
+ }
98
+ if (isValidCnpj(cpfCnpj)) {
99
+ return "cnpj";
100
+ }
101
+ return null;
102
+ }
103
+ function isValidTaxpayer(cpfCnpj) {
104
+ return Boolean(getTaxpayerType(cpfCnpj));
105
+ }
106
+ function formatTaxpayer(cpfCnpj) {
107
+ const type = getTaxpayerType(cpfCnpj);
108
+ if (type === "cpf") {
109
+ return formatCpf(cpfCnpj);
110
+ } else if (type === "cnpj") {
111
+ return formatCnpj(cpfCnpj);
112
+ }
113
+ return null;
114
+ }
115
+ var cpf = {
116
+ isValid: isValidCpf,
117
+ format: formatCpf,
118
+ compare: compareCpf,
119
+ clean: keepDigits
120
+ };
121
+ var cnpj = {
122
+ isValid: isValidCnpj,
123
+ format: formatCnpj,
124
+ compare: compareCnpj,
125
+ clean: keepAlphanumeric
126
+ };
127
+ var taxpayer = {
128
+ type: getTaxpayerType,
129
+ isValid: isValidTaxpayer,
130
+ format: formatTaxpayer,
131
+ compare: compareTaxpayer,
132
+ // unknown type → alphanumeric is the safe normalization: works for both a
133
+ // numeric CPF and an alphanumeric CNPJ, and their lengths never collide
134
+ clean: keepAlphanumeric
135
+ };
136
+ export {
137
+ cnpj,
138
+ cpf,
139
+ taxpayer
140
+ };
package/package.json ADDED
@@ -0,0 +1,41 @@
1
+ {
2
+ "name": "@azify/cpf-cnpj",
3
+ "version": "0.1.0",
4
+ "description": "CPF/CNPJ validation, formatting and comparison helpers (including alphanumeric CNPJ).",
5
+ "license": "UNLICENSED",
6
+ "author": "Azify",
7
+ "repository": {
8
+ "type": "git",
9
+ "url": "git+https://github.com/azifydev/azify-cpf-cnpj.git"
10
+ },
11
+ "bugs": {
12
+ "url": "https://github.com/azifydev/azify-cpf-cnpj/issues"
13
+ },
14
+ "homepage": "https://github.com/azifydev/azify-cpf-cnpj#readme",
15
+ "main": "./dist/index.js",
16
+ "module": "./dist/index.mjs",
17
+ "types": "./dist/index.d.ts",
18
+ "exports": {
19
+ ".": {
20
+ "types": "./dist/index.d.ts",
21
+ "import": "./dist/index.mjs",
22
+ "require": "./dist/index.js"
23
+ }
24
+ },
25
+ "files": [
26
+ "dist"
27
+ ],
28
+ "publishConfig": {
29
+ "access": "restricted"
30
+ },
31
+ "scripts": {
32
+ "build": "tsup src/index.ts --format cjs,esm --dts --clean",
33
+ "test": "vitest run",
34
+ "prepublishOnly": "npm run build && npm test"
35
+ },
36
+ "devDependencies": {
37
+ "tsup": "^8.3.5",
38
+ "typescript": "^5.7.2",
39
+ "vitest": "^2.1.8"
40
+ }
41
+ }