@elyukai/utils 0.1.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.
Files changed (67) hide show
  1. package/AUTHORS +1 -0
  2. package/CHANGELOG.md +46 -0
  3. package/LICENSE +373 -0
  4. package/README.md +1 -0
  5. package/dist/array/filters.d.ts +14 -0
  6. package/dist/array/filters.js +24 -0
  7. package/dist/array/generators.d.ts +9 -0
  8. package/dist/array/generators.js +13 -0
  9. package/dist/array/groups.d.ts +24 -0
  10. package/dist/array/groups.js +45 -0
  11. package/dist/array/modify.d.ts +21 -0
  12. package/dist/array/modify.js +57 -0
  13. package/dist/array/nonEmpty.d.ts +23 -0
  14. package/dist/array/nonEmpty.js +15 -0
  15. package/dist/array/reductions.d.ts +39 -0
  16. package/dist/array/reductions.js +58 -0
  17. package/dist/array/sets.d.ts +17 -0
  18. package/dist/array/sets.js +19 -0
  19. package/dist/array.d.ts +4 -0
  20. package/dist/array.js +5 -0
  21. package/dist/async.d.ts +11 -0
  22. package/dist/async.js +11 -0
  23. package/dist/classList.d.ts +5 -0
  24. package/dist/classList.js +17 -0
  25. package/dist/compare.d.ts +44 -0
  26. package/dist/compare.js +73 -0
  27. package/dist/date.d.ts +5 -0
  28. package/dist/date.js +5 -0
  29. package/dist/dictionary/native.d.ts +116 -0
  30. package/dist/dictionary/native.js +142 -0
  31. package/dist/dictionary.d.ts +115 -0
  32. package/dist/dictionary.js +178 -0
  33. package/dist/equality.d.ts +44 -0
  34. package/dist/equality.js +53 -0
  35. package/dist/function.d.ts +48 -0
  36. package/dist/function.js +52 -0
  37. package/dist/lazy.d.ts +16 -0
  38. package/dist/lazy.js +32 -0
  39. package/dist/math.d.ts +47 -0
  40. package/dist/math.js +56 -0
  41. package/dist/maybe.d.ts +51 -0
  42. package/dist/maybe.js +36 -0
  43. package/dist/nullable.d.ts +50 -0
  44. package/dist/nullable.js +35 -0
  45. package/dist/number.d.ts +16 -0
  46. package/dist/number.js +16 -0
  47. package/dist/object.d.ts +40 -0
  48. package/dist/object.js +58 -0
  49. package/dist/ordering.d.ts +30 -0
  50. package/dist/ordering.js +46 -0
  51. package/dist/range.d.ts +37 -0
  52. package/dist/range.js +41 -0
  53. package/dist/regex.d.ts +28 -0
  54. package/dist/regex.js +35 -0
  55. package/dist/result.d.ts +54 -0
  56. package/dist/result.js +45 -0
  57. package/dist/roman.d.ts +4 -0
  58. package/dist/roman.js +47 -0
  59. package/dist/string/number.d.ts +31 -0
  60. package/dist/string/number.js +40 -0
  61. package/dist/string/regex.d.ts +28 -0
  62. package/dist/string/regex.js +38 -0
  63. package/dist/string.d.ts +32 -0
  64. package/dist/string.js +96 -0
  65. package/dist/typeSafety.d.ts +38 -0
  66. package/dist/typeSafety.js +33 -0
  67. package/package.json +46 -0
