gerar 0.0.2 → 0.0.3
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/LICENSE +21 -0
- package/README.md +50 -0
- package/dist/commands/cnpj/index.d.ts +2 -0
- package/dist/commands/cnpj/index.js +15 -0
- package/dist/commands/cnpj/index.js.map +1 -0
- package/dist/commands/cnpj/utils.d.ts +7 -0
- package/dist/commands/cnpj/utils.js +27 -0
- package/dist/commands/cnpj/utils.js.map +1 -0
- package/dist/index.js +6 -0
- package/dist/index.js.map +1 -1
- package/package.json +2 -2
- package/src/commands/cnpj/index.ts +21 -0
- package/src/commands/cnpj/tests/utils.test.ts +114 -0
- package/src/commands/cnpj/utils.ts +38 -0
- package/src/commands/cpf/tests/utils.test.ts +1 -1
- package/src/index.ts +11 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2025 Victor Ribeiro Boechat
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
# Gerar
|
|
2
|
+
|
|
3
|
+
[](https://www.npmjs.com/package/gerar)
|
|
4
|
+
|
|
5
|
+
CLI brasileiro para gerar dados fictícios válidos para testes.
|
|
6
|
+
|
|
7
|
+
## Instalação
|
|
8
|
+
|
|
9
|
+
```bash
|
|
10
|
+
npm i -g gerar
|
|
11
|
+
```
|
|
12
|
+
|
|
13
|
+
## Exemplo de Uso
|
|
14
|
+
|
|
15
|
+
Gera um dado fictício válido, nesse caso CPF:
|
|
16
|
+
|
|
17
|
+
```bash
|
|
18
|
+
gerar cpf
|
|
19
|
+
```
|
|
20
|
+
|
|
21
|
+
Gera múltiplos dados:
|
|
22
|
+
|
|
23
|
+
```bash
|
|
24
|
+
gerar cpf --amount 5
|
|
25
|
+
# ou
|
|
26
|
+
gerar cpf -a 5
|
|
27
|
+
```
|
|
28
|
+
|
|
29
|
+
**Exemplo de saída:**
|
|
30
|
+
|
|
31
|
+
```
|
|
32
|
+
CPF 1) Com Máscara: 123.456.789-00 - Sem Máscara: 12345678900
|
|
33
|
+
```
|
|
34
|
+
|
|
35
|
+
## Roadmap
|
|
36
|
+
|
|
37
|
+
| Funcionalidade | Status |
|
|
38
|
+
| ------------------------------------------------- | ----------- |
|
|
39
|
+
| CPF | ✅ Completo |
|
|
40
|
+
| CNPJ | ✅ Completo |
|
|
41
|
+
| Cartão de crédito com base na bandeira | ⏳ Pendente |
|
|
42
|
+
| Endereço | ⏳ Pendente |
|
|
43
|
+
| UUID v4 | ⏳ Pendente |
|
|
44
|
+
| UUID v7 | ⏳ Pendente |
|
|
45
|
+
| Autocomplete no Terminal | ⏳ Pendente |
|
|
46
|
+
| Localização de endereço norte-americano e europeu | ⏳ Pendente |
|
|
47
|
+
|
|
48
|
+
## Licença
|
|
49
|
+
|
|
50
|
+
Este projeto está licenciado sob a licença MIT. Para mais informações, consulte a [página do pacote no NPM](https://www.npmjs.com/package/gerar).
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.cnpjCommand = void 0;
|
|
4
|
+
const utils_1 = require("./utils");
|
|
5
|
+
exports.cnpjCommand = {
|
|
6
|
+
name: "cnpj",
|
|
7
|
+
description: "Gera um CNPJ fictício válido.",
|
|
8
|
+
action: (options) => {
|
|
9
|
+
const generatedCnpjs = Array.from({ length: options.amount ?? 1 }, utils_1.generateCnpj);
|
|
10
|
+
generatedCnpjs.forEach((generatedCnpj, index) => {
|
|
11
|
+
console.log(`CNPJ ${index + 1}) Com Máscara: ${generatedCnpj.withMask} - Sem Máscara: ${generatedCnpj.withoutMask}`);
|
|
12
|
+
});
|
|
13
|
+
},
|
|
14
|
+
};
|
|
15
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/commands/cnpj/index.ts"],"names":[],"mappings":";;;AACA,mCAAuC;AAE1B,QAAA,WAAW,GAAqB;IAC3C,IAAI,EAAE,MAAM;IACZ,WAAW,EAAE,+BAA+B;IAC5C,MAAM,EAAE,CAAC,OAA4B,EAAE,EAAE;QACvC,MAAM,cAAc,GAAG,KAAK,CAAC,IAAI,CAC/B,EAAE,MAAM,EAAE,OAAO,CAAC,MAAM,IAAI,CAAC,EAAE,EAC/B,oBAAY,CACb,CAAC;QAEF,cAAc,CAAC,OAAO,CAAC,CAAC,aAAa,EAAE,KAAK,EAAE,EAAE;YAC9C,OAAO,CAAC,GAAG,CACT,QAAQ,KAAK,GAAG,CAAC,kBACf,aAAa,CAAC,QAChB,mBAAmB,aAAa,CAAC,WAAW,EAAE,CAC/C,CAAC;QACJ,CAAC,CAAC,CAAC;IACL,CAAC;CACF,CAAC"}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.generateCnpj = exports.calculateCnpjDigit = void 0;
|
|
4
|
+
const calculateCnpjDigit = (cnpj) => {
|
|
5
|
+
const weights = [6, 5, 4, 3, 2, 9, 8, 7, 6, 5, 4, 3, 2];
|
|
6
|
+
const length = cnpj.length;
|
|
7
|
+
const relevantWeights = weights.slice(weights.length - length);
|
|
8
|
+
const sum = cnpj
|
|
9
|
+
.split("")
|
|
10
|
+
.reduce((acc, num, index) => acc + Number(num) * relevantWeights[index], 0);
|
|
11
|
+
const remainder = sum % 11;
|
|
12
|
+
return remainder < 2 ? 0 : 11 - remainder;
|
|
13
|
+
};
|
|
14
|
+
exports.calculateCnpjDigit = calculateCnpjDigit;
|
|
15
|
+
const generateCnpj = () => {
|
|
16
|
+
const baseCnpj = Array.from({ length: 12 }, () => Math.floor(Math.random() * 10)).join("");
|
|
17
|
+
const firstDigit = (0, exports.calculateCnpjDigit)(baseCnpj);
|
|
18
|
+
const lastDigit = (0, exports.calculateCnpjDigit)(baseCnpj + firstDigit);
|
|
19
|
+
const fullCnpj = baseCnpj + firstDigit.toString() + lastDigit.toString();
|
|
20
|
+
return {
|
|
21
|
+
// TODO: Improve this as soon as possible.
|
|
22
|
+
withMask: `${fullCnpj.slice(0, 2)}.${fullCnpj.slice(2, 5)}.${fullCnpj.slice(5, 8)}/${fullCnpj.slice(8, 12)}-${fullCnpj.slice(12, 14)}`,
|
|
23
|
+
withoutMask: fullCnpj,
|
|
24
|
+
};
|
|
25
|
+
};
|
|
26
|
+
exports.generateCnpj = generateCnpj;
|
|
27
|
+
//# sourceMappingURL=utils.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"utils.js","sourceRoot":"","sources":["../../../src/commands/cnpj/utils.ts"],"names":[],"mappings":";;;AAKO,MAAM,kBAAkB,GAAG,CAAC,IAAY,EAAU,EAAE;IACzD,MAAM,OAAO,GAAG,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC,CAAC;IACxD,MAAM,MAAM,GAAG,IAAI,CAAC,MAAM,CAAC;IAC3B,MAAM,eAAe,GAAG,OAAO,CAAC,KAAK,CAAC,OAAO,CAAC,MAAM,GAAG,MAAM,CAAC,CAAC;IAE/D,MAAM,GAAG,GAAG,IAAI;SACb,KAAK,CAAC,EAAE,CAAC;SACT,MAAM,CAAC,CAAC,GAAG,EAAE,GAAG,EAAE,KAAK,EAAE,EAAE,CAAC,GAAG,GAAG,MAAM,CAAC,GAAG,CAAC,GAAG,eAAe,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC,CAAC;IAE9E,MAAM,SAAS,GAAG,GAAG,GAAG,EAAE,CAAC;IAE3B,OAAO,SAAS,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,EAAE,GAAG,SAAS,CAAC;AAC5C,CAAC,CAAC;AAZW,QAAA,kBAAkB,sBAY7B;AAEK,MAAM,YAAY,GAAG,GAAyB,EAAE;IACrD,MAAM,QAAQ,GAAG,KAAK,CAAC,IAAI,CAAC,EAAE,MAAM,EAAE,EAAE,EAAE,EAAE,GAAG,EAAE,CAC/C,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,MAAM,EAAE,GAAG,EAAE,CAAC,CAC/B,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;IAEX,MAAM,UAAU,GAAG,IAAA,0BAAkB,EAAC,QAAQ,CAAC,CAAC;IAChD,MAAM,SAAS,GAAG,IAAA,0BAAkB,EAAC,QAAQ,GAAG,UAAU,CAAC,CAAC;IAE5D,MAAM,QAAQ,GAAG,QAAQ,GAAG,UAAU,CAAC,QAAQ,EAAE,GAAG,SAAS,CAAC,QAAQ,EAAE,CAAC;IAEzE,OAAO;QACL,0CAA0C;QAC1C,QAAQ,EAAE,GAAG,QAAQ,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,IAAI,QAAQ,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,IAAI,QAAQ,CAAC,KAAK,CACzE,CAAC,EACD,CAAC,CACF,IAAI,QAAQ,CAAC,KAAK,CAAC,CAAC,EAAE,EAAE,CAAC,IAAI,QAAQ,CAAC,KAAK,CAAC,EAAE,EAAE,EAAE,CAAC,EAAE;QACtD,WAAW,EAAE,QAAQ;KACtB,CAAC;AACJ,CAAC,CAAC;AAlBW,QAAA,YAAY,gBAkBvB"}
|
package/dist/index.js
CHANGED
|
@@ -3,6 +3,7 @@
|
|
|
3
3
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
4
4
|
const commander_1 = require("commander");
|
|
5
5
|
const cpf_1 = require("./commands/cpf");
|
|
6
|
+
const cnpj_1 = require("./commands/cnpj");
|
|
6
7
|
const program = new commander_1.Command();
|
|
7
8
|
program
|
|
8
9
|
.name("gerar")
|
|
@@ -15,5 +16,10 @@ program
|
|
|
15
16
|
.description(cpf_1.cpfCommand.description)
|
|
16
17
|
.option("-a, --amount <amount>", "Quantidade a ser gerado.", (value) => Number(value))
|
|
17
18
|
.action(cpf_1.cpfCommand.action);
|
|
19
|
+
program
|
|
20
|
+
.command(cnpj_1.cnpjCommand.name)
|
|
21
|
+
.description(cnpj_1.cnpjCommand.description)
|
|
22
|
+
.option("-a, --amount <amount>", "Quantidade a ser gerado.", (value) => Number(value))
|
|
23
|
+
.action(cnpj_1.cnpjCommand.action);
|
|
18
24
|
program.parse();
|
|
19
25
|
//# sourceMappingURL=index.js.map
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";;;AACA,yCAAoC;AACpC,wCAA4C;
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";;;AACA,yCAAoC;AACpC,wCAA4C;AAC5C,0CAA8C;AAE9C,MAAM,OAAO,GAAG,IAAI,mBAAO,EAAE,CAAC;AAE9B,OAAO;KACJ,IAAI,CAAC,OAAO,CAAC;KACb,WAAW,CAAC,wDAAwD,CAAC;KACrE,OAAO,CAAC,OAAO,CAAC,CAAC;AAEpB,OAAO,CAAC,WAAW,CAAC,MAAM,EAAE,oCAAoC,CAAC,CAAC;AAElE,oDAAoD;AACpD,OAAO;KACJ,OAAO,CAAC,gBAAU,CAAC,IAAI,CAAC;KACxB,WAAW,CAAC,gBAAU,CAAC,WAAW,CAAC;KACnC,MAAM,CACL,uBAAuB,EACvB,0BAA0B,EAC1B,CAAC,KAAa,EAAE,EAAE,CAAC,MAAM,CAAC,KAAK,CAAC,CACjC;KACA,MAAM,CAAC,gBAAU,CAAC,MAAM,CAAC,CAAC;AAE7B,OAAO;KACJ,OAAO,CAAC,kBAAW,CAAC,IAAI,CAAC;KACzB,WAAW,CAAC,kBAAW,CAAC,WAAW,CAAC;KACpC,MAAM,CACL,uBAAuB,EACvB,0BAA0B,EAC1B,CAAC,KAAa,EAAE,EAAE,CAAC,MAAM,CAAC,KAAK,CAAC,CACjC;KACA,MAAM,CAAC,kBAAW,CAAC,MAAM,CAAC,CAAC;AAE9B,OAAO,CAAC,KAAK,EAAE,CAAC"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "gerar",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.3",
|
|
4
4
|
"description": "CLI brasileiro para gerar dados fictícios para testes.",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"author": "Victor Ribeiro Boechat",
|
|
@@ -15,7 +15,7 @@
|
|
|
15
15
|
"test:watch": "vitest"
|
|
16
16
|
},
|
|
17
17
|
"keywords": [],
|
|
18
|
-
"license": "
|
|
18
|
+
"license": "MIT",
|
|
19
19
|
"dependencies": {
|
|
20
20
|
"commander": "^14.0.2"
|
|
21
21
|
},
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import { CommandStructure } from "../../shared/utils/command-structure";
|
|
2
|
+
import { generateCnpj } from "./utils";
|
|
3
|
+
|
|
4
|
+
export const cnpjCommand: CommandStructure = {
|
|
5
|
+
name: "cnpj",
|
|
6
|
+
description: "Gera um CNPJ fictício válido.",
|
|
7
|
+
action: (options: { amount?: number }) => {
|
|
8
|
+
const generatedCnpjs = Array.from(
|
|
9
|
+
{ length: options.amount ?? 1 },
|
|
10
|
+
generateCnpj
|
|
11
|
+
);
|
|
12
|
+
|
|
13
|
+
generatedCnpjs.forEach((generatedCnpj, index) => {
|
|
14
|
+
console.log(
|
|
15
|
+
`CNPJ ${index + 1}) Com Máscara: ${
|
|
16
|
+
generatedCnpj.withMask
|
|
17
|
+
} - Sem Máscara: ${generatedCnpj.withoutMask}`
|
|
18
|
+
);
|
|
19
|
+
});
|
|
20
|
+
},
|
|
21
|
+
};
|
|
@@ -0,0 +1,114 @@
|
|
|
1
|
+
import { describe, it, expect } from "vitest";
|
|
2
|
+
import { calculateCnpjDigit, generateCnpj } from "../utils";
|
|
3
|
+
|
|
4
|
+
describe("calculateCnpjDigit", () => {
|
|
5
|
+
it("should calculate the first check digit correctly for known CNPJ", () => {
|
|
6
|
+
const firstDigit = calculateCnpjDigit("112223330001");
|
|
7
|
+
|
|
8
|
+
expect(firstDigit).toBe(8);
|
|
9
|
+
});
|
|
10
|
+
|
|
11
|
+
it("should calculate the second check digit correctly for known CNPJ", () => {
|
|
12
|
+
const secondDigit = calculateCnpjDigit("1122233300018");
|
|
13
|
+
|
|
14
|
+
expect(secondDigit).toBe(1);
|
|
15
|
+
});
|
|
16
|
+
|
|
17
|
+
it("should return 0 when remainder is less than 2", () => {
|
|
18
|
+
const digit = calculateCnpjDigit("000000000000");
|
|
19
|
+
|
|
20
|
+
expect(digit).toBe(0);
|
|
21
|
+
});
|
|
22
|
+
|
|
23
|
+
it("should return correct digit when remainder is 2 or greater", () => {
|
|
24
|
+
const digit = calculateCnpjDigit("123456780001");
|
|
25
|
+
|
|
26
|
+
expect(digit).toBeGreaterThanOrEqual(0);
|
|
27
|
+
expect(digit).toBeLessThanOrEqual(9);
|
|
28
|
+
});
|
|
29
|
+
|
|
30
|
+
it("should handle 12-digit input correctly", () => {
|
|
31
|
+
const digit = calculateCnpjDigit("123456780001");
|
|
32
|
+
|
|
33
|
+
expect(digit).toBeTypeOf("number");
|
|
34
|
+
expect(digit).toBeGreaterThanOrEqual(0);
|
|
35
|
+
expect(digit).toBeLessThanOrEqual(9);
|
|
36
|
+
});
|
|
37
|
+
|
|
38
|
+
it("should handle 13-digit input correctly (for second digit calculation)", () => {
|
|
39
|
+
const digit = calculateCnpjDigit("1234567800012");
|
|
40
|
+
|
|
41
|
+
expect(digit).toBeTypeOf("number");
|
|
42
|
+
expect(digit).toBeGreaterThanOrEqual(0);
|
|
43
|
+
expect(digit).toBeLessThanOrEqual(9);
|
|
44
|
+
});
|
|
45
|
+
});
|
|
46
|
+
|
|
47
|
+
describe("generateCnpj", () => {
|
|
48
|
+
it("should generate a CNPJ with correct structure", () => {
|
|
49
|
+
const result = generateCnpj();
|
|
50
|
+
|
|
51
|
+
expect(result).toHaveProperty("withMask");
|
|
52
|
+
expect(result).toHaveProperty("withoutMask");
|
|
53
|
+
});
|
|
54
|
+
|
|
55
|
+
it("should generate CNPJ withoutMask with exactly 14 digits", () => {
|
|
56
|
+
const result = generateCnpj();
|
|
57
|
+
|
|
58
|
+
expect(result.withoutMask).toMatch(/^\d{14}$/);
|
|
59
|
+
expect(result.withoutMask.length).toBe(14);
|
|
60
|
+
});
|
|
61
|
+
|
|
62
|
+
it("should generate CNPJ withMask in correct format (XX.XXX.XXX/XXXX-XX)", () => {
|
|
63
|
+
const result = generateCnpj();
|
|
64
|
+
|
|
65
|
+
expect(result.withMask).toMatch(/^\d{2}\.\d{3}\.\d{3}\/\d{4}-\d{2}$/);
|
|
66
|
+
});
|
|
67
|
+
|
|
68
|
+
it("should generate valid CNPJ digits (check digits are correct)", () => {
|
|
69
|
+
const result = generateCnpj();
|
|
70
|
+
const cnpj = result.withoutMask;
|
|
71
|
+
|
|
72
|
+
const base = cnpj.slice(0, 12);
|
|
73
|
+
const firstCheckDigit = Number(cnpj[12]);
|
|
74
|
+
const secondCheckDigit = Number(cnpj[13]);
|
|
75
|
+
|
|
76
|
+
const calculatedFirstDigit = calculateCnpjDigit(base);
|
|
77
|
+
expect(firstCheckDigit).toBe(calculatedFirstDigit);
|
|
78
|
+
|
|
79
|
+
const calculatedSecondDigit = calculateCnpjDigit(base + firstCheckDigit);
|
|
80
|
+
expect(secondCheckDigit).toBe(calculatedSecondDigit);
|
|
81
|
+
});
|
|
82
|
+
|
|
83
|
+
it("should generate different CNPJs on multiple calls", () => {
|
|
84
|
+
const results = Array.from({ length: 10 }, () => generateCnpj());
|
|
85
|
+
const uniqueCnpjs = new Set(results.map((r) => r.withoutMask));
|
|
86
|
+
|
|
87
|
+
expect(uniqueCnpjs.size).toBeGreaterThan(1);
|
|
88
|
+
});
|
|
89
|
+
|
|
90
|
+
it("should generate CNPJ where withMask and withoutMask represent the same number", () => {
|
|
91
|
+
const result = generateCnpj();
|
|
92
|
+
|
|
93
|
+
const unmasked = result.withMask.replace(/[.\/-]/g, "");
|
|
94
|
+
|
|
95
|
+
expect(unmasked).toBe(result.withoutMask);
|
|
96
|
+
});
|
|
97
|
+
|
|
98
|
+
it("should generate multiple valid CNPJs", () => {
|
|
99
|
+
const results = Array.from({ length: 100 }, () => generateCnpj());
|
|
100
|
+
|
|
101
|
+
results.forEach((result) => {
|
|
102
|
+
const cnpj = result.withoutMask;
|
|
103
|
+
const base = cnpj.slice(0, 12);
|
|
104
|
+
const firstCheckDigit = Number(cnpj[12]);
|
|
105
|
+
const secondCheckDigit = Number(cnpj[13]);
|
|
106
|
+
|
|
107
|
+
const calculatedFirstDigit = calculateCnpjDigit(base);
|
|
108
|
+
const calculatedSecondDigit = calculateCnpjDigit(base + firstCheckDigit);
|
|
109
|
+
|
|
110
|
+
expect(firstCheckDigit).toBe(calculatedFirstDigit);
|
|
111
|
+
expect(secondCheckDigit).toBe(calculatedSecondDigit);
|
|
112
|
+
});
|
|
113
|
+
});
|
|
114
|
+
});
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
type GenerateCnpjResponse = {
|
|
2
|
+
withMask: string;
|
|
3
|
+
withoutMask: string;
|
|
4
|
+
};
|
|
5
|
+
|
|
6
|
+
export const calculateCnpjDigit = (cnpj: string): number => {
|
|
7
|
+
const weights = [6, 5, 4, 3, 2, 9, 8, 7, 6, 5, 4, 3, 2];
|
|
8
|
+
const length = cnpj.length;
|
|
9
|
+
const relevantWeights = weights.slice(weights.length - length);
|
|
10
|
+
|
|
11
|
+
const sum = cnpj
|
|
12
|
+
.split("")
|
|
13
|
+
.reduce((acc, num, index) => acc + Number(num) * relevantWeights[index], 0);
|
|
14
|
+
|
|
15
|
+
const remainder = sum % 11;
|
|
16
|
+
|
|
17
|
+
return remainder < 2 ? 0 : 11 - remainder;
|
|
18
|
+
};
|
|
19
|
+
|
|
20
|
+
export const generateCnpj = (): GenerateCnpjResponse => {
|
|
21
|
+
const baseCnpj = Array.from({ length: 12 }, () =>
|
|
22
|
+
Math.floor(Math.random() * 10)
|
|
23
|
+
).join("");
|
|
24
|
+
|
|
25
|
+
const firstDigit = calculateCnpjDigit(baseCnpj);
|
|
26
|
+
const lastDigit = calculateCnpjDigit(baseCnpj + firstDigit);
|
|
27
|
+
|
|
28
|
+
const fullCnpj = baseCnpj + firstDigit.toString() + lastDigit.toString();
|
|
29
|
+
|
|
30
|
+
return {
|
|
31
|
+
// TODO: Improve this as soon as possible.
|
|
32
|
+
withMask: `${fullCnpj.slice(0, 2)}.${fullCnpj.slice(2, 5)}.${fullCnpj.slice(
|
|
33
|
+
5,
|
|
34
|
+
8
|
|
35
|
+
)}/${fullCnpj.slice(8, 12)}-${fullCnpj.slice(12, 14)}`,
|
|
36
|
+
withoutMask: fullCnpj,
|
|
37
|
+
};
|
|
38
|
+
};
|
package/src/index.ts
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
import { Command } from "commander";
|
|
3
3
|
import { cpfCommand } from "./commands/cpf";
|
|
4
|
+
import { cnpjCommand } from "./commands/cnpj";
|
|
4
5
|
|
|
5
6
|
const program = new Command();
|
|
6
7
|
|
|
@@ -22,4 +23,14 @@ program
|
|
|
22
23
|
)
|
|
23
24
|
.action(cpfCommand.action);
|
|
24
25
|
|
|
26
|
+
program
|
|
27
|
+
.command(cnpjCommand.name)
|
|
28
|
+
.description(cnpjCommand.description)
|
|
29
|
+
.option(
|
|
30
|
+
"-a, --amount <amount>",
|
|
31
|
+
"Quantidade a ser gerado.",
|
|
32
|
+
(value: string) => Number(value)
|
|
33
|
+
)
|
|
34
|
+
.action(cnpjCommand.action);
|
|
35
|
+
|
|
25
36
|
program.parse();
|