@ooneex/utils 0.0.5 → 0.0.6

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 (65) hide show
  1. package/dist/capitalizeWord.d.ts +2 -0
  2. package/dist/capitalizeWord.d.ts.map +1 -0
  3. package/dist/dataURLtoFile.d.ts +2 -0
  4. package/dist/dataURLtoFile.d.ts.map +1 -0
  5. package/dist/formatRelativeNumber.d.ts +5 -0
  6. package/dist/formatRelativeNumber.d.ts.map +1 -0
  7. package/dist/index.d.ts +16 -69
  8. package/dist/index.d.ts.map +1 -0
  9. package/dist/millisecondsToHMS.d.ts +2 -0
  10. package/dist/millisecondsToHMS.d.ts.map +1 -0
  11. package/dist/parseEnvVars.d.ts +2 -0
  12. package/dist/parseEnvVars.d.ts.map +1 -0
  13. package/dist/parseString.d.ts +2 -0
  14. package/dist/parseString.d.ts.map +1 -0
  15. package/dist/random.d.ts +6 -0
  16. package/dist/random.d.ts.map +1 -0
  17. package/dist/secondsToHMS.d.ts +2 -0
  18. package/dist/secondsToHMS.d.ts.map +1 -0
  19. package/dist/secondsToMS.d.ts +2 -0
  20. package/dist/secondsToMS.d.ts.map +1 -0
  21. package/dist/sleep.d.ts +2 -0
  22. package/dist/sleep.d.ts.map +1 -0
  23. package/dist/splitToWords.d.ts +2 -0
  24. package/dist/splitToWords.d.ts.map +1 -0
  25. package/dist/toCamelCase.d.ts +2 -0
  26. package/dist/toCamelCase.d.ts.map +1 -0
  27. package/dist/toKebabCase.d.ts +2 -0
  28. package/dist/toKebabCase.d.ts.map +1 -0
  29. package/dist/toPascalCase.d.ts +2 -0
  30. package/dist/toPascalCase.d.ts.map +1 -0
  31. package/dist/trim.d.ts +2 -0
  32. package/dist/trim.d.ts.map +1 -0
  33. package/package.json +12 -9
  34. package/src/capitalizeWord.ts +3 -0
  35. package/src/dataURLtoFile.ts +12 -0
  36. package/src/formatRelativeNumber.ts +7 -0
  37. package/src/index.ts +15 -0
  38. package/src/millisecondsToHMS.ts +16 -0
  39. package/src/parseEnvVars.ts +14 -0
  40. package/src/parseString.ts +47 -0
  41. package/src/random.ts +13 -0
  42. package/src/secondsToHMS.ts +16 -0
  43. package/src/secondsToMS.ts +5 -0
  44. package/src/sleep.ts +3 -0
  45. package/src/splitToWords.ts +14 -0
  46. package/src/toCamelCase.ts +8 -0
  47. package/src/toKebabCase.ts +6 -0
  48. package/src/toPascalCase.ts +7 -0
  49. package/src/trim.ts +8 -0
  50. package/tests/capitalizeWord.spec.ts +163 -0
  51. package/tests/dataURLtoFile.spec.ts +472 -0
  52. package/tests/formatRelativeNumber.spec.ts +303 -0
  53. package/tests/millisecondsToHMS.spec.ts +209 -0
  54. package/tests/parseEnvVars.spec.ts +468 -0
  55. package/tests/parseString.spec.ts +377 -0
  56. package/tests/random.spec.ts +422 -0
  57. package/tests/secondsToHMS.spec.ts +341 -0
  58. package/tests/secondsToMS.spec.ts +467 -0
  59. package/tests/splitToWords.spec.ts +359 -0
  60. package/tests/toCamelCase.spec.ts +526 -0
  61. package/tests/toKebabCase.spec.ts +664 -0
  62. package/tests/toPascalCase.spec.ts +721 -0
  63. package/tests/trim.spec.ts +486 -0
  64. package/tsconfig.build.json +14 -0
  65. package/tsconfig.json +11 -0