package/dist/roman.js ADDED
@@ -0,0 +1,47 @@
1
+ import { minus } from "./string/number.js";
2
+ const signPairs = [
3
+ ["I", "V"],
4
+ ["X", "L"],
5
+ ["C", "D"],
6
+ ["M", "ↁ"],
7
+ ];
8
+ const romanizeNatural = (num) => num
9
+ .toString(10)
10
+ .split("")
11
+ .reverse()
12
+ .map((digit, index) => {
13
+ const pair = signPairs[index];
14
+ if (pair === undefined) {
15
+ return "?";
16
+ }
17
+ const value = parseInt(digit, 10);
18
+ const [one, five] = pair;
19
+ if (value <= 3) {
20
+ return one.repeat(value);
21
+ }
22
+ else if (value === 4) {
23
+ return one + five;
24
+ }
25
+ else if (value <= 8) {
26
+ return five + one.repeat(value - 5);
27
+ }
28
+ else {
29
+ return one + (signPairs[index + 1]?.[0] ?? "?");
30
+ }
31
+ })
32
+ .reverse()
33
+ .join("");
34
+ /**
35
+ * Converts a number to a roman numeral.
36
+ */
37
+ export const romanize = (num) => {
38
+ if (num === 0) {
39
+ return "0";
40
+ }
41
+ else if (num < 0) {
42
+ return minus + romanizeNatural(-num);
43
+ }
44
+ else {
45
+ return romanizeNatural(num);
46
+ }
47
+ };
@@ -0,0 +1,31 @@
1
+ /**
2
+ * The minus sign.
3
+ */
4
+ export declare const minus = "\u2212";
5
+ /**
6
+ * The plus/minus sign.
7
+ */
8
+ export declare const plusMinus = "\u00B1";
9
+ /**
10
+ * Forces signing on the given number, returning `undefined` on zero.
11
+ */
12
+ export declare const signIgnoreZero: (x: number) => string | undefined;
13
+ /**
14
+ * Forces signing on the given number.
15
+ */
16
+ export declare const sign: (x: number) => string;
17
+ /**
18
+ * Returns the sign of the given number. Returns `undefined` if the number is
19
+ * zero.
20
+ */
21
+ export declare const signStr: (x: number) => string | undefined;
22
+ /**
23
+ * Converts a string to an integer. If the string is not a valid integer, it
24
+ * returns `undefined`.
25
+ */
26
+ export declare const parseInt: (str: string) => number | undefined;
27
+ /**
28
+ * Converts a string to a natural number. If the string is not a valid natural
29
+ * number, it returns `undefined`.
30
+ */
31
+ export declare const parseNat: (str: string) => number | undefined;
@@ -0,0 +1,40 @@
1
+ import { isInteger, isNaturalNumber } from "./regex.js";
2
+ /**
3
+ * The minus sign.
4
+ */
5
+ export const minus = "−";
6
+ /**
7
+ * The plus/minus sign.
8
+ */
9
+ export const plusMinus = "\xB1";
10
+ /**
11
+ * Forces signing on the given number, returning `undefined` on zero.
12
+ */
13
+ export const signIgnoreZero = (x) => x > 0
14
+ ? `+${x.toString()}`
15
+ : x < 0
16
+ ? `${minus}\u2060${Math.abs(x).toString()}`
17
+ : undefined;
18
+ /**
19
+ * Forces signing on the given number.
20
+ */
21
+ export const sign = (x) => x > 0
22
+ ? `+${x.toString()}`
23
+ : x < 0
24
+ ? `${minus}\u2060${Math.abs(x).toString()}`
25
+ : "0";
26
+ /**
27
+ * Returns the sign of the given number. Returns `undefined` if the number is
28
+ * zero.
29
+ */
30
+ export const signStr = (x) => x > 0 ? "+" : x < 0 ? minus : undefined;
31
+ /**
32
+ * Converts a string to an integer. If the string is not a valid integer, it
33
+ * returns `undefined`.
34
+ */
35
+ export const parseInt = (str) => str.length > 0 && isInteger(str) ? Number.parseInt(str, 10) : undefined;
36
+ /**
37
+ * Converts a string to a natural number. If the string is not a valid natural
38
+ * number, it returns `undefined`.
39
+ */
40
+ export const parseNat = (str) => str.length > 0 && isNaturalNumber(str) ? Number.parseInt(str, 10) : undefined;
@@ -0,0 +1,28 @@
1
+ /**
2
+ * Checks if the provided string is a string representation of a natural number.
3
+ * @param test The string to test.
4
+ */
5
+ export declare const isNaturalNumber: (test: string) => boolean;
6
+ /**
7
+ * Checks if the provided string is a string representation of an integer.
8
+ * @param test The string to test.
9
+ */
10
+ export declare const isInteger: (test: string) => boolean;
11
+ /**
12
+ * Checks if the provided string is a string representation of a floating-point
13
+ * number. Both `.` and `,` are accepted as decimal separators.
14
+ * @param test The string to test.
15
+ */
16
+ export declare const isFloat: (test: string) => boolean;
17
+ /**
18
+ * Checks if the provided string either is an empty string or passes the given
19
+ * test function.
20
+ * @param check The test function to apply if the string is not empty.
21
+ * @param test The string to test.
22
+ */
23
+ export declare const isEmptyOr: (check: (test: string) => boolean, test: string) => boolean;
24
+ /**
25
+ * Checks if the provided string is a valid URL.
26
+ * @param test The string to test.
27
+ */
28
+ export declare const isUrl: (test: string) => boolean;
@@ -0,0 +1,38 @@
1
+ const naturalNumberPattern = /^(?:0|[1-9][0-9]*)$/u;
2
+ const integerPattern = /^(?:0|-?[1-9][0-9]*)$/u;
3
+ const floatPattern = /^(?:(?:0|-?[1-9][0-9]*)(?:[.,][0-9]+)?)$/u;
4
+ /**
5
+ * Checks if the provided string is a string representation of a natural number.
6
+ * @param test The string to test.
7
+ */
8
+ export const isNaturalNumber = (test) => naturalNumberPattern.test(test);
9
+ /**
10
+ * Checks if the provided string is a string representation of an integer.
11
+ * @param test The string to test.
12
+ */
13
+ export const isInteger = (test) => integerPattern.test(test);
14
+ /**
15
+ * Checks if the provided string is a string representation of a floating-point
16
+ * number. Both `.` and `,` are accepted as decimal separators.
17
+ * @param test The string to test.
18
+ */
19
+ export const isFloat = (test) => floatPattern.test(test);
20
+ /**
21
+ * Checks if the provided string either is an empty string or passes the given
22
+ * test function.
23
+ * @param check The test function to apply if the string is not empty.
24
+ * @param test The string to test.
25
+ */
26
+ export const isEmptyOr = (check, test) => test === "" || check(test);
27
+ /**
28
+ * Checks if the provided string is a valid URL.
29
+ * @param test The string to test.
30
+ */
31
+ export const isUrl = (test) => {
32
+ try {
33
+ return typeof new URL(test) === "object";
34
+ }
35
+ catch {
36
+ return false;
37
+ }
38
+ };
@@ -0,0 +1,32 @@
1
+ /**
2
+ * Checks if a value is a non-empty string.
3
+ */
4
+ export declare const isNonEmptyString: (value: string | null | undefined) => value is string;
5
+ /**
6
+ * Splits a string into its constituent parts based on casing and separators.
7
+ */
8
+ export declare const splitStringParts: (str: string) => string[];
9
+ /**
10
+ * Converts a string to PascalCase.
11
+ */
12
+ export declare const toPascalCase: (str: string) => string;
13
+ /**
14
+ * Converts a string to camelCase.
15
+ */
16
+ export declare const toCamelCase: (str: string) => string;
17
+ /**
18
+ * Converts a string to kebab-case.
19
+ */
20
+ export declare const toKebabCase: (str: string) => string;
21
+ /**
22
+ * Converts a string to snake_case.
23
+ */
24
+ export declare const toSnakeCase: (str: string) => string;
25
+ /**
26
+ * Converts a string to Title Case.
27
+ */
28
+ export declare const toTitleCase: (str: string) => string;
29
+ /**
30
+ * Finds the longest common prefix among the provided strings.
31
+ */
32
+ export declare const commonPrefix: (...strs: string[]) => string;
package/dist/string.js ADDED
@@ -0,0 +1,96 @@
1
+ /**
2
+ * Checks if a value is a non-empty string.
3
+ */
4
+ export const isNonEmptyString = (value) => typeof value === "string" && value.length > 0;
5
+ const letterOrDigit = /[a-zA-Z0-9]/;
6
+ const uppercase = /[A-Z]/;
7
+ const lowerCaseOrDigit = /[a-z0-9]/;
8
+ const separator = /[^a-z0-9]/;
9
+ const lastChar = (str) => str[str.length - 1];
10
+ const lastElement = (arr) => arr[arr.length - 1];
11
+ const isAllUppercase = (str) => str === str.toUpperCase();
12
+ /**
13
+ * Splits a string into its constituent parts based on casing and separators.
14
+ */
15
+ export const splitStringParts = (str) => [...new Intl.Segmenter().segment(str)].reduce((acc, segment, i, strArr) => {
16
+ const char = segment.segment;
17
+ if (acc.length === 0) {
18
+ return letterOrDigit.test(char) ? [char] : acc;
19
+ }
20
+ // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
21
+ const lastPart = lastElement(acc);
22
+ if (uppercase.test(char)) {
23
+ const lastCharOfLastPart = lastChar(lastPart);
24
+ const nextSegment = strArr[i + 1];
25
+ const nextChar = nextSegment?.segment;
26
+ if (lastCharOfLastPart === undefined ||
27
+ (uppercase.test(lastCharOfLastPart) &&
28
+ (nextChar === undefined || separator.test(nextChar)))) {
29
+ return [...acc.slice(0, -1), lastPart + char];
30
+ }
31
+ else {
32
+ return [...acc, char];
33
+ }
34
+ }
35
+ if (lowerCaseOrDigit.test(char)) {
36
+ return [...acc.slice(0, -1), lastPart + char];
37
+ }
38
+ if (lastPart === "") {
39
+ return acc;
40
+ }
41
+ else {
42
+ return [...acc, ""];
43
+ }
44
+ }, []);
45
+ /**
46
+ * Converts a string to PascalCase.
47
+ */
48
+ export const toPascalCase = (str) => splitStringParts(isAllUppercase(str) ? str.toLowerCase() : str)
49
+ .map((part) => isAllUppercase(part)
50
+ ? part
51
+ : part.charAt(0).toUpperCase() + part.slice(1).toLowerCase())
52
+ .join("");
53
+ /**
54
+ * Converts a string to camelCase.
55
+ */
56
+ export const toCamelCase = (str) => splitStringParts(isAllUppercase(str) ? str.toLowerCase() : str)
57
+ .map((part, i) => i === 0
58
+ ? part.toLowerCase()
59
+ : isAllUppercase(part)
60
+ ? part
61
+ : part.charAt(0).toUpperCase() + part.slice(1).toLowerCase())
62
+ .join("");
63
+ /**
64
+ * Converts a string to kebab-case.
65
+ */
66
+ export const toKebabCase = (str) => splitStringParts(str)
67
+ .map((part) => part.toLowerCase())
68
+ .join("-");
69
+ /**
70
+ * Converts a string to snake_case.
71
+ */
72
+ export const toSnakeCase = (str) => splitStringParts(str)
73
+ .map((part) => part.toLowerCase())
74
+ .join("_");
75
+ /**
76
+ * Converts a string to Title Case.
77
+ */
78
+ export const toTitleCase = (str) => splitStringParts(isAllUppercase(str) ? str.toLowerCase() : str)
79
+ .map((part) => isAllUppercase(part)
80
+ ? part
81
+ : part.charAt(0).toUpperCase() + part.slice(1).toLowerCase())
82
+ .join(" ");
83
+ /**
84
+ * Finds the longest common prefix among the provided strings.
85
+ */
86
+ export const commonPrefix = (...strs) => {
87
+ if (strs.length === 0) {
88
+ return "";
89
+ }
90
+ return strs.reduce((accPrefix, str) => {
91
+ const indexOfDifference = Array.from(accPrefix).findIndex((char, i) => str[i] !== char);
92
+ return indexOfDifference === -1
93
+ ? accPrefix
94
+ : accPrefix.slice(0, indexOfDifference);
95
+ });
96
+ };
@@ -0,0 +1,38 @@
1
+ /**
2
+ * This function is used to make sure that the `switch` is exhaustive. Place it
3
+ * in the `default` case of the `switch`.
4
+ *
5
+ * Optionally, you can pass a custom error message.
6
+ * @param _x - The value that is used in the `switch`.
7
+ * @param [msg] - A custom error message.
8
+ * @example
9
+ * const aorb = (x: "a" | "b") => {
10
+ * switch (x) {
11
+ * case "a": return 1
12
+ * case "b": return 2
13
+ * default: return assertExhaustive(x)
14
+ * }
15
+ * }
16
+ */
17
+ export declare function assertExhaustive(_x: never, msg?: string): never;
18
+ /**
19
+ * Tries to execute a function, returning a default value if an error is thrown.
20
+ * @param f The function to execute.
21
+ * @param defaultValue The default value to return if an error is thrown.
22
+ * @returns The result of the function if successful, or the default value.
23
+ */
24
+ export declare const trySafe: {
25
+ /**
26
+ * Tries to execute a function, returning `undefined` if an error is thrown.
27
+ * @param f The function to execute.
28
+ * @returns The result of the function if successful, or `undefined`.
29
+ */
30
+ <T>(f: () => T): T | undefined;
31
+ /**
32
+ * Tries to execute a function, returning a default value if an error is thrown.
33
+ * @param f The function to execute.
34
+ * @param defaultValue The default value to return if an error is thrown.
35
+ * @returns The result of the function if successful, or the default value.
36
+ */
37
+ <T>(f: () => T, defaultValue: T): T;
38
+ };
@@ -0,0 +1,33 @@
1
+ /**
2
+ * This function is used to make sure that the `switch` is exhaustive. Place it
3
+ * in the `default` case of the `switch`.
4
+ *
5
+ * Optionally, you can pass a custom error message.
6
+ * @param _x - The value that is used in the `switch`.
7
+ * @param [msg] - A custom error message.
8
+ * @example
9
+ * const aorb = (x: "a" | "b") => {
10
+ * switch (x) {
11
+ * case "a": return 1
12
+ * case "b": return 2
13
+ * default: return assertExhaustive(x)
14
+ * }
15
+ * }
16
+ */
17
+ export function assertExhaustive(_x, msg = "The switch is not exhaustive.") {
18
+ throw new Error(msg);
19
+ }
20
+ /**
21
+ * Tries to execute a function, returning a default value if an error is thrown.
22
+ * @param f The function to execute.
23
+ * @param defaultValue The default value to return if an error is thrown.
24
+ * @returns The result of the function if successful, or the default value.
25
+ */
26
+ export const trySafe = (f, defaultValue) => {
27
+ try {
28
+ return f();
29
+ }
30
+ catch {
31
+ return defaultValue;
32
+ }
33
+ };
package/package.json ADDED
@@ -0,0 +1,46 @@
1
+ {
2
+ "name": "@elyukai/utils",
3
+ "version": "0.1.2",
4
+ "description": "A set of JavaScript helper functions.",
5
+ "files": [
6
+ "dist",
7
+ "!dist/**/*.tsbuildinfo",
8
+ "AUTHORS",
9
+ "CHANGELOG.md"
10
+ ],
11
+ "exports": {
12
+ "./*": "./dist/*.js"
13
+ },
14
+ "scripts": {
15
+ "build": "tsc -b",
16
+ "watch": "tsc -b -w",
17
+ "test": "node --import tsx --test",
18
+ "lint": "eslint",
19
+ "format": "prettier \"{src,test}/**/*.{ts,tsx}\" --write",
20
+ "format:check": "prettier \"{src,test}/**/*.{ts,tsx}\" --check",
21
+ "release": "commit-and-tag-version",
22
+ "release:sign": "commit-and-tag-version --sign --signoff"
23
+ },
24
+ "repository": {
25
+ "type": "git",
26
+ "url": "git+https://github.com/elyukai/ts-utils.git"
27
+ },
28
+ "author": "Lukas Obermann",
29
+ "license": "MPL-2.0",
30
+ "bugs": {
31
+ "url": "https://github.com/elyukai/ts-utils/issues"
32
+ },
33
+ "homepage": "https://github.com/elyukai/ts-utils#readme",
34
+ "devDependencies": {
35
+ "@eslint/js": "^9.39.2",
36
+ "@types/node": "^25.0.10",
37
+ "commit-and-tag-version": "^12.6.1",
38
+ "eslint": "^9.39.2",
39
+ "glob": "^13.0.0",
40
+ "prettier": "^3.8.1",
41
+ "tsx": "^4.21.0",
42
+ "typescript": "^5.9.3",
43
+ "typescript-eslint": "^8.53.1"
44
+ },
45
+ "type": "module"
46
+ }