gerar 0.0.2
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/.github/workflows/publish.yml +51 -0
- package/Makefile +22 -0
- package/dist/commands/cpf/index.d.ts +2 -0
- package/dist/commands/cpf/index.js +15 -0
- package/dist/commands/cpf/index.js.map +1 -0
- package/dist/commands/cpf/utils.d.ts +7 -0
- package/dist/commands/cpf/utils.js +25 -0
- package/dist/commands/cpf/utils.js.map +1 -0
- package/dist/index.d.ts +2 -0
- package/dist/index.js +19 -0
- package/dist/index.js.map +1 -0
- package/dist/shared/utils/command-structure.d.ts +6 -0
- package/dist/shared/utils/command-structure.js +3 -0
- package/dist/shared/utils/command-structure.js.map +1 -0
- package/package.json +29 -0
- package/src/commands/cpf/index.ts +21 -0
- package/src/commands/cpf/tests/utils.test.ts +114 -0
- package/src/commands/cpf/utils.ts +35 -0
- package/src/index.ts +25 -0
- package/src/shared/utils/command-structure.ts +7 -0
- package/tsconfig.json +17 -0
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
name: Publish to NPM Registry
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
workflow_dispatch:
|
|
5
|
+
|
|
6
|
+
jobs:
|
|
7
|
+
publish:
|
|
8
|
+
runs-on: ubuntu-latest
|
|
9
|
+
|
|
10
|
+
steps:
|
|
11
|
+
- name: Checkout repository
|
|
12
|
+
uses: actions/checkout@v4
|
|
13
|
+
with:
|
|
14
|
+
ref: ${{ github.ref }}
|
|
15
|
+
|
|
16
|
+
- name: Enable Corepack & setup pnpm v10.20.0
|
|
17
|
+
run: |
|
|
18
|
+
corepack enable
|
|
19
|
+
corepack prepare pnpm@10.20.0 --activate
|
|
20
|
+
|
|
21
|
+
- name: Setup Node.js
|
|
22
|
+
uses: actions/setup-node@v4
|
|
23
|
+
with:
|
|
24
|
+
node-version: "22.12.0"
|
|
25
|
+
registry-url: "https://registry.npmjs.org/"
|
|
26
|
+
|
|
27
|
+
- name: Install dependencies
|
|
28
|
+
run: pnpm install
|
|
29
|
+
|
|
30
|
+
- name: Test project
|
|
31
|
+
run: pnpm test
|
|
32
|
+
|
|
33
|
+
- name: Build project
|
|
34
|
+
run: pnpm build
|
|
35
|
+
|
|
36
|
+
- name: Detect tag and bump version in package.json
|
|
37
|
+
run: |
|
|
38
|
+
if [[ "${GITHUB_REF}" == refs/tags/* ]]; then
|
|
39
|
+
TAG_VERSION="${GITHUB_REF##*/}"
|
|
40
|
+
NEW_VERSION="${TAG_VERSION#v}"
|
|
41
|
+
jq --arg version "$NEW_VERSION" '.version = $version' package.json > package.tmp.json
|
|
42
|
+
mv package.tmp.json package.json
|
|
43
|
+
else
|
|
44
|
+
echo "::error::Este workflow só pode ser disparado por uma tag!"
|
|
45
|
+
exit 1
|
|
46
|
+
fi
|
|
47
|
+
|
|
48
|
+
- name: Publish to NPM
|
|
49
|
+
run: npm publish --access public
|
|
50
|
+
env:
|
|
51
|
+
NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}
|
package/Makefile
ADDED
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
.PHONY: build install check-node-version check-pnpm-version check-installation unit-tests watch-unit-tests
|
|
2
|
+
|
|
3
|
+
check-node-version:
|
|
4
|
+
@node -v | grep -q 'v22' || (echo "Node.js LTS version is required." && exit 1)
|
|
5
|
+
|
|
6
|
+
check-pnpm-version: check-node-version
|
|
7
|
+
@pnpm -v | grep -q '10.' || (echo "pnpm version 10.x is required." && exit 1)
|
|
8
|
+
|
|
9
|
+
check-installation: check-node-version check-pnpm-version
|
|
10
|
+
@if [ ! -d "node_modules" ]; then echo "Dependencies are not installed. Run make install." && exit 1; fi
|
|
11
|
+
|
|
12
|
+
install: check-node-version check-pnpm-version
|
|
13
|
+
@pnpm install;
|
|
14
|
+
|
|
15
|
+
build: check-node-version check-pnpm-version check-installation
|
|
16
|
+
@pnpm build;
|
|
17
|
+
|
|
18
|
+
unit-tests: check-node-version check-pnpm-version check-installation
|
|
19
|
+
@pnpm test;
|
|
20
|
+
|
|
21
|
+
watch-unit-tests: check-node-version check-pnpm-version check-installation
|
|
22
|
+
@pnpm test:watch;
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.cpfCommand = void 0;
|
|
4
|
+
const utils_1 = require("./utils");
|
|
5
|
+
exports.cpfCommand = {
|
|
6
|
+
name: "cpf",
|
|
7
|
+
description: "Gera um CPF fictício válido.",
|
|
8
|
+
action: (options) => {
|
|
9
|
+
const generatedCpfs = Array.from({ length: options.amount ?? 1 }, utils_1.generateCpf);
|
|
10
|
+
generatedCpfs.forEach((generatedCpf, index) => {
|
|
11
|
+
console.log(`CPF ${index + 1}) Com Máscara: ${generatedCpf.withMask} - Sem Máscara: ${generatedCpf.withoutMask}`);
|
|
12
|
+
});
|
|
13
|
+
},
|
|
14
|
+
};
|
|
15
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/commands/cpf/index.ts"],"names":[],"mappings":";;;AACA,mCAAsC;AAEzB,QAAA,UAAU,GAAqB;IAC1C,IAAI,EAAE,KAAK;IACX,WAAW,EAAE,8BAA8B;IAC3C,MAAM,EAAE,CAAC,OAA4B,EAAE,EAAE;QACvC,MAAM,aAAa,GAAG,KAAK,CAAC,IAAI,CAC9B,EAAE,MAAM,EAAE,OAAO,CAAC,MAAM,IAAI,CAAC,EAAE,EAC/B,mBAAW,CACZ,CAAC;QAEF,aAAa,CAAC,OAAO,CAAC,CAAC,YAAY,EAAE,KAAK,EAAE,EAAE;YAC5C,OAAO,CAAC,GAAG,CACT,OAAO,KAAK,GAAG,CAAC,kBACd,YAAY,CAAC,QACf,mBAAmB,YAAY,CAAC,WAAW,EAAE,CAC9C,CAAC;QACJ,CAAC,CAAC,CAAC;IACL,CAAC;CACF,CAAC"}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.generateCpf = exports.calculateCpfDigit = void 0;
|
|
4
|
+
const calculateCpfDigit = (cpf) => {
|
|
5
|
+
const length = cpf.length + 1;
|
|
6
|
+
const sum = cpf
|
|
7
|
+
.split("")
|
|
8
|
+
.reduce((acc, num, index) => acc + Number(num) * (length - index), 0);
|
|
9
|
+
const remainder = sum % 11;
|
|
10
|
+
return remainder < 2 ? 0 : 11 - remainder;
|
|
11
|
+
};
|
|
12
|
+
exports.calculateCpfDigit = calculateCpfDigit;
|
|
13
|
+
const generateCpf = () => {
|
|
14
|
+
const baseCpf = Array.from({ length: 9 }, () => Math.floor(Math.random() * 10)).join("");
|
|
15
|
+
const firstDigit = (0, exports.calculateCpfDigit)(baseCpf);
|
|
16
|
+
const lastDigit = (0, exports.calculateCpfDigit)(baseCpf + firstDigit);
|
|
17
|
+
const fullCpf = baseCpf + firstDigit.toString() + lastDigit.toString();
|
|
18
|
+
return {
|
|
19
|
+
// TODO: Improve this as soon as possible.
|
|
20
|
+
withMask: `${fullCpf.slice(0, 3)}.${fullCpf.slice(3, 6)}.${fullCpf.slice(6, 9)}-${fullCpf.slice(9, 11)}`,
|
|
21
|
+
withoutMask: fullCpf,
|
|
22
|
+
};
|
|
23
|
+
};
|
|
24
|
+
exports.generateCpf = generateCpf;
|
|
25
|
+
//# sourceMappingURL=utils.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"utils.js","sourceRoot":"","sources":["../../../src/commands/cpf/utils.ts"],"names":[],"mappings":";;;AAKO,MAAM,iBAAiB,GAAG,CAAC,GAAW,EAAU,EAAE;IACvD,MAAM,MAAM,GAAG,GAAG,CAAC,MAAM,GAAG,CAAC,CAAC;IAC9B,MAAM,GAAG,GAAG,GAAG;SACZ,KAAK,CAAC,EAAE,CAAC;SACT,MAAM,CAAC,CAAC,GAAG,EAAE,GAAG,EAAE,KAAK,EAAE,EAAE,CAAC,GAAG,GAAG,MAAM,CAAC,GAAG,CAAC,GAAG,CAAC,MAAM,GAAG,KAAK,CAAC,EAAE,CAAC,CAAC,CAAC;IAExE,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;AATW,QAAA,iBAAiB,qBAS5B;AAEK,MAAM,WAAW,GAAG,GAAwB,EAAE;IACnD,MAAM,OAAO,GAAG,KAAK,CAAC,IAAI,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,EAAE,GAAG,EAAE,CAC7C,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,MAAM,EAAE,GAAG,EAAE,CAAC,CAC/B,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;IAEX,MAAM,UAAU,GAAG,IAAA,yBAAiB,EAAC,OAAO,CAAC,CAAC;IAC9C,MAAM,SAAS,GAAG,IAAA,yBAAiB,EAAC,OAAO,GAAG,UAAU,CAAC,CAAC;IAE1D,MAAM,OAAO,GAAG,OAAO,GAAG,UAAU,CAAC,QAAQ,EAAE,GAAG,SAAS,CAAC,QAAQ,EAAE,CAAC;IAEvE,OAAO;QACL,0CAA0C;QAC1C,QAAQ,EAAE,GAAG,OAAO,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,IAAI,OAAO,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,IAAI,OAAO,CAAC,KAAK,CACtE,CAAC,EACD,CAAC,CACF,IAAI,OAAO,CAAC,KAAK,CAAC,CAAC,EAAE,EAAE,CAAC,EAAE;QAC3B,WAAW,EAAE,OAAO;KACrB,CAAC;AACJ,CAAC,CAAC;AAlBW,QAAA,WAAW,eAkBtB"}
|
package/dist/index.d.ts
ADDED
package/dist/index.js
ADDED
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
"use strict";
|
|
3
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
4
|
+
const commander_1 = require("commander");
|
|
5
|
+
const cpf_1 = require("./commands/cpf");
|
|
6
|
+
const program = new commander_1.Command();
|
|
7
|
+
program
|
|
8
|
+
.name("gerar")
|
|
9
|
+
.description("CLI brasileiro para gerar dados fictícios para testes.")
|
|
10
|
+
.version("0.0.1");
|
|
11
|
+
program.helpCommand("help", "Exibe informações de ajuda do CLI.");
|
|
12
|
+
// TODO: Create automatic registration for commands.
|
|
13
|
+
program
|
|
14
|
+
.command(cpf_1.cpfCommand.name)
|
|
15
|
+
.description(cpf_1.cpfCommand.description)
|
|
16
|
+
.option("-a, --amount <amount>", "Quantidade a ser gerado.", (value) => Number(value))
|
|
17
|
+
.action(cpf_1.cpfCommand.action);
|
|
18
|
+
program.parse();
|
|
19
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";;;AACA,yCAAoC;AACpC,wCAA4C;AAE5C,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,CAAC,KAAK,EAAE,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"command-structure.js","sourceRoot":"","sources":["../../../src/shared/utils/command-structure.ts"],"names":[],"mappings":""}
|
package/package.json
ADDED
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "gerar",
|
|
3
|
+
"version": "0.0.2",
|
|
4
|
+
"description": "CLI brasileiro para gerar dados fictícios para testes.",
|
|
5
|
+
"main": "dist/index.js",
|
|
6
|
+
"author": "Victor Ribeiro Boechat",
|
|
7
|
+
"bin": {
|
|
8
|
+
"gerar": "dist/index.js"
|
|
9
|
+
},
|
|
10
|
+
"scripts": {
|
|
11
|
+
"build": "tsc -p .",
|
|
12
|
+
"dev": "tsx src/index.ts",
|
|
13
|
+
"start": "node dist/index.js",
|
|
14
|
+
"test": "vitest run",
|
|
15
|
+
"test:watch": "vitest"
|
|
16
|
+
},
|
|
17
|
+
"keywords": [],
|
|
18
|
+
"license": "ISC",
|
|
19
|
+
"dependencies": {
|
|
20
|
+
"commander": "^14.0.2"
|
|
21
|
+
},
|
|
22
|
+
"devDependencies": {
|
|
23
|
+
"@types/node": "^24.10.1",
|
|
24
|
+
"tsx": "^4.19.2",
|
|
25
|
+
"typescript": "^5.9.3",
|
|
26
|
+
"vitest": "^4.0.13"
|
|
27
|
+
},
|
|
28
|
+
"packageManager": "pnpm@10.20.0"
|
|
29
|
+
}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import { CommandStructure } from "../../shared/utils/command-structure";
|
|
2
|
+
import { generateCpf } from "./utils";
|
|
3
|
+
|
|
4
|
+
export const cpfCommand: CommandStructure = {
|
|
5
|
+
name: "cpf",
|
|
6
|
+
description: "Gera um CPF fictício válido.",
|
|
7
|
+
action: (options: { amount?: number }) => {
|
|
8
|
+
const generatedCpfs = Array.from(
|
|
9
|
+
{ length: options.amount ?? 1 },
|
|
10
|
+
generateCpf
|
|
11
|
+
);
|
|
12
|
+
|
|
13
|
+
generatedCpfs.forEach((generatedCpf, index) => {
|
|
14
|
+
console.log(
|
|
15
|
+
`CPF ${index + 1}) Com Máscara: ${
|
|
16
|
+
generatedCpf.withMask
|
|
17
|
+
} - Sem Máscara: ${generatedCpf.withoutMask}`
|
|
18
|
+
);
|
|
19
|
+
});
|
|
20
|
+
},
|
|
21
|
+
};
|
|
@@ -0,0 +1,114 @@
|
|
|
1
|
+
import { describe, it, expect, expectTypeOf } from "vitest";
|
|
2
|
+
import { calculateCpfDigit, generateCpf } from "../utils";
|
|
3
|
+
|
|
4
|
+
describe("calculateCpfDigit", () => {
|
|
5
|
+
it("should calculate the first check digit correctly for known CPF", () => {
|
|
6
|
+
const firstDigit = calculateCpfDigit("111444777");
|
|
7
|
+
|
|
8
|
+
expect(firstDigit).toBe(3);
|
|
9
|
+
});
|
|
10
|
+
|
|
11
|
+
it("should calculate the second check digit correctly for known CPF", () => {
|
|
12
|
+
const secondDigit = calculateCpfDigit("1114447773");
|
|
13
|
+
|
|
14
|
+
expect(secondDigit).toBe(5);
|
|
15
|
+
});
|
|
16
|
+
|
|
17
|
+
it("should return 0 when remainder is less than 2", () => {
|
|
18
|
+
const digit = calculateCpfDigit("000000000");
|
|
19
|
+
|
|
20
|
+
expect(digit).toBe(0);
|
|
21
|
+
});
|
|
22
|
+
|
|
23
|
+
it("should return correct digit when remainder is 2 or greater", () => {
|
|
24
|
+
const digit = calculateCpfDigit("123456789");
|
|
25
|
+
|
|
26
|
+
expect(digit).toBeGreaterThanOrEqual(0);
|
|
27
|
+
expect(digit).toBeLessThanOrEqual(9);
|
|
28
|
+
});
|
|
29
|
+
|
|
30
|
+
it("should handle 9-digit input correctly", () => {
|
|
31
|
+
const digit = calculateCpfDigit("123456789");
|
|
32
|
+
|
|
33
|
+
expect(digit).toBeTypeOf("number");
|
|
34
|
+
expect(digit).toBeGreaterThanOrEqual(0);
|
|
35
|
+
expect(digit).toBeLessThanOrEqual(9);
|
|
36
|
+
});
|
|
37
|
+
|
|
38
|
+
it("should handle 10-digit input correctly (for second digit calculation)", () => {
|
|
39
|
+
const digit = calculateCpfDigit("1234567890");
|
|
40
|
+
|
|
41
|
+
expect(digit).toBeTypeOf("number");
|
|
42
|
+
expect(digit).toBeGreaterThanOrEqual(0);
|
|
43
|
+
expect(digit).toBeLessThanOrEqual(9);
|
|
44
|
+
});
|
|
45
|
+
});
|
|
46
|
+
|
|
47
|
+
describe("generateCpf", () => {
|
|
48
|
+
it("should generate a CPF with correct structure", () => {
|
|
49
|
+
const result = generateCpf();
|
|
50
|
+
|
|
51
|
+
expect(result).toHaveProperty("withMask");
|
|
52
|
+
expect(result).toHaveProperty("withoutMask");
|
|
53
|
+
});
|
|
54
|
+
|
|
55
|
+
it("should generate CPF withoutMask with exactly 11 digits", () => {
|
|
56
|
+
const result = generateCpf();
|
|
57
|
+
|
|
58
|
+
expect(result.withoutMask).toMatch(/^\d{11}$/);
|
|
59
|
+
expect(result.withoutMask.length).toBe(11);
|
|
60
|
+
});
|
|
61
|
+
|
|
62
|
+
it("should generate CPF withMask in correct format (XXX.XXX.XXX-XX)", () => {
|
|
63
|
+
const result = generateCpf();
|
|
64
|
+
|
|
65
|
+
expect(result.withMask).toMatch(/^\d{3}\.\d{3}\.\d{3}-\d{2}$/);
|
|
66
|
+
});
|
|
67
|
+
|
|
68
|
+
it("should generate valid CPF digits (check digits are correct)", () => {
|
|
69
|
+
const result = generateCpf();
|
|
70
|
+
const cpf = result.withoutMask;
|
|
71
|
+
|
|
72
|
+
const base = cpf.slice(0, 9);
|
|
73
|
+
const firstCheckDigit = Number(cpf[9]);
|
|
74
|
+
const secondCheckDigit = Number(cpf[10]);
|
|
75
|
+
|
|
76
|
+
const calculatedFirstDigit = calculateCpfDigit(base);
|
|
77
|
+
expect(firstCheckDigit).toBe(calculatedFirstDigit);
|
|
78
|
+
|
|
79
|
+
const calculatedSecondDigit = calculateCpfDigit(base + firstCheckDigit);
|
|
80
|
+
expect(secondCheckDigit).toBe(calculatedSecondDigit);
|
|
81
|
+
});
|
|
82
|
+
|
|
83
|
+
it("should generate different CPFs on multiple calls", () => {
|
|
84
|
+
const results = Array.from({ length: 10 }, () => generateCpf());
|
|
85
|
+
const uniqueCpfs = new Set(results.map((r) => r.withoutMask));
|
|
86
|
+
|
|
87
|
+
expect(uniqueCpfs.size).toBeGreaterThan(1);
|
|
88
|
+
});
|
|
89
|
+
|
|
90
|
+
it("should generate CPF where withMask and withoutMask represent the same number", () => {
|
|
91
|
+
const result = generateCpf();
|
|
92
|
+
|
|
93
|
+
const unmasked = result.withMask.replace(/[.-]/g, "");
|
|
94
|
+
|
|
95
|
+
expect(unmasked).toBe(result.withoutMask);
|
|
96
|
+
});
|
|
97
|
+
|
|
98
|
+
it("should generate multiple valid CPFs", () => {
|
|
99
|
+
const results = Array.from({ length: 100 }, () => generateCpf());
|
|
100
|
+
|
|
101
|
+
results.forEach((result) => {
|
|
102
|
+
const cpf = result.withoutMask;
|
|
103
|
+
const base = cpf.slice(0, 9);
|
|
104
|
+
const firstCheckDigit = Number(cpf[9]);
|
|
105
|
+
const secondCheckDigit = Number(cpf[10]);
|
|
106
|
+
|
|
107
|
+
const calculatedFirstDigit = calculateCpfDigit(base);
|
|
108
|
+
const calculatedSecondDigit = calculateCpfDigit(base + firstCheckDigit);
|
|
109
|
+
|
|
110
|
+
expect(firstCheckDigit).toBe(calculatedFirstDigit);
|
|
111
|
+
expect(secondCheckDigit).toBe(calculatedSecondDigit);
|
|
112
|
+
});
|
|
113
|
+
});
|
|
114
|
+
});
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
type GenerateCpfResponse = {
|
|
2
|
+
withMask: string;
|
|
3
|
+
withoutMask: string;
|
|
4
|
+
};
|
|
5
|
+
|
|
6
|
+
export const calculateCpfDigit = (cpf: string): number => {
|
|
7
|
+
const length = cpf.length + 1;
|
|
8
|
+
const sum = cpf
|
|
9
|
+
.split("")
|
|
10
|
+
.reduce((acc, num, index) => acc + Number(num) * (length - index), 0);
|
|
11
|
+
|
|
12
|
+
const remainder = sum % 11;
|
|
13
|
+
|
|
14
|
+
return remainder < 2 ? 0 : 11 - remainder;
|
|
15
|
+
};
|
|
16
|
+
|
|
17
|
+
export const generateCpf = (): GenerateCpfResponse => {
|
|
18
|
+
const baseCpf = Array.from({ length: 9 }, () =>
|
|
19
|
+
Math.floor(Math.random() * 10)
|
|
20
|
+
).join("");
|
|
21
|
+
|
|
22
|
+
const firstDigit = calculateCpfDigit(baseCpf);
|
|
23
|
+
const lastDigit = calculateCpfDigit(baseCpf + firstDigit);
|
|
24
|
+
|
|
25
|
+
const fullCpf = baseCpf + firstDigit.toString() + lastDigit.toString();
|
|
26
|
+
|
|
27
|
+
return {
|
|
28
|
+
// TODO: Improve this as soon as possible.
|
|
29
|
+
withMask: `${fullCpf.slice(0, 3)}.${fullCpf.slice(3, 6)}.${fullCpf.slice(
|
|
30
|
+
6,
|
|
31
|
+
9
|
|
32
|
+
)}-${fullCpf.slice(9, 11)}`,
|
|
33
|
+
withoutMask: fullCpf,
|
|
34
|
+
};
|
|
35
|
+
};
|
package/src/index.ts
ADDED
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import { Command } from "commander";
|
|
3
|
+
import { cpfCommand } from "./commands/cpf";
|
|
4
|
+
|
|
5
|
+
const program = new Command();
|
|
6
|
+
|
|
7
|
+
program
|
|
8
|
+
.name("gerar")
|
|
9
|
+
.description("CLI brasileiro para gerar dados fictícios para testes.")
|
|
10
|
+
.version("0.0.1");
|
|
11
|
+
|
|
12
|
+
program.helpCommand("help", "Exibe informações de ajuda do CLI.");
|
|
13
|
+
|
|
14
|
+
// TODO: Create automatic registration for commands.
|
|
15
|
+
program
|
|
16
|
+
.command(cpfCommand.name)
|
|
17
|
+
.description(cpfCommand.description)
|
|
18
|
+
.option(
|
|
19
|
+
"-a, --amount <amount>",
|
|
20
|
+
"Quantidade a ser gerado.",
|
|
21
|
+
(value: string) => Number(value)
|
|
22
|
+
)
|
|
23
|
+
.action(cpfCommand.action);
|
|
24
|
+
|
|
25
|
+
program.parse();
|
package/tsconfig.json
ADDED
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
{
|
|
2
|
+
"compilerOptions": {
|
|
3
|
+
"target": "es2022",
|
|
4
|
+
"module": "commonjs",
|
|
5
|
+
"lib": ["es2022"],
|
|
6
|
+
"outDir": "dist",
|
|
7
|
+
"rootDir": "src",
|
|
8
|
+
"strict": true,
|
|
9
|
+
"esModuleInterop": true,
|
|
10
|
+
"skipLibCheck": true,
|
|
11
|
+
"forceConsistentCasingInFileNames": true,
|
|
12
|
+
"declaration": true,
|
|
13
|
+
"sourceMap": true
|
|
14
|
+
},
|
|
15
|
+
"include": ["src/**/*"],
|
|
16
|
+
"exclude": ["node_modules", "dist", "src/**/tests/**"]
|
|
17
|
+
}
|