@arkyn/shared 1.5.0 → 1.5.1
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.txt +24 -0
- package/README.md +113 -0
- package/dist/formats/formatDate.d.ts +43 -0
- package/dist/formats/formatDate.d.ts.map +1 -0
- package/dist/formats/formatDate.js +77 -0
- package/dist/formats/formatJsonObject.d.ts +31 -1
- package/dist/formats/formatJsonObject.d.ts.map +1 -1
- package/dist/formats/formatJsonObject.js +67 -26
- package/dist/formats/formatJsonString.d.ts +37 -1
- package/dist/formats/formatJsonString.d.ts.map +1 -1
- package/dist/formats/formatJsonString.js +38 -4
- package/dist/formats/formatToCep.d.ts +27 -1
- package/dist/formats/formatToCep.d.ts.map +1 -1
- package/dist/formats/formatToCep.js +31 -6
- package/dist/formats/formatToCnpj.d.ts +30 -0
- package/dist/formats/formatToCnpj.d.ts.map +1 -0
- package/dist/formats/formatToCnpj.js +35 -0
- package/dist/formats/formatToCpf.d.ts +30 -0
- package/dist/formats/formatToCpf.d.ts.map +1 -0
- package/dist/formats/formatToCpf.js +35 -0
- package/dist/formats/formatToCpfCnpj.d.ts +22 -1
- package/dist/formats/formatToCpfCnpj.d.ts.map +1 -1
- package/dist/formats/formatToCpfCnpj.js +27 -7
- package/dist/formats/formatToCurrency.d.ts +29 -0
- package/dist/formats/formatToCurrency.d.ts.map +1 -0
- package/dist/formats/formatToCurrency.js +41 -0
- package/dist/formats/formatToEllipsis.d.ts +14 -1
- package/dist/formats/formatToEllipsis.d.ts.map +1 -1
- package/dist/formats/formatToEllipsis.js +20 -3
- package/dist/formats/formatToHiddenDigits.d.ts +30 -2
- package/dist/formats/formatToHiddenDigits.d.ts.map +1 -1
- package/dist/formats/formatToHiddenDigits.js +49 -3
- package/dist/formats/formatToPhone.d.ts +32 -1
- package/dist/formats/formatToPhone.d.ts.map +1 -1
- package/dist/formats/formatToPhone.js +128 -6
- package/dist/generators/generateColorByString.d.ts +13 -1
- package/dist/generators/generateColorByString.d.ts.map +1 -1
- package/dist/generators/generateColorByString.js +15 -4
- package/dist/generators/generateId.d.ts +26 -4
- package/dist/generators/generateId.d.ts.map +1 -1
- package/dist/generators/generateId.js +11 -5
- package/dist/generators/generateSlug.d.ts +15 -1
- package/dist/generators/generateSlug.d.ts.map +1 -1
- package/dist/generators/generateSlug.js +16 -2
- package/dist/index.d.ts +9 -10
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +10 -12
- package/dist/services/calculateCardInstallment.d.ts +31 -5
- package/dist/services/calculateCardInstallment.d.ts.map +1 -1
- package/dist/services/calculateCardInstallment.js +52 -11
- package/dist/services/maskSensitiveData.d.ts +24 -1
- package/dist/services/maskSensitiveData.d.ts.map +1 -1
- package/dist/services/maskSensitiveData.js +24 -2
- package/dist/services/removeCurrencySymbols.d.ts +20 -0
- package/dist/services/removeCurrencySymbols.d.ts.map +1 -0
- package/dist/services/removeCurrencySymbols.js +23 -0
- package/dist/services/removeNonNumeric.d.ts +15 -0
- package/dist/services/removeNonNumeric.d.ts.map +1 -0
- package/dist/services/removeNonNumeric.js +16 -0
- package/dist/services/truncateLargeFields.d.ts +30 -1
- package/dist/services/truncateLargeFields.d.ts.map +1 -1
- package/dist/services/truncateLargeFields.js +34 -6
- package/dist/validations/validateCep.d.ts +24 -0
- package/dist/validations/validateCep.d.ts.map +1 -0
- package/dist/validations/validateCep.js +33 -0
- package/dist/validations/validateCnpj.d.ts +22 -0
- package/dist/validations/validateCnpj.d.ts.map +1 -0
- package/dist/validations/validateCnpj.js +52 -0
- package/dist/validations/validateCpf.d.ts +24 -0
- package/dist/validations/validateCpf.d.ts.map +1 -0
- package/dist/validations/validateCpf.js +54 -0
- package/dist/validations/validateDate.d.ts +27 -6
- package/dist/validations/validateDate.d.ts.map +1 -1
- package/dist/validations/validateDate.js +38 -12
- package/dist/validations/validatePassword.d.ts +21 -0
- package/dist/validations/validatePassword.d.ts.map +1 -0
- package/dist/validations/validatePassword.js +34 -0
- package/dist/validations/validatePhone.d.ts +27 -1
- package/dist/validations/validatePhone.d.ts.map +1 -1
- package/dist/validations/validatePhone.js +29 -4
- package/dist/validations/validateRg.d.ts +22 -0
- package/dist/validations/validateRg.d.ts.map +1 -0
- package/dist/validations/validateRg.js +31 -0
- package/package.json +7 -2
- package/src/formats/__test__/formatDate.spec.ts +88 -0
- package/src/formats/__test__/formatJsonObject.spec.ts +87 -0
- package/src/formats/__test__/formatJsonString.spec.ts +83 -0
- package/src/formats/__test__/formatToCep.spec.ts +37 -0
- package/src/formats/__test__/formatToCnpj.spec.ts +35 -0
- package/src/formats/__test__/formatToCpf.spec.ts +37 -0
- package/src/formats/__test__/formatToCpfCnpj.spec.ts +43 -0
- package/src/formats/__test__/formatToCurrency.spec.ts +50 -0
- package/src/formats/__test__/formatToEllipsis.spec.ts +44 -0
- package/src/formats/__test__/formatToHiddenDigits.spec.ts +58 -0
- package/src/formats/__test__/formatToPhone.spec.ts +58 -0
- package/src/formats/formatDate.ts +97 -0
- package/src/formats/formatJsonObject.ts +68 -26
- package/src/formats/formatJsonString.ts +40 -4
- package/src/formats/formatToCep.ts +35 -7
- package/src/formats/formatToCnpj.ts +39 -0
- package/src/formats/formatToCpf.ts +39 -0
- package/src/formats/formatToCpfCnpj.ts +31 -7
- package/src/formats/formatToCurrency.ts +53 -0
- package/src/formats/formatToEllipsis.ts +23 -3
- package/src/formats/formatToHiddenDigits.ts +75 -7
- package/src/formats/formatToPhone.ts +156 -6
- package/src/generators/__test__/generateColorByString.spec.ts +37 -0
- package/src/generators/__test__/generateId.spec.ts +44 -0
- package/src/generators/__test__/generateSlug.spec.ts +47 -0
- package/src/generators/generateColorByString.ts +18 -4
- package/src/generators/generateId.ts +36 -5
- package/src/generators/generateSlug.ts +17 -2
- package/src/index.ts +10 -13
- package/src/services/__test__/calculateCardInstallment.spec.ts +87 -0
- package/src/services/__test__/maskSensitiveData.spec.ts +102 -0
- package/src/services/__test__/removeCurrencySymbols.spec.ts +41 -0
- package/src/services/__test__/removeNonNumeric.spec.ts +33 -0
- package/src/services/__test__/truncateLargeFields.spec.ts +90 -0
- package/src/services/calculateCardInstallment.ts +57 -12
- package/src/services/maskSensitiveData.ts +29 -4
- package/src/services/removeCurrencySymbols.ts +25 -0
- package/src/services/removeNonNumeric.ts +18 -0
- package/src/services/truncateLargeFields.ts +40 -6
- package/src/validations/__test__/validateCep.spec.ts +40 -0
- package/src/validations/__test__/validateCnpj.spec.ts +42 -0
- package/src/validations/__test__/validateCpf.spec.ts +38 -0
- package/src/validations/__test__/validateDate.spec.ts +81 -0
- package/src/validations/__test__/validatePassword.spec.ts +43 -0
- package/src/validations/__test__/validatePhone.spec.ts +39 -0
- package/src/validations/__test__/validateRg.spec.ts +48 -0
- package/src/validations/validateCep.ts +40 -0
- package/src/validations/validateCnpj.ts +64 -0
- package/src/validations/validateCpf.ts +61 -0
- package/src/validations/validateDate.ts +39 -17
- package/src/validations/validatePassword.ts +41 -0
- package/src/validations/validatePhone.ts +31 -4
- package/src/validations/validateRg.ts +37 -0
- package/tsconfig.json +2 -2
- package/vitest.config.ts +5 -0
- package/dist/formats/formatBrazilianDateHour.d.ts +0 -3
- package/dist/formats/formatBrazilianDateHour.d.ts.map +0 -1
- package/dist/formats/formatBrazilianDateHour.js +0 -12
- package/dist/formats/formatBrazilianDateToDate.d.ts +0 -3
- package/dist/formats/formatBrazilianDateToDate.d.ts.map +0 -1
- package/dist/formats/formatBrazilianDateToDate.js +0 -9
- package/dist/formats/formatDateHour.d.ts +0 -3
- package/dist/formats/formatDateHour.d.ts.map +0 -1
- package/dist/formats/formatDateHour.js +0 -11
- package/dist/formats/formatToBRL.d.ts +0 -3
- package/dist/formats/formatToBRL.d.ts.map +0 -1
- package/dist/formats/formatToBRL.js +0 -8
- package/dist/formats/formatToCNPJ.d.ts +0 -3
- package/dist/formats/formatToCNPJ.d.ts.map +0 -1
- package/dist/formats/formatToCNPJ.js +0 -9
- package/dist/formats/formatToCPF.d.ts +0 -3
- package/dist/formats/formatToCPF.d.ts.map +0 -1
- package/dist/formats/formatToCPF.js +0 -9
- package/dist/parsers/parseToCharacters.d.ts +0 -17
- package/dist/parsers/parseToCharacters.d.ts.map +0 -1
- package/dist/parsers/parseToCharacters.js +0 -13
- package/dist/services/range.d.ts +0 -4
- package/dist/services/range.d.ts.map +0 -1
- package/dist/services/range.js +0 -9
- package/dist/validations/regex.d.ts +0 -15
- package/dist/validations/regex.d.ts.map +0 -1
- package/dist/validations/regex.js +0 -25
- package/dist/validations/validateCPF.d.ts +0 -3
- package/dist/validations/validateCPF.d.ts.map +0 -1
- package/dist/validations/validateCPF.js +0 -36
- package/src/formats/formatBrazilianDateHour.ts +0 -17
- package/src/formats/formatBrazilianDateToDate.ts +0 -13
- package/src/formats/formatDateHour.ts +0 -15
- package/src/formats/formatToBRL.ts +0 -10
- package/src/formats/formatToCNPJ.ts +0 -10
- package/src/formats/formatToCPF.ts +0 -10
- package/src/parsers/parseToCharacters.ts +0 -34
- package/src/services/range.ts +0 -15
- package/src/validations/regex.ts +0 -41
- package/src/validations/validateCPF.ts +0 -38
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
import { describe, it, expect } from "vitest";
|
|
2
|
+
import { generateSlug } from "../generateSlug";
|
|
3
|
+
|
|
4
|
+
describe("generateSlug", () => {
|
|
5
|
+
it("should convert a string to a URL-friendly slug", () => {
|
|
6
|
+
expect(generateSlug("Hello World")).toBe("hello-world");
|
|
7
|
+
expect(generateSlug("This is a Test")).toBe("this-is-a-test");
|
|
8
|
+
});
|
|
9
|
+
|
|
10
|
+
it("should remove diacritical marks (accents)", () => {
|
|
11
|
+
expect(generateSlug("Olá Mundo")).toBe("ola-mundo");
|
|
12
|
+
expect(generateSlug("Crème brûlée")).toBe("creme-brulee");
|
|
13
|
+
});
|
|
14
|
+
|
|
15
|
+
it("should remove non-alphanumeric characters except spaces and hyphens", () => {
|
|
16
|
+
expect(generateSlug("Hello, World!")).toBe("hello-world");
|
|
17
|
+
expect(generateSlug("C# Programming")).toBe("c-programming");
|
|
18
|
+
});
|
|
19
|
+
|
|
20
|
+
it("should collapse multiple spaces into a single hyphen", () => {
|
|
21
|
+
expect(generateSlug("Hello World")).toBe("hello-world");
|
|
22
|
+
});
|
|
23
|
+
|
|
24
|
+
it("should collapse multiple consecutive hyphens into a single hyphen", () => {
|
|
25
|
+
expect(generateSlug("Hello--World")).toBe("hello-world");
|
|
26
|
+
expect(generateSlug("Hello---World")).toBe("hello-world");
|
|
27
|
+
});
|
|
28
|
+
|
|
29
|
+
it("should trim leading and trailing hyphens", () => {
|
|
30
|
+
expect(generateSlug("-Hello World-")).toBe("hello-world");
|
|
31
|
+
expect(generateSlug("--Hello World--")).toBe("hello-world");
|
|
32
|
+
});
|
|
33
|
+
|
|
34
|
+
it("should handle empty strings", () => {
|
|
35
|
+
expect(generateSlug("")).toBe("");
|
|
36
|
+
});
|
|
37
|
+
|
|
38
|
+
it("should handle strings with only special characters", () => {
|
|
39
|
+
expect(generateSlug("!@#$%^&*()")).toBe("");
|
|
40
|
+
expect(generateSlug("---")).toBe("");
|
|
41
|
+
});
|
|
42
|
+
|
|
43
|
+
it("should handle strings with numbers", () => {
|
|
44
|
+
expect(generateSlug("Version 2.0")).toBe("version-20");
|
|
45
|
+
expect(generateSlug("123 Testing")).toBe("123-testing");
|
|
46
|
+
});
|
|
47
|
+
});
|
|
@@ -1,8 +1,22 @@
|
|
|
1
|
-
|
|
1
|
+
import type { GenerateColorByStringFunction } from "@arkyn/types";
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Generates a hexadecimal color code based on the input string.
|
|
5
|
+
* The function creates a hash from the string and uses it to calculate
|
|
6
|
+
* RGB values, which are then converted to a hexadecimal color code.
|
|
7
|
+
*
|
|
8
|
+
* @param prop - The input string used to generate the color.
|
|
9
|
+
* @returns A hexadecimal color code (e.g., "#a1b2c3") derived from the input string.
|
|
10
|
+
* @example
|
|
11
|
+
* const color = generateColorByString("example");
|
|
12
|
+
* console.log(color); // Outputs a consistent hex color like "#5e8f9a"
|
|
13
|
+
*/
|
|
14
|
+
|
|
15
|
+
const generateColorByString: GenerateColorByStringFunction = (prop) => {
|
|
2
16
|
var hash = 0;
|
|
3
17
|
|
|
4
|
-
for (var i = 0; i <
|
|
5
|
-
hash =
|
|
18
|
+
for (var i = 0; i < prop.length; i++) {
|
|
19
|
+
hash = prop.charCodeAt(i) + ((hash << 5) - hash);
|
|
6
20
|
}
|
|
7
21
|
|
|
8
22
|
var red = (hash & 0xff0000) >> 16;
|
|
@@ -14,6 +28,6 @@ function generateColorByString(string: string) {
|
|
|
14
28
|
var blueHex = blue.toString(16).padStart(2, "0");
|
|
15
29
|
|
|
16
30
|
return "#" + redHex + greenHex + blueHex;
|
|
17
|
-
}
|
|
31
|
+
};
|
|
18
32
|
|
|
19
33
|
export { generateColorByString };
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { v4, v7 } from "uuid";
|
|
2
2
|
|
|
3
3
|
function hexToBin(hex: string) {
|
|
4
|
+
hex = hex.replace(/-/g, "");
|
|
4
5
|
const buffer = new Uint8Array(hex.length / 2);
|
|
5
6
|
|
|
6
7
|
for (let i = 0; i < hex.length; i += 2) {
|
|
@@ -20,11 +21,41 @@ function uuidV7() {
|
|
|
20
21
|
return { text: uuid, binary: hexToBin(uuid) };
|
|
21
22
|
}
|
|
22
23
|
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
24
|
+
/**
|
|
25
|
+
* Generates a unique identifier (UUID) in the specified format and type.
|
|
26
|
+
*
|
|
27
|
+
* @param type - The desired output type of the UUID. Can be:
|
|
28
|
+
* - `"text"`: Returns the UUID as a string.
|
|
29
|
+
* - `"binary"`: Returns the UUID as a `Uint8Array` in binary format.
|
|
30
|
+
* @param format - The version of the UUID to generate. Can be:
|
|
31
|
+
* - `"v4"`: Generates a random UUID (version 4).
|
|
32
|
+
* - `"v7"`: Generates a time-ordered UUID (version 7).
|
|
33
|
+
* @returns The generated UUID in the specified type and format.
|
|
34
|
+
* - If `type` is `"text"`, a string representation of the UUID is returned.
|
|
35
|
+
* - If `type` is `"binary"`, a `Uint8Array` representation of the UUID is returned.
|
|
36
|
+
* @throws {Error} If an invalid `type` or `format` is provided.
|
|
37
|
+
*
|
|
38
|
+
* @example
|
|
39
|
+
* // Generate a version 4 UUID as a string
|
|
40
|
+
* const idTextV4 = generateId("text", "v4");
|
|
41
|
+
* console.log(idTextV4); // e.g., "550e8400-e29b-41d4-a716-446655440000"
|
|
42
|
+
*
|
|
43
|
+
* @example
|
|
44
|
+
* // Generate a version 7 UUID as binary
|
|
45
|
+
* const idBinaryV7 = generateId("binary", "v7");
|
|
46
|
+
* console.log(idBinaryV7); // Uint8Array([...])
|
|
47
|
+
*/
|
|
48
|
+
function generateId(type: "text", format: "v4" | "v7"): string;
|
|
49
|
+
function generateId(type: "binary", format: "v4" | "v7"): Uint8Array;
|
|
50
|
+
function generateId(
|
|
51
|
+
type: "text" | "binary",
|
|
52
|
+
format: "v4" | "v7"
|
|
53
|
+
): string | Uint8Array {
|
|
54
|
+
if (type === "text" && format === "v4") return uuidV4().text;
|
|
55
|
+
if (type === "binary" && format === "v4") return uuidV4().binary;
|
|
56
|
+
if (type === "text" && format === "v7") return uuidV7().text;
|
|
57
|
+
if (type === "binary" && format === "v7") return uuidV7().binary;
|
|
58
|
+
throw new Error("Invalid type or format");
|
|
28
59
|
}
|
|
29
60
|
|
|
30
61
|
export { generateId };
|
|
@@ -1,5 +1,20 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
1
|
+
/**
|
|
2
|
+
* Generates a URL-friendly slug from a given string.
|
|
3
|
+
*
|
|
4
|
+
* The function performs the following transformations:
|
|
5
|
+
* - Normalizes the string to remove diacritical marks (e.g., accents).
|
|
6
|
+
* - Removes non-alphanumeric characters except for spaces and hyphens.
|
|
7
|
+
* - Replaces spaces with hyphens.
|
|
8
|
+
* - Converts the string to lowercase.
|
|
9
|
+
* - Collapses multiple consecutive hyphens into a single hyphen.
|
|
10
|
+
* - Trims leading and trailing hyphens.
|
|
11
|
+
*
|
|
12
|
+
* @param string - The input string to be converted into a slug.
|
|
13
|
+
* @returns A URL-friendly slug derived from the input string.
|
|
14
|
+
*/
|
|
15
|
+
|
|
16
|
+
function generateSlug(prop: string) {
|
|
17
|
+
let slug = prop.normalize("NFD").replace(/[\u0300-\u036f]/g, "");
|
|
3
18
|
|
|
4
19
|
slug = slug
|
|
5
20
|
.replace(/[^\w\s-]/g, "")
|
package/src/index.ts
CHANGED
|
@@ -1,14 +1,12 @@
|
|
|
1
1
|
// formats
|
|
2
|
-
export {
|
|
3
|
-
export { formatBrazilianDateToDate } from "./formats/formatBrazilianDateToDate";
|
|
4
|
-
export { formatDateHour } from "./formats/formatDateHour";
|
|
2
|
+
export { formatDate } from "./formats/formatDate";
|
|
5
3
|
export { formatJsonObject } from "./formats/formatJsonObject";
|
|
6
4
|
export { formatJsonString } from "./formats/formatJsonString";
|
|
7
|
-
export { formatToBRL } from "./formats/formatToBRL";
|
|
8
5
|
export { formatToCep } from "./formats/formatToCep";
|
|
9
|
-
export {
|
|
10
|
-
export {
|
|
6
|
+
export { formatToCnpj } from "./formats/formatToCnpj";
|
|
7
|
+
export { formatToCpf } from "./formats/formatToCpf";
|
|
11
8
|
export { formatToCpfCnpj } from "./formats/formatToCpfCnpj";
|
|
9
|
+
export { formatToCurrency } from "./formats/formatToCurrency";
|
|
12
10
|
export { formatToEllipsis } from "./formats/formatToEllipsis";
|
|
13
11
|
export { formatToHiddenDigits } from "./formats/formatToHiddenDigits";
|
|
14
12
|
export { formatToPhone } from "./formats/formatToPhone";
|
|
@@ -18,17 +16,16 @@ export { generateColorByString } from "./generators/generateColorByString";
|
|
|
18
16
|
export { generateId } from "./generators/generateId";
|
|
19
17
|
export { generateSlug } from "./generators/generateSlug";
|
|
20
18
|
|
|
21
|
-
// parsers
|
|
22
|
-
export { parseToCharacters } from "./parsers/parseToCharacters";
|
|
23
|
-
|
|
24
19
|
// services
|
|
25
20
|
export { calculateCardInstallment } from "./services/calculateCardInstallment";
|
|
26
21
|
export { maskSensitiveData } from "./services/maskSensitiveData";
|
|
27
|
-
export {
|
|
22
|
+
export { removeNonNumeric } from "./services/removeNonNumeric";
|
|
28
23
|
export { truncateLargeFields } from "./services/truncateLargeFields";
|
|
29
24
|
|
|
30
|
-
//
|
|
31
|
-
export {
|
|
32
|
-
export {
|
|
25
|
+
// utils
|
|
26
|
+
export { validateCep } from "./validations/validateCep";
|
|
27
|
+
export { validateCnpj } from "./validations/validateCnpj";
|
|
28
|
+
export { validateCpf } from "./validations/validateCpf";
|
|
33
29
|
export { validateDate } from "./validations/validateDate";
|
|
34
30
|
export { validatePhone } from "./validations/validatePhone";
|
|
31
|
+
export { validateRg } from "./validations/validateRg";
|
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
import { describe, it, expect } from "vitest";
|
|
2
|
+
import { calculateCardInstallment } from "../calculateCardInstallment";
|
|
3
|
+
|
|
4
|
+
describe("calculateCardInstallment", () => {
|
|
5
|
+
it("should calculate the total and installment price with default fees", () => {
|
|
6
|
+
const result = calculateCardInstallment({
|
|
7
|
+
cashPrice: 1000,
|
|
8
|
+
numberInstallments: 12,
|
|
9
|
+
});
|
|
10
|
+
|
|
11
|
+
expect(result).toEqual({
|
|
12
|
+
totalPrice: 1241.08,
|
|
13
|
+
installmentPrice: 103.42,
|
|
14
|
+
});
|
|
15
|
+
});
|
|
16
|
+
|
|
17
|
+
it("should calculate the total and installment price with custom fees", () => {
|
|
18
|
+
const result = calculateCardInstallment({
|
|
19
|
+
cashPrice: 1000,
|
|
20
|
+
numberInstallments: 12,
|
|
21
|
+
fees: 0.02,
|
|
22
|
+
});
|
|
23
|
+
|
|
24
|
+
expect(result).toEqual({
|
|
25
|
+
totalPrice: 1134.72,
|
|
26
|
+
installmentPrice: 94.56,
|
|
27
|
+
});
|
|
28
|
+
});
|
|
29
|
+
|
|
30
|
+
it("should calculate correctly for a single installment (no interest)", () => {
|
|
31
|
+
const result = calculateCardInstallment({
|
|
32
|
+
cashPrice: 1000,
|
|
33
|
+
numberInstallments: 1,
|
|
34
|
+
fees: 0,
|
|
35
|
+
});
|
|
36
|
+
|
|
37
|
+
expect(result).toEqual({
|
|
38
|
+
totalPrice: 1000,
|
|
39
|
+
installmentPrice: 1000,
|
|
40
|
+
});
|
|
41
|
+
});
|
|
42
|
+
|
|
43
|
+
it("should calculate correctly for zero fees", () => {
|
|
44
|
+
const result = calculateCardInstallment({
|
|
45
|
+
cashPrice: 500,
|
|
46
|
+
numberInstallments: 5,
|
|
47
|
+
fees: 0,
|
|
48
|
+
});
|
|
49
|
+
|
|
50
|
+
expect(result).toEqual({
|
|
51
|
+
totalPrice: 500,
|
|
52
|
+
installmentPrice: 100,
|
|
53
|
+
});
|
|
54
|
+
});
|
|
55
|
+
|
|
56
|
+
it("should handle edge case with zero installments", () => {
|
|
57
|
+
expect(() =>
|
|
58
|
+
calculateCardInstallment({
|
|
59
|
+
cashPrice: 1000,
|
|
60
|
+
numberInstallments: 0,
|
|
61
|
+
})
|
|
62
|
+
).toThrow("Number of installments must be greater than 0");
|
|
63
|
+
});
|
|
64
|
+
|
|
65
|
+
it("should handle edge case with negative fees", () => {
|
|
66
|
+
expect(() =>
|
|
67
|
+
calculateCardInstallment({
|
|
68
|
+
cashPrice: 1000,
|
|
69
|
+
numberInstallments: 12,
|
|
70
|
+
fees: -0.01,
|
|
71
|
+
})
|
|
72
|
+
).toThrow("Fees must be greater than or equal to 0");
|
|
73
|
+
});
|
|
74
|
+
|
|
75
|
+
it("should handle large numbers for cash price and installments", () => {
|
|
76
|
+
const result = calculateCardInstallment({
|
|
77
|
+
cashPrice: 1000000,
|
|
78
|
+
numberInstallments: 24,
|
|
79
|
+
fees: 0.01,
|
|
80
|
+
});
|
|
81
|
+
|
|
82
|
+
expect(result).toEqual({
|
|
83
|
+
totalPrice: 1129763.33,
|
|
84
|
+
installmentPrice: 47073.47,
|
|
85
|
+
});
|
|
86
|
+
});
|
|
87
|
+
});
|
|
@@ -0,0 +1,102 @@
|
|
|
1
|
+
import { describe, it, expect } from "vitest";
|
|
2
|
+
import { maskSensitiveData } from "../maskSensitiveData";
|
|
3
|
+
|
|
4
|
+
describe("maskSensitiveData", () => {
|
|
5
|
+
it("should mask sensitive keys in a flat JSON object", () => {
|
|
6
|
+
const jsonString = JSON.stringify({
|
|
7
|
+
username: "user123",
|
|
8
|
+
password: "secret",
|
|
9
|
+
email: "user@example.com",
|
|
10
|
+
});
|
|
11
|
+
|
|
12
|
+
const result = maskSensitiveData(jsonString, ["password"]);
|
|
13
|
+
expect(result).toBe(
|
|
14
|
+
'{"username":"user123","password":"****","email":"user@example.com"}'
|
|
15
|
+
);
|
|
16
|
+
});
|
|
17
|
+
|
|
18
|
+
it("should mask sensitive keys in nested objects", () => {
|
|
19
|
+
const jsonString = JSON.stringify({
|
|
20
|
+
profile: {
|
|
21
|
+
username: "user123",
|
|
22
|
+
creditCard: "1234-5678-9012-3456",
|
|
23
|
+
},
|
|
24
|
+
});
|
|
25
|
+
|
|
26
|
+
const result = maskSensitiveData(jsonString, ["creditCard"]);
|
|
27
|
+
expect(result).toBe(
|
|
28
|
+
'{"profile":{"username":"user123","creditCard":"****"}}'
|
|
29
|
+
);
|
|
30
|
+
});
|
|
31
|
+
|
|
32
|
+
it("should mask sensitive keys in arrays", () => {
|
|
33
|
+
const jsonString = JSON.stringify({
|
|
34
|
+
users: [
|
|
35
|
+
{ username: "user1", password: "pass1" },
|
|
36
|
+
{ username: "user2", password: "pass2" },
|
|
37
|
+
],
|
|
38
|
+
});
|
|
39
|
+
|
|
40
|
+
const result = maskSensitiveData(jsonString, ["password"]);
|
|
41
|
+
expect(result).toBe(
|
|
42
|
+
'{"users":[{"username":"user1","password":"****"},{"username":"user2","password":"****"}]}'
|
|
43
|
+
);
|
|
44
|
+
});
|
|
45
|
+
|
|
46
|
+
it("should handle non-JSON strings gracefully", () => {
|
|
47
|
+
const invalidJson = "not a json string";
|
|
48
|
+
const result = maskSensitiveData(invalidJson, ["password"]);
|
|
49
|
+
expect(result).toBe("not a json string");
|
|
50
|
+
});
|
|
51
|
+
|
|
52
|
+
it("should handle empty JSON objects", () => {
|
|
53
|
+
const jsonString = JSON.stringify({});
|
|
54
|
+
const result = maskSensitiveData(jsonString, ["password"]);
|
|
55
|
+
expect(result).toBe("{}");
|
|
56
|
+
});
|
|
57
|
+
|
|
58
|
+
it("should handle empty arrays", () => {
|
|
59
|
+
const jsonString = JSON.stringify([]);
|
|
60
|
+
const result = maskSensitiveData(jsonString, ["password"]);
|
|
61
|
+
expect(result).toBe("[]");
|
|
62
|
+
});
|
|
63
|
+
|
|
64
|
+
it("should use default sensitive keys if none are provided", () => {
|
|
65
|
+
const jsonString = JSON.stringify({
|
|
66
|
+
username: "user123",
|
|
67
|
+
password: "secret",
|
|
68
|
+
confirmPassword: "secret",
|
|
69
|
+
creditCard: "1234-5678-9012-3456",
|
|
70
|
+
});
|
|
71
|
+
|
|
72
|
+
const result = maskSensitiveData(jsonString);
|
|
73
|
+
expect(result).toBe(
|
|
74
|
+
'{"username":"user123","password":"****","confirmPassword":"****","creditCard":"****"}'
|
|
75
|
+
);
|
|
76
|
+
});
|
|
77
|
+
|
|
78
|
+
it("should not mask keys that are not in the sensitive keys list", () => {
|
|
79
|
+
const jsonString = JSON.stringify({
|
|
80
|
+
username: "user123",
|
|
81
|
+
email: "user@example.com",
|
|
82
|
+
});
|
|
83
|
+
|
|
84
|
+
const result = maskSensitiveData(jsonString, ["password"]);
|
|
85
|
+
expect(result).toBe('{"username":"user123","email":"user@example.com"}');
|
|
86
|
+
});
|
|
87
|
+
|
|
88
|
+
it("should handle deeply nested objects", () => {
|
|
89
|
+
const jsonString = JSON.stringify({
|
|
90
|
+
level1: {
|
|
91
|
+
level2: {
|
|
92
|
+
level3: {
|
|
93
|
+
password: "secret",
|
|
94
|
+
},
|
|
95
|
+
},
|
|
96
|
+
},
|
|
97
|
+
});
|
|
98
|
+
|
|
99
|
+
const result = maskSensitiveData(jsonString, ["password"]);
|
|
100
|
+
expect(result).toBe('{"level1":{"level2":{"level3":{"password":"****"}}}}');
|
|
101
|
+
});
|
|
102
|
+
});
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
import { describe, it, expect } from "vitest";
|
|
2
|
+
import { removeCurrencySymbols } from "../removeCurrencySymbols";
|
|
3
|
+
|
|
4
|
+
describe("removeCurrencySymbols", () => {
|
|
5
|
+
it("should remove common currency symbols from the string", () => {
|
|
6
|
+
expect(removeCurrencySymbols("R$13,45")).toBe("13,45");
|
|
7
|
+
expect(removeCurrencySymbols("$123.45")).toBe("123.45");
|
|
8
|
+
expect(removeCurrencySymbols("€99.99")).toBe("99.99");
|
|
9
|
+
expect(removeCurrencySymbols("¥1,000")).toBe("1,000");
|
|
10
|
+
});
|
|
11
|
+
|
|
12
|
+
it("should handle strings without currency symbols", () => {
|
|
13
|
+
expect(removeCurrencySymbols("123.45")).toBe("123.45");
|
|
14
|
+
expect(removeCurrencySymbols("1,000")).toBe("1,000");
|
|
15
|
+
});
|
|
16
|
+
|
|
17
|
+
it("should handle strings with multiple currency symbols", () => {
|
|
18
|
+
expect(removeCurrencySymbols("R$ $123.45")).toBe("123.45");
|
|
19
|
+
expect(removeCurrencySymbols("€¥99,99")).toBe("99,99");
|
|
20
|
+
});
|
|
21
|
+
|
|
22
|
+
it("should handle strings with leading and trailing whitespace", () => {
|
|
23
|
+
expect(removeCurrencySymbols(" $123.45 ")).toBe("123.45");
|
|
24
|
+
expect(removeCurrencySymbols("\t€99.99\n")).toBe("99.99");
|
|
25
|
+
});
|
|
26
|
+
|
|
27
|
+
it("should return an empty string if the input is only currency symbols", () => {
|
|
28
|
+
expect(removeCurrencySymbols("R$")).toBe("");
|
|
29
|
+
expect(removeCurrencySymbols("$")).toBe("");
|
|
30
|
+
expect(removeCurrencySymbols("€")).toBe("");
|
|
31
|
+
});
|
|
32
|
+
|
|
33
|
+
it("should handle an empty string input", () => {
|
|
34
|
+
expect(removeCurrencySymbols("")).toBe("");
|
|
35
|
+
});
|
|
36
|
+
|
|
37
|
+
it("should handle strings with special characters but no currency symbols", () => {
|
|
38
|
+
expect(removeCurrencySymbols("123-45")).toBe("123-45");
|
|
39
|
+
expect(removeCurrencySymbols("1,000.00")).toBe("1,000.00");
|
|
40
|
+
});
|
|
41
|
+
});
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import { describe, it, expect } from "vitest";
|
|
2
|
+
import { removeNonNumeric } from "../removeNonNumeric";
|
|
3
|
+
|
|
4
|
+
describe("removeNonNumeric", () => {
|
|
5
|
+
it("should remove all non-numeric characters from a string", () => {
|
|
6
|
+
expect(removeNonNumeric("abc123def456")).toBe("123456");
|
|
7
|
+
expect(removeNonNumeric("!@#123$%^456&*()")).toBe("123456");
|
|
8
|
+
expect(removeNonNumeric("a1b2c3")).toBe("123");
|
|
9
|
+
});
|
|
10
|
+
|
|
11
|
+
it("should return an empty string if there are no numeric characters", () => {
|
|
12
|
+
expect(removeNonNumeric("abcdef")).toBe("");
|
|
13
|
+
expect(removeNonNumeric("!@#$%^&*()")).toBe("");
|
|
14
|
+
});
|
|
15
|
+
|
|
16
|
+
it("should return the same string if it contains only numeric characters", () => {
|
|
17
|
+
expect(removeNonNumeric("123456")).toBe("123456");
|
|
18
|
+
expect(removeNonNumeric("000123")).toBe("000123");
|
|
19
|
+
});
|
|
20
|
+
|
|
21
|
+
it("should handle an empty string input", () => {
|
|
22
|
+
expect(removeNonNumeric("")).toBe("");
|
|
23
|
+
});
|
|
24
|
+
|
|
25
|
+
it("should handle strings with spaces and remove them", () => {
|
|
26
|
+
expect(removeNonNumeric("123 456 789")).toBe("123456789");
|
|
27
|
+
expect(removeNonNumeric(" 1 2 3 ")).toBe("123");
|
|
28
|
+
});
|
|
29
|
+
|
|
30
|
+
it("should handle strings with special characters and preserve only numbers", () => {
|
|
31
|
+
expect(removeNonNumeric("12-34.56/78")).toBe("12345678");
|
|
32
|
+
});
|
|
33
|
+
});
|
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
import { describe, it, expect } from "vitest";
|
|
2
|
+
import { truncateLargeFields } from "../truncateLargeFields";
|
|
3
|
+
|
|
4
|
+
describe("truncateLargeFields", () => {
|
|
5
|
+
it("should truncate string fields exceeding the maxLength", () => {
|
|
6
|
+
const json = JSON.stringify({
|
|
7
|
+
name: "John",
|
|
8
|
+
description: "A very long description that exceeds the maximum length...",
|
|
9
|
+
});
|
|
10
|
+
|
|
11
|
+
const result = truncateLargeFields(json, 20);
|
|
12
|
+
expect(result).toBe(
|
|
13
|
+
'{"name":"John","description":"To large information: field as 58 characters"}'
|
|
14
|
+
);
|
|
15
|
+
});
|
|
16
|
+
|
|
17
|
+
it("should handle nested objects and truncate large string fields", () => {
|
|
18
|
+
const json = JSON.stringify({
|
|
19
|
+
nested: {
|
|
20
|
+
details: "Another long string that needs truncation.",
|
|
21
|
+
},
|
|
22
|
+
});
|
|
23
|
+
|
|
24
|
+
const result = truncateLargeFields(json, 20);
|
|
25
|
+
expect(result).toBe(
|
|
26
|
+
'{"nested":{"details":"To large information: field as 42 characters"}}'
|
|
27
|
+
);
|
|
28
|
+
});
|
|
29
|
+
|
|
30
|
+
it("should handle arrays and truncate large string fields within them", () => {
|
|
31
|
+
const json = JSON.stringify({
|
|
32
|
+
items: ["short", "A very long string in an array that exceeds the limit"],
|
|
33
|
+
});
|
|
34
|
+
|
|
35
|
+
const result = truncateLargeFields(json, 20);
|
|
36
|
+
expect(result).toBe(
|
|
37
|
+
'{"items":["short","To large information: field as 53 characters"]}'
|
|
38
|
+
);
|
|
39
|
+
});
|
|
40
|
+
|
|
41
|
+
it("should not modify fields that are within the maxLength", () => {
|
|
42
|
+
const json = JSON.stringify({
|
|
43
|
+
name: "John",
|
|
44
|
+
description: "Short description",
|
|
45
|
+
});
|
|
46
|
+
|
|
47
|
+
const result = truncateLargeFields(json, 20);
|
|
48
|
+
expect(result).toBe('{"name":"John","description":"Short description"}');
|
|
49
|
+
});
|
|
50
|
+
|
|
51
|
+
it("should throw an error for invalid JSON strings", () => {
|
|
52
|
+
const invalidJson = "{ name: 'John' }"; // Invalid JSON
|
|
53
|
+
expect(() => truncateLargeFields(invalidJson, 20)).toThrow(
|
|
54
|
+
"Invalid JSON string"
|
|
55
|
+
);
|
|
56
|
+
});
|
|
57
|
+
|
|
58
|
+
it("should handle empty JSON objects", () => {
|
|
59
|
+
const json = JSON.stringify({});
|
|
60
|
+
const result = truncateLargeFields(json, 20);
|
|
61
|
+
expect(result).toBe("{}");
|
|
62
|
+
});
|
|
63
|
+
|
|
64
|
+
it("should handle empty arrays", () => {
|
|
65
|
+
const json = JSON.stringify([]);
|
|
66
|
+
const result = truncateLargeFields(json, 20);
|
|
67
|
+
expect(result).toBe("[]");
|
|
68
|
+
});
|
|
69
|
+
|
|
70
|
+
it("should handle non-string fields without modification", () => {
|
|
71
|
+
const json = JSON.stringify({
|
|
72
|
+
number: 123,
|
|
73
|
+
boolean: true,
|
|
74
|
+
nullValue: null,
|
|
75
|
+
});
|
|
76
|
+
|
|
77
|
+
const result = truncateLargeFields(json, 20);
|
|
78
|
+
expect(result).toBe('{"number":123,"boolean":true,"nullValue":null}');
|
|
79
|
+
});
|
|
80
|
+
|
|
81
|
+
it("should use the default maxLength of 1000 if not provided", () => {
|
|
82
|
+
const longString = "a".repeat(1500);
|
|
83
|
+
const json = JSON.stringify({ longField: longString });
|
|
84
|
+
const result = truncateLargeFields(json);
|
|
85
|
+
|
|
86
|
+
expect(result).toBe(
|
|
87
|
+
`{"longField":"To large information: field as 1500 characters"}`
|
|
88
|
+
);
|
|
89
|
+
});
|
|
90
|
+
});
|
|
@@ -1,21 +1,66 @@
|
|
|
1
|
-
import type {
|
|
1
|
+
import type { CalculateCardInstallmentFunction } from "@arkyn/types";
|
|
2
2
|
|
|
3
|
-
|
|
4
|
-
|
|
3
|
+
/**
|
|
4
|
+
* Calculates the installment price and total price for a card payment plan.
|
|
5
|
+
*
|
|
6
|
+
* @remarks
|
|
7
|
+
* **Important:** When the interest amount (`fees`) is equal to 0 or the number of installments (`numberInstallments`) is equal to 1, no interest will be charged.
|
|
8
|
+
*
|
|
9
|
+
* @throws Will throw an error if the number of installments is less than or equal to 0.
|
|
10
|
+
* @throws Will throw an error if the fees are less than 0.
|
|
11
|
+
*
|
|
12
|
+
* @param props - The input parameters for the calculation.
|
|
13
|
+
* @param props.cashPrice - The total cash price of the product or service.
|
|
14
|
+
* @param props.numberInstallments - The number of installments for the payment plan.
|
|
15
|
+
* @param props.fees - The interest rate per installment (default is 0.0349).
|
|
16
|
+
*
|
|
17
|
+
* @returns An object containing:
|
|
18
|
+
* - `totalPrice`: The total price to be paid, rounded to two decimal places.
|
|
19
|
+
* - `installmentPrice`: The price of each installment, rounded to two decimal places.
|
|
20
|
+
*
|
|
21
|
+
* @example
|
|
22
|
+
* ```typescript
|
|
23
|
+
* const result = calculateCardInstallment({
|
|
24
|
+
* cashPrice: 1000,
|
|
25
|
+
* numberInstallments: 12,
|
|
26
|
+
* fees: 0.02,
|
|
27
|
+
* });
|
|
28
|
+
* console.log(result);
|
|
29
|
+
* // Output: { totalPrice: 1124.62, installmentPrice: 93.72 }
|
|
30
|
+
* ```
|
|
31
|
+
*/
|
|
5
32
|
|
|
6
|
-
|
|
7
|
-
|
|
33
|
+
const calculateCardInstallment: CalculateCardInstallmentFunction = (props) => {
|
|
34
|
+
const { cashPrice, numberInstallments, fees = 0.0349 } = props;
|
|
8
35
|
|
|
9
|
-
|
|
10
|
-
|
|
36
|
+
if (fees === 0 || numberInstallments === 1) {
|
|
37
|
+
return {
|
|
38
|
+
totalPrice: cashPrice,
|
|
39
|
+
installmentPrice: cashPrice / numberInstallments,
|
|
40
|
+
};
|
|
41
|
+
}
|
|
11
42
|
|
|
12
|
-
|
|
13
|
-
|
|
43
|
+
if (numberInstallments <= 0) {
|
|
44
|
+
throw new Error("Number of installments must be greater than 0");
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
if (fees < 0) {
|
|
48
|
+
throw new Error("Fees must be greater than or equal to 0");
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
let installmentPrice = 0;
|
|
52
|
+
let totalPrice = 0;
|
|
53
|
+
|
|
54
|
+
let numerator = Math.pow(1 + fees, numberInstallments) * fees;
|
|
55
|
+
let denominator = Math.pow(1 + fees, numberInstallments) - 1;
|
|
56
|
+
|
|
57
|
+
installmentPrice = cashPrice * (numerator / denominator);
|
|
58
|
+
totalPrice = numberInstallments * installmentPrice;
|
|
14
59
|
|
|
15
60
|
return {
|
|
16
|
-
|
|
17
|
-
|
|
61
|
+
totalPrice: +totalPrice.toFixed(2),
|
|
62
|
+
installmentPrice: +installmentPrice.toFixed(2),
|
|
18
63
|
};
|
|
19
|
-
}
|
|
64
|
+
};
|
|
20
65
|
|
|
21
66
|
export { calculateCardInstallment };
|