@@ -0,0 +1,2 @@
1
+ export declare const capitalizeWord: (word: string) => string;
2
+ //# sourceMappingURL=capitalizeWord.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"capitalizeWord.d.ts","sourceRoot":"","sources":["../src/capitalizeWord.ts"],"names":[],"mappings":"AAAA,eAAO,MAAM,cAAc,GAAI,MAAM,MAAM,KAAG,MAE7C,CAAC"}
@@ -0,0 +1,2 @@
1
+ export declare const dataURLtoFile: (dataurl: string, filename: string) => File;
2
+ //# sourceMappingURL=dataURLtoFile.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"dataURLtoFile.d.ts","sourceRoot":"","sources":["../src/dataURLtoFile.ts"],"names":[],"mappings":"AAAA,eAAO,MAAM,aAAa,GAAI,SAAS,MAAM,EAAE,UAAU,MAAM,SAW9D,CAAC"}
@@ -0,0 +1,5 @@
1
+ export declare const formatRelativeNumber: (num: number, config?: {
2
+ precision?: number;
3
+ lang?: string;
4
+ }) => string;
5
+ //# sourceMappingURL=formatRelativeNumber.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"formatRelativeNumber.d.ts","sourceRoot":"","sources":["../src/formatRelativeNumber.ts"],"names":[],"mappings":"AAAA,eAAO,MAAM,oBAAoB,GAAI,KAAK,MAAM,EAAE,SAAS;IAAE,SAAS,CAAC,EAAE,MAAM,CAAC;IAAC,IAAI,CAAC,EAAE,MAAM,CAAA;CAAE,KAAG,MAMlG,CAAC"}
package/dist/index.d.ts CHANGED
@@ -1,69 +1,16 @@
1
- declare module "capitalizeWord" {
2
- export const capitalizeWord: (word: string) => string;
3
- }
4
- declare module "dataURLtoFile" {
5
- export const dataURLtoFile: (dataurl: string, filename: string) => File;
6
- }
7
- declare module "formatRelativeNumber" {
8
- export const formatRelativeNumber: (num: number, config?: {
9
- precision?: number;
10
- lang?: string;
11
- }) => string;
12
- }
13
- declare module "millisecondsToHMS" {
14
- export const millisecondsToHMS: (ms: number) => string;
15
- }
16
- declare module "trim" {
17
- export const trim: (text: string, char?: string) => string;
18
- }
19
- declare module "parseString" {
20
- export const parseString: <T = unknown>(text: string) => T;
21
- }
22
- declare module "splitToWords" {
23
- export const splitToWords: (input: string) => RegExpMatchArray | [];
24
- }
25
- declare module "toCamelCase" {
26
- export const toCamelCase: (input: string) => string;
27
- }
28
- declare module "parseEnvVars" {
29
- export const parseEnvVars: <T = Record<string, unknown>>(envs: Record<string, unknown>) => T;
30
- }
31
- declare module "random" {
32
- export const random: {
33
- nanoid(size?: number): string;
34
- stringInt(size?: number): string;
35
- nanoidFactory(size?: number): (size?: number) => string;
36
- };
37
- }
38
- declare module "secondsToHMS" {
39
- export const secondsToHMS: (seconds: number) => string;
40
- }
41
- declare module "secondsToMS" {
42
- export const secondsToMS: (seconds: number) => string;
43
- }
44
- declare module "sleep" {
45
- export const sleep: (ms: number) => Promise<void>;
46
- }
47
- declare module "toKebabCase" {
48
- export const toKebabCase: (input: string) => string;
49
- }
50
- declare module "toPascalCase" {
51
- export const toPascalCase: (input: string) => string;
52
- }
53
- declare module "index" {
54
- export { capitalizeWord } from "capitalizeWord";
55
- export { dataURLtoFile } from "dataURLtoFile";
56
- export { formatRelativeNumber } from "formatRelativeNumber";
57
- export { millisecondsToHMS } from "millisecondsToHMS";
58
- export { parseEnvVars } from "parseEnvVars";
59
- export { parseString } from "parseString";
60
- export { random } from "random";
61
- export { secondsToHMS } from "secondsToHMS";
62
- export { secondsToMS } from "secondsToMS";
63
- export { sleep } from "sleep";
64
- export { splitToWords } from "splitToWords";
65
- export { toCamelCase } from "toCamelCase";
66
- export { toKebabCase } from "toKebabCase";
67
- export { toPascalCase } from "toPascalCase";
68
- export { trim } from "trim";
69
- }
1
+ export { capitalizeWord } from "./capitalizeWord";
2
+ export { dataURLtoFile } from "./dataURLtoFile";
3
+ export { formatRelativeNumber } from "./formatRelativeNumber";
4
+ export { millisecondsToHMS } from "./millisecondsToHMS";
5
+ export { parseEnvVars } from "./parseEnvVars";
6
+ export { parseString } from "./parseString";
7
+ export { random } from "./random";
8
+ export { secondsToHMS } from "./secondsToHMS";
9
+ export { secondsToMS } from "./secondsToMS";
10
+ export { sleep } from "./sleep";
11
+ export { splitToWords } from "./splitToWords";
12
+ export { toCamelCase } from "./toCamelCase";
13
+ export { toKebabCase } from "./toKebabCase";
14
+ export { toPascalCase } from "./toPascalCase";
15
+ export { trim } from "./trim";
16
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,EAAE,MAAM,kBAAkB,CAAC;AAClD,OAAO,EAAE,aAAa,EAAE,MAAM,iBAAiB,CAAC;AAChD,OAAO,EAAE,oBAAoB,EAAE,MAAM,wBAAwB,CAAC;AAC9D,OAAO,EAAE,iBAAiB,EAAE,MAAM,qBAAqB,CAAC;AACxD,OAAO,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAC;AAC9C,OAAO,EAAE,WAAW,EAAE,MAAM,eAAe,CAAC;AAC5C,OAAO,EAAE,MAAM,EAAE,MAAM,UAAU,CAAC;AAClC,OAAO,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAC;AAC9C,OAAO,EAAE,WAAW,EAAE,MAAM,eAAe,CAAC;AAC5C,OAAO,EAAE,KAAK,EAAE,MAAM,SAAS,CAAC;AAChC,OAAO,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAC;AAC9C,OAAO,EAAE,WAAW,EAAE,MAAM,eAAe,CAAC;AAC5C,OAAO,EAAE,WAAW,EAAE,MAAM,eAAe,CAAC;AAC5C,OAAO,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAC;AAC9C,OAAO,EAAE,IAAI,EAAE,MAAM,QAAQ,CAAC"}
@@ -0,0 +1,2 @@
1
+ export declare const millisecondsToHMS: (ms: number) => string;
2
+ //# sourceMappingURL=millisecondsToHMS.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"millisecondsToHMS.d.ts","sourceRoot":"","sources":["../src/millisecondsToHMS.ts"],"names":[],"mappings":"AAAA,eAAO,MAAM,iBAAiB,GAAI,IAAI,MAAM,KAAG,MAe9C,CAAC"}
@@ -0,0 +1,2 @@
1
+ export declare const parseEnvVars: <T = Record<string, unknown>>(envs: Record<string, unknown>) => T;
2
+ //# sourceMappingURL=parseEnvVars.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"parseEnvVars.d.ts","sourceRoot":"","sources":["../src/parseEnvVars.ts"],"names":[],"mappings":"AAGA,eAAO,MAAM,YAAY,GAAI,CAAC,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAAE,MAAM,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,KAAG,CAUzF,CAAC"}
@@ -0,0 +1,2 @@
1
+ export declare const parseString: <T = unknown>(text: string) => T;
2
+ //# sourceMappingURL=parseString.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"parseString.d.ts","sourceRoot":"","sources":["../src/parseString.ts"],"names":[],"mappings":"AAEA,eAAO,MAAM,WAAW,GAAI,CAAC,GAAG,OAAO,EAAE,MAAM,MAAM,KAAG,CA4CvD,CAAC"}
@@ -0,0 +1,6 @@
1
+ export declare const random: {
2
+ nanoid(size?: number): string;
3
+ stringInt(size?: number): string;
4
+ nanoidFactory(size?: number): (size?: number) => string;
5
+ };
6
+ //# sourceMappingURL=random.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"random.d.ts","sourceRoot":"","sources":["../src/random.ts"],"names":[],"mappings":"AAEA,eAAO,MAAM,MAAM;kBACH,MAAM,GAAG,MAAM;qBAGZ,MAAM,GAAG,MAAM;yBAGX,MAAM,GAAG,CAAC,IAAI,CAAC,EAAE,MAAM,KAAK,MAAM;CAGxD,CAAC"}
@@ -0,0 +1,2 @@
1
+ export declare const secondsToHMS: (seconds: number) => string;
2
+ //# sourceMappingURL=secondsToHMS.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"secondsToHMS.d.ts","sourceRoot":"","sources":["../src/secondsToHMS.ts"],"names":[],"mappings":"AAAA,eAAO,MAAM,YAAY,GAAI,SAAS,MAAM,KAAG,MAe9C,CAAC"}
@@ -0,0 +1,2 @@
1
+ export declare const secondsToMS: (seconds: number) => string;
2
+ //# sourceMappingURL=secondsToMS.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"secondsToMS.d.ts","sourceRoot":"","sources":["../src/secondsToMS.ts"],"names":[],"mappings":"AAAA,eAAO,MAAM,WAAW,GAAI,SAAS,MAAM,KAAG,MAI7C,CAAC"}
@@ -0,0 +1,2 @@
1
+ export declare const sleep: (ms: number) => Promise<void>;
2
+ //# sourceMappingURL=sleep.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"sleep.d.ts","sourceRoot":"","sources":["../src/sleep.ts"],"names":[],"mappings":"AAAA,eAAO,MAAM,KAAK,GAAI,IAAI,MAAM,KAAG,OAAO,CAAC,IAAI,CAE9C,CAAC"}
@@ -0,0 +1,2 @@
1
+ export declare const splitToWords: (input: string) => RegExpMatchArray | [];
2
+ //# sourceMappingURL=splitToWords.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"splitToWords.d.ts","sourceRoot":"","sources":["../src/splitToWords.ts"],"names":[],"mappings":"AAWA,eAAO,MAAM,YAAY,GAAI,OAAO,MAAM,0BAEzC,CAAC"}
@@ -0,0 +1,2 @@
1
+ export declare const toCamelCase: (input: string) => string;
2
+ //# sourceMappingURL=toCamelCase.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"toCamelCase.d.ts","sourceRoot":"","sources":["../src/toCamelCase.ts"],"names":[],"mappings":"AAGA,eAAO,MAAM,WAAW,GAAI,OAAO,MAAM,KAAG,MAI3C,CAAC"}
@@ -0,0 +1,2 @@
1
+ export declare const toKebabCase: (input: string) => string;
2
+ //# sourceMappingURL=toKebabCase.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"toKebabCase.d.ts","sourceRoot":"","sources":["../src/toKebabCase.ts"],"names":[],"mappings":"AAEA,eAAO,MAAM,WAAW,GAAI,OAAO,MAAM,KAAG,MAG3C,CAAC"}
@@ -0,0 +1,2 @@
1
+ export declare const toPascalCase: (input: string) => string;
2
+ //# sourceMappingURL=toPascalCase.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"toPascalCase.d.ts","sourceRoot":"","sources":["../src/toPascalCase.ts"],"names":[],"mappings":"AAGA,eAAO,MAAM,YAAY,GAAI,OAAO,MAAM,KAAG,MAG5C,CAAC"}
package/dist/trim.d.ts ADDED
@@ -0,0 +1,2 @@
1
+ export declare const trim: (text: string, char?: string) => string;
2
+ //# sourceMappingURL=trim.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"trim.d.ts","sourceRoot":"","sources":["../src/trim.ts"],"names":[],"mappings":"AAAA,eAAO,MAAM,IAAI,GAAI,MAAM,MAAM,EAAE,aAAU,KAAG,MAO/C,CAAC"}
package/package.json CHANGED
@@ -1,13 +1,20 @@
1
1
  {
2
2
  "name": "@ooneex/utils",
3
- "version": "0.0.5",
3
+ "version": "0.0.6",
4
4
  "description": "",
5
- "main": "dist/index.js",
6
- "types": "dist/index.d.ts",
7
5
  "type": "module",
6
+ "exports": {
7
+ ".": {
8
+ "types": "./dist/index.d.ts",
9
+ "import": "./dist/index.js"
10
+ }
11
+ },
12
+ "types": "./dist/index.d.ts",
13
+ "main": "./dist/index.js",
14
+ "module": "./dist/index.js",
8
15
  "license": "MIT",
9
16
  "scripts": {
10
- "compile": "tsc ./src/index.ts --declaration --emitDeclarationOnly --target ES2022 --moduleResolution bundler --outfile dist/index.d.ts",
17
+ "compile": "tsc -p tsconfig.build.json",
11
18
  "build": "rm -rf dist && bun run compile && bun build ./src/index.ts --outdir ./dist --target browser --format esm --packages external --minify",
12
19
  "publish": "bun run build && bun publish --access public"
13
20
  },
@@ -15,9 +22,5 @@
15
22
  "peerDependencies": {},
16
23
  "dependencies": {
17
24
  "nanoid": "^5.1.6"
18
- },
19
- "files": [
20
- "dist/**/*.js",
21
- "dist/**/*.d.ts"
22
- ]
25
+ }
23
26
  }
@@ -0,0 +1,3 @@
1
+ export const capitalizeWord = (word: string): string => {
2
+ return word ? word[0]?.toUpperCase() + word.slice(1).toLowerCase() : word;
3
+ };
@@ -0,0 +1,12 @@
1
+ export const dataURLtoFile = (dataurl: string, filename: string) => {
2
+ const arr = dataurl.split(",");
3
+ const mimeMatch = arr[0]?.match(/:(.*?);/);
4
+ const mime = mimeMatch ? mimeMatch[1] : "";
5
+ const bstr = atob(arr[1] as string);
6
+ let n = bstr.length;
7
+ const u8arr = new Uint8Array(n);
8
+ while (n--) {
9
+ u8arr[n] = bstr.charCodeAt(n);
10
+ }
11
+ return new File([u8arr], filename, { type: mime });
12
+ };
@@ -0,0 +1,7 @@
1
+ export const formatRelativeNumber = (num: number, config?: { precision?: number; lang?: string }): string => {
2
+ return new Intl.NumberFormat(config?.lang ?? "en-GB", {
3
+ notation: "compact",
4
+ compactDisplay: "short",
5
+ maximumFractionDigits: config?.precision ?? 1,
6
+ }).format(num);
7
+ };
package/src/index.ts ADDED
@@ -0,0 +1,15 @@
1
+ export { capitalizeWord } from "./capitalizeWord";
2
+ export { dataURLtoFile } from "./dataURLtoFile";
3
+ export { formatRelativeNumber } from "./formatRelativeNumber";
4
+ export { millisecondsToHMS } from "./millisecondsToHMS";
5
+ export { parseEnvVars } from "./parseEnvVars";
6
+ export { parseString } from "./parseString";
7
+ export { random } from "./random";
8
+ export { secondsToHMS } from "./secondsToHMS";
9
+ export { secondsToMS } from "./secondsToMS";
10
+ export { sleep } from "./sleep";
11
+ export { splitToWords } from "./splitToWords";
12
+ export { toCamelCase } from "./toCamelCase";
13
+ export { toKebabCase } from "./toKebabCase";
14
+ export { toPascalCase } from "./toPascalCase";
15
+ export { trim } from "./trim";
@@ -0,0 +1,16 @@
1
+ export const millisecondsToHMS = (ms: number): string => {
2
+ const totalSeconds = Math.floor(ms / 1000);
3
+ const hours = Math.floor(totalSeconds / 3600);
4
+ const minutes = Math.floor((totalSeconds % 3600) / 60);
5
+ const seconds = totalSeconds % 60;
6
+
7
+ if (hours > 0) {
8
+ return `${hours}:${minutes.toString().padStart(2, "0")}:${seconds.toString().padStart(2, "0")}`;
9
+ }
10
+
11
+ if (minutes > 0) {
12
+ return `${minutes}:${seconds.toString().padStart(2, "0")}`;
13
+ }
14
+
15
+ return seconds.toString();
16
+ };
@@ -0,0 +1,14 @@
1
+ import { parseString } from "./parseString";
2
+ import { toCamelCase } from "./toCamelCase";
3
+
4
+ export const parseEnvVars = <T = Record<string, unknown>>(envs: Record<string, unknown>): T => {
5
+ const vars: Record<string, unknown> = {};
6
+
7
+ for (const key in envs) {
8
+ const k = toCamelCase(key);
9
+ const value = parseString(envs[key] as string) as unknown;
10
+ vars[k] = value;
11
+ }
12
+
13
+ return vars as T;
14
+ };
@@ -0,0 +1,47 @@
1
+ import { trim } from "./trim";
2
+
3
+ export const parseString = <T = unknown>(text: string): T => {
4
+ if (/^[0-9]+$/.test(text)) {
5
+ return Number.parseInt(text, 10) as T;
6
+ }
7
+
8
+ if (/^[0-9]+[.][0-9]+$/.test(text)) {
9
+ return Number.parseFloat(text) as T;
10
+ }
11
+
12
+ if (/^true$/i.test(text)) {
13
+ return true as T;
14
+ }
15
+
16
+ if (/^false$/i.test(text)) {
17
+ return false as T;
18
+ }
19
+
20
+ if (/^null$/i.test(text)) {
21
+ return null as T;
22
+ }
23
+
24
+ if (/^\[/.test(text) && /]$/.test(text)) {
25
+ const trimmedText = trim(text, "\\[|\\]");
26
+
27
+ let values: unknown[] = trimmedText.split(/, */);
28
+
29
+ values = values.map((value) => {
30
+ return parseString(value as string);
31
+ });
32
+
33
+ return values as T;
34
+ }
35
+
36
+ try {
37
+ const result = JSON.parse(text);
38
+
39
+ if (result === Number.POSITIVE_INFINITY || result === Number.NEGATIVE_INFINITY) {
40
+ return text as T;
41
+ }
42
+
43
+ return result;
44
+ } catch {
45
+ return text as T;
46
+ }
47
+ };
package/src/random.ts ADDED
@@ -0,0 +1,13 @@
1
+ import { customAlphabet } from "nanoid";
2
+
3
+ export const random = {
4
+ nanoid(size?: number): string {
5
+ return customAlphabet("1234567890abcdef", size ?? 10)();
6
+ },
7
+ stringInt(size?: number): string {
8
+ return customAlphabet("1234567890", size ?? 10)();
9
+ },
10
+ nanoidFactory(size?: number): (size?: number) => string {
11
+ return customAlphabet("1234567890abcdef", size ?? 10);
12
+ },
13
+ };
@@ -0,0 +1,16 @@
1
+ export const secondsToHMS = (seconds: number): string => {
2
+ const totalSeconds = Math.floor(seconds);
3
+ const hours = Math.floor(totalSeconds / 3600);
4
+ const minutes = Math.floor((totalSeconds % 3600) / 60);
5
+ const remainingSeconds = totalSeconds % 60;
6
+
7
+ if (hours > 0) {
8
+ return `${hours}:${minutes.toString().padStart(2, "0")}:${remainingSeconds.toString().padStart(2, "0")}`;
9
+ }
10
+
11
+ if (minutes > 0) {
12
+ return `${minutes}:${remainingSeconds.toString().padStart(2, "0")}`;
13
+ }
14
+
15
+ return remainingSeconds.toString();
16
+ };
@@ -0,0 +1,5 @@
1
+ export const secondsToMS = (seconds: number): string => {
2
+ const minutes = Math.floor(seconds / 60);
3
+ const remainingSeconds = seconds % 60;
4
+ return `${minutes}:${remainingSeconds.toString().padStart(2, "0")}`;
5
+ };
package/src/sleep.ts ADDED
@@ -0,0 +1,3 @@
1
+ export const sleep = (ms: number): Promise<void> => {
2
+ return new Promise((resolve) => setTimeout(resolve, ms));
3
+ };
@@ -0,0 +1,14 @@
1
+ const CAPITALIZED_WORD_REGEXP = /\p{Lu}\p{Ll}+/u; // e.g. Apple
2
+ const ACRONYM_REGEXP = /\p{Lu}+(?=(\p{Lu}\p{Ll})|\P{L}|\b)/u; // e.g. ID, URL, handles an acronym followed by a capitalized word e.g. HTMLElement
3
+ const LOWERCASED_WORD_REGEXP = /(\p{Ll}+)/u; // e.g. apple
4
+ const ANY_LETTERS = /\p{L}+/u; // will match any sequence of letters, including in languages without a concept of upper/lower case
5
+ const DIGITS_REGEXP = /\p{N}+/u; // e.g. 123
6
+
7
+ const WORD_OR_NUMBER_REGEXP = new RegExp(
8
+ `${CAPITALIZED_WORD_REGEXP.source}|${ACRONYM_REGEXP.source}|${LOWERCASED_WORD_REGEXP.source}|${ANY_LETTERS.source}|${DIGITS_REGEXP.source}`,
9
+ "gu",
10
+ );
11
+
12
+ export const splitToWords = (input: string) => {
13
+ return input.match(WORD_OR_NUMBER_REGEXP) ?? [];
14
+ };
@@ -0,0 +1,8 @@
1
+ import { capitalizeWord } from "./capitalizeWord";
2
+ import { splitToWords } from "./splitToWords";
3
+
4
+ export const toCamelCase = (input: string): string => {
5
+ input = input.trim();
6
+ const [first = "", ...rest] = splitToWords(input);
7
+ return [first.toLowerCase(), ...rest.map(capitalizeWord)].join("");
8
+ };
@@ -0,0 +1,6 @@
1
+ import { splitToWords } from "./splitToWords";
2
+
3
+ export const toKebabCase = (input: string): string => {
4
+ input = input.trim();
5
+ return splitToWords(input).join("-").toLowerCase();
6
+ };
@@ -0,0 +1,7 @@
1
+ import { capitalizeWord } from "./capitalizeWord";
2
+ import { splitToWords } from "./splitToWords";
3
+
4
+ export const toPascalCase = (input: string): string => {
5
+ input = input.trim();
6
+ return splitToWords(input).map(capitalizeWord).join("");
7
+ };
package/src/trim.ts ADDED
@@ -0,0 +1,8 @@
1
+ export const trim = (text: string, char = " "): string => {
2
+ if ([".", "[", "]", "(", ")", "+", "*", "^", "$", "?", "/", "\\"].includes(char)) {
3
+ char = `\\${char}`;
4
+ }
5
+
6
+ const reg = new RegExp(`^${char}+|${char}+$`, "g");
7
+ return text.replace(reg, "");
8
+ };
@@ -0,0 +1,163 @@
1
+ import { describe, expect, test } from "bun:test";
2
+ import { capitalizeWord } from "@/index";
3
+
4
+ describe("capitalizeWord", () => {
5
+ describe("basic functionality", () => {
6
+ test("should capitalize first letter of lowercase word", () => {
7
+ expect(capitalizeWord("hello")).toBe("Hello");
8
+ });
9
+
10
+ test("should capitalize first letter and lowercase the rest", () => {
11
+ expect(capitalizeWord("hELLO")).toBe("Hello");
12
+ });
13
+
14
+ test("should handle single character", () => {
15
+ expect(capitalizeWord("a")).toBe("A");
16
+ });
17
+
18
+ test("should handle uppercase single character", () => {
19
+ expect(capitalizeWord("A")).toBe("A");
20
+ });
21
+
22
+ test("should handle already capitalized word", () => {
23
+ expect(capitalizeWord("Hello")).toBe("Hello");
24
+ });
25
+
26
+ test("should handle mixed case word", () => {
27
+ expect(capitalizeWord("hElLo")).toBe("Hello");
28
+ });
29
+ });
30
+
31
+ describe("edge cases", () => {
32
+ test("should return empty string when input is empty", () => {
33
+ expect(capitalizeWord("")).toBe("");
34
+ });
35
+
36
+ test("should handle words with numbers", () => {
37
+ expect(capitalizeWord("hello123")).toBe("Hello123");
38
+ });
39
+
40
+ test("should handle words starting with numbers", () => {
41
+ expect(capitalizeWord("123hello")).toBe("123hello");
42
+ });
43
+
44
+ test("should handle special characters", () => {
45
+ expect(capitalizeWord("!hello")).toBe("!hello");
46
+ });
47
+
48
+ test("should handle words with special characters", () => {
49
+ expect(capitalizeWord("hello-world")).toBe("Hello-world");
50
+ });
51
+
52
+ test("should handle accented characters", () => {
53
+ expect(capitalizeWord("école")).toBe("École");
54
+ });
55
+
56
+ test("should handle non-latin characters", () => {
57
+ expect(capitalizeWord("привет")).toBe("Привет");
58
+ });
59
+ });
60
+
61
+ describe("whitespace handling", () => {
62
+ test("should handle words with leading spaces", () => {
63
+ expect(capitalizeWord(" hello")).toBe(" hello");
64
+ });
65
+
66
+ test("should handle words with trailing spaces", () => {
67
+ expect(capitalizeWord("hello ")).toBe("Hello ");
68
+ });
69
+
70
+ test("should handle single space", () => {
71
+ expect(capitalizeWord(" ")).toBe(" ");
72
+ });
73
+
74
+ test("should handle multiple spaces", () => {
75
+ expect(capitalizeWord(" ")).toBe(" ");
76
+ });
77
+
78
+ test("should handle tab character", () => {
79
+ expect(capitalizeWord("\t")).toBe("\t");
80
+ });
81
+
82
+ test("should handle newline character", () => {
83
+ expect(capitalizeWord("\n")).toBe("\n");
84
+ });
85
+ });
86
+
87
+ describe("parametrized tests", () => {
88
+ test.each([
89
+ ["word", "Word"],
90
+ ["WORD", "Word"],
91
+ ["wORD", "Word"],
92
+ ["test", "Test"],
93
+ ["javascript", "Javascript"],
94
+ ["typescript", "Typescript"],
95
+ ["react", "React"],
96
+ ])("capitalizeWord(%s) should return %s", (input, expected) => {
97
+ expect(capitalizeWord(input)).toBe(expected);
98
+ });
99
+ });
100
+
101
+ describe("type safety", () => {
102
+ test("should handle very long strings", () => {
103
+ const longString = "a".repeat(1000);
104
+ const result = capitalizeWord(longString);
105
+ expect(result).toHaveLength(1000);
106
+ expect(result[0]).toBe("A");
107
+ expect(result.slice(1)).toBe("a".repeat(999));
108
+ });
109
+
110
+ test("should handle unicode characters", () => {
111
+ expect(capitalizeWord("émile")).toBe("Émile");
112
+ expect(capitalizeWord("ñoño")).toBe("Ñoño");
113
+ expect(capitalizeWord("café")).toBe("Café");
114
+ });
115
+
116
+ test("should handle emoji", () => {
117
+ expect(capitalizeWord("😀hello")).toBe("😀hello");
118
+ expect(capitalizeWord("hello😀")).toBe("Hello😀");
119
+ });
120
+ });
121
+
122
+ describe("function behavior", () => {
123
+ test("should not mutate original string", () => {
124
+ const original = "hello";
125
+ const result = capitalizeWord(original);
126
+ expect(original).toBe("hello");
127
+ expect(result).toBe("Hello");
128
+ });
129
+
130
+ test("should return string type", () => {
131
+ const result = capitalizeWord("test");
132
+ expect(typeof result).toBe("string");
133
+ });
134
+
135
+ test("should handle consecutive calls consistently", () => {
136
+ const word = "hello";
137
+ const result1 = capitalizeWord(word);
138
+ const result2 = capitalizeWord(word);
139
+ expect(result1).toBe(result2);
140
+ expect(result1).toBe("Hello");
141
+ });
142
+ });
143
+
144
+ describe("real world examples", () => {
145
+ test("should capitalize common names", () => {
146
+ expect(capitalizeWord("john")).toBe("John");
147
+ expect(capitalizeWord("mary")).toBe("Mary");
148
+ expect(capitalizeWord("david")).toBe("David");
149
+ });
150
+
151
+ test("should handle programming terms", () => {
152
+ expect(capitalizeWord("function")).toBe("Function");
153
+ expect(capitalizeWord("variable")).toBe("Variable");
154
+ expect(capitalizeWord("method")).toBe("Method");
155
+ });
156
+
157
+ test("should handle common words", () => {
158
+ expect(capitalizeWord("the")).toBe("The");
159
+ expect(capitalizeWord("and")).toBe("And");
160
+ expect(capitalizeWord("but")).toBe("But");
161
+ });
162
+ });
163
+ });