@catbee/utils 0.0.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 +201 -0
- package/README.md +295 -0
- package/build/esm/config.d.ts +22 -0
- package/build/esm/config.js +21 -0
- package/build/esm/config.js.map +1 -0
- package/build/esm/index.d.ts +19 -0
- package/build/esm/index.js +19 -0
- package/build/esm/index.js.map +1 -0
- package/build/esm/types/api-response.d.ts +44 -0
- package/build/esm/types/api-response.js +2 -0
- package/build/esm/types/api-response.js.map +1 -0
- package/build/esm/utils/array.utils.d.ts +105 -0
- package/build/esm/utils/array.utils.js +232 -0
- package/build/esm/utils/array.utils.js.map +1 -0
- package/build/esm/utils/async.utils.d.ts +119 -0
- package/build/esm/utils/async.utils.js +474 -0
- package/build/esm/utils/async.utils.js.map +1 -0
- package/build/esm/utils/cache.utils.d.ts +90 -0
- package/build/esm/utils/cache.utils.js +294 -0
- package/build/esm/utils/cache.utils.js.map +1 -0
- package/build/esm/utils/context-store.utils.d.ts +85 -0
- package/build/esm/utils/context-store.utils.js +99 -0
- package/build/esm/utils/context-store.utils.js.map +1 -0
- package/build/esm/utils/crypto.utils.d.ts +58 -0
- package/build/esm/utils/crypto.utils.js +76 -0
- package/build/esm/utils/crypto.utils.js.map +1 -0
- package/build/esm/utils/dir.utils.d.ts +75 -0
- package/build/esm/utils/dir.utils.js +400 -0
- package/build/esm/utils/dir.utils.js.map +1 -0
- package/build/esm/utils/env.utils.d.ts +131 -0
- package/build/esm/utils/env.utils.js +218 -0
- package/build/esm/utils/env.utils.js.map +1 -0
- package/build/esm/utils/exception.utils.d.ts +114 -0
- package/build/esm/utils/exception.utils.js +217 -0
- package/build/esm/utils/exception.utils.js.map +1 -0
- package/build/esm/utils/fs.utils.d.ts +32 -0
- package/build/esm/utils/fs.utils.js +140 -0
- package/build/esm/utils/fs.utils.js.map +1 -0
- package/build/esm/utils/http-status-codes.d.ts +357 -0
- package/build/esm/utils/http-status-codes.js +358 -0
- package/build/esm/utils/http-status-codes.js.map +1 -0
- package/build/esm/utils/id.utils.d.ts +35 -0
- package/build/esm/utils/id.utils.js +55 -0
- package/build/esm/utils/id.utils.js.map +1 -0
- package/build/esm/utils/logger.utils.d.ts +15 -0
- package/build/esm/utils/logger.utils.js +59 -0
- package/build/esm/utils/logger.utils.js.map +1 -0
- package/build/esm/utils/obj.utils.d.ts +55 -0
- package/build/esm/utils/obj.utils.js +121 -0
- package/build/esm/utils/obj.utils.js.map +1 -0
- package/build/esm/utils/response.utils.d.ts +48 -0
- package/build/esm/utils/response.utils.js +80 -0
- package/build/esm/utils/response.utils.js.map +1 -0
- package/build/esm/utils/string.utils.d.ts +37 -0
- package/build/esm/utils/string.utils.js +56 -0
- package/build/esm/utils/string.utils.js.map +1 -0
- package/build/esm/utils/url.utils.d.ts +24 -0
- package/build/esm/utils/url.utils.js +73 -0
- package/build/esm/utils/url.utils.js.map +1 -0
- package/build/esm/utils/validate.utils.d.ts +60 -0
- package/build/esm/utils/validate.utils.js +121 -0
- package/build/esm/utils/validate.utils.js.map +1 -0
- package/build/esnext/config.d.ts +22 -0
- package/build/esnext/config.js +21 -0
- package/build/esnext/config.js.map +1 -0
- package/build/esnext/index.d.ts +19 -0
- package/build/esnext/index.js +19 -0
- package/build/esnext/index.js.map +1 -0
- package/build/esnext/types/api-response.d.ts +44 -0
- package/build/esnext/types/api-response.js +2 -0
- package/build/esnext/types/api-response.js.map +1 -0
- package/build/esnext/utils/array.utils.d.ts +105 -0
- package/build/esnext/utils/array.utils.js +203 -0
- package/build/esnext/utils/array.utils.js.map +1 -0
- package/build/esnext/utils/async.utils.d.ts +119 -0
- package/build/esnext/utils/async.utils.js +291 -0
- package/build/esnext/utils/async.utils.js.map +1 -0
- package/build/esnext/utils/cache.utils.d.ts +90 -0
- package/build/esnext/utils/cache.utils.js +142 -0
- package/build/esnext/utils/cache.utils.js.map +1 -0
- package/build/esnext/utils/context-store.utils.d.ts +85 -0
- package/build/esnext/utils/context-store.utils.js +95 -0
- package/build/esnext/utils/context-store.utils.js.map +1 -0
- package/build/esnext/utils/crypto.utils.d.ts +58 -0
- package/build/esnext/utils/crypto.utils.js +72 -0
- package/build/esnext/utils/crypto.utils.js.map +1 -0
- package/build/esnext/utils/dir.utils.d.ts +75 -0
- package/build/esnext/utils/dir.utils.js +150 -0
- package/build/esnext/utils/dir.utils.js.map +1 -0
- package/build/esnext/utils/env.utils.d.ts +131 -0
- package/build/esnext/utils/env.utils.js +211 -0
- package/build/esnext/utils/env.utils.js.map +1 -0
- package/build/esnext/utils/exception.utils.d.ts +114 -0
- package/build/esnext/utils/exception.utils.js +148 -0
- package/build/esnext/utils/exception.utils.js.map +1 -0
- package/build/esnext/utils/fs.utils.d.ts +32 -0
- package/build/esnext/utils/fs.utils.js +62 -0
- package/build/esnext/utils/fs.utils.js.map +1 -0
- package/build/esnext/utils/http-status-codes.d.ts +357 -0
- package/build/esnext/utils/http-status-codes.js +358 -0
- package/build/esnext/utils/http-status-codes.js.map +1 -0
- package/build/esnext/utils/id.utils.d.ts +35 -0
- package/build/esnext/utils/id.utils.js +53 -0
- package/build/esnext/utils/id.utils.js.map +1 -0
- package/build/esnext/utils/logger.utils.d.ts +15 -0
- package/build/esnext/utils/logger.utils.js +59 -0
- package/build/esnext/utils/logger.utils.js.map +1 -0
- package/build/esnext/utils/obj.utils.d.ts +55 -0
- package/build/esnext/utils/obj.utils.js +94 -0
- package/build/esnext/utils/obj.utils.js.map +1 -0
- package/build/esnext/utils/response.utils.d.ts +48 -0
- package/build/esnext/utils/response.utils.js +58 -0
- package/build/esnext/utils/response.utils.js.map +1 -0
- package/build/esnext/utils/string.utils.d.ts +37 -0
- package/build/esnext/utils/string.utils.js +46 -0
- package/build/esnext/utils/string.utils.js.map +1 -0
- package/build/esnext/utils/url.utils.d.ts +24 -0
- package/build/esnext/utils/url.utils.js +35 -0
- package/build/esnext/utils/url.utils.js.map +1 -0
- package/build/esnext/utils/validate.utils.d.ts +60 -0
- package/build/esnext/utils/validate.utils.js +105 -0
- package/build/esnext/utils/validate.utils.js.map +1 -0
- package/build/src/config.d.ts +22 -0
- package/build/src/config.js +24 -0
- package/build/src/config.js.map +1 -0
- package/build/src/index.d.ts +19 -0
- package/build/src/index.js +35 -0
- package/build/src/index.js.map +1 -0
- package/build/src/types/api-response.d.ts +44 -0
- package/build/src/types/api-response.js +3 -0
- package/build/src/types/api-response.js.map +1 -0
- package/build/src/utils/array.utils.d.ts +105 -0
- package/build/src/utils/array.utils.js +216 -0
- package/build/src/utils/array.utils.js.map +1 -0
- package/build/src/utils/async.utils.d.ts +119 -0
- package/build/src/utils/async.utils.js +304 -0
- package/build/src/utils/async.utils.js.map +1 -0
- package/build/src/utils/cache.utils.d.ts +90 -0
- package/build/src/utils/cache.utils.js +146 -0
- package/build/src/utils/cache.utils.js.map +1 -0
- package/build/src/utils/context-store.utils.d.ts +85 -0
- package/build/src/utils/context-store.utils.js +100 -0
- package/build/src/utils/context-store.utils.js.map +1 -0
- package/build/src/utils/crypto.utils.d.ts +58 -0
- package/build/src/utils/crypto.utils.js +82 -0
- package/build/src/utils/crypto.utils.js.map +1 -0
- package/build/src/utils/dir.utils.d.ts +75 -0
- package/build/src/utils/dir.utils.js +164 -0
- package/build/src/utils/dir.utils.js.map +1 -0
- package/build/src/utils/env.utils.d.ts +131 -0
- package/build/src/utils/env.utils.js +215 -0
- package/build/src/utils/env.utils.js.map +1 -0
- package/build/src/utils/exception.utils.d.ts +114 -0
- package/build/src/utils/exception.utils.js +162 -0
- package/build/src/utils/exception.utils.js.map +1 -0
- package/build/src/utils/fs.utils.d.ts +32 -0
- package/build/src/utils/fs.utils.js +71 -0
- package/build/src/utils/fs.utils.js.map +1 -0
- package/build/src/utils/http-status-codes.d.ts +357 -0
- package/build/src/utils/http-status-codes.js +361 -0
- package/build/src/utils/http-status-codes.js.map +1 -0
- package/build/src/utils/id.utils.d.ts +35 -0
- package/build/src/utils/id.utils.js +60 -0
- package/build/src/utils/id.utils.js.map +1 -0
- package/build/src/utils/logger.utils.d.ts +15 -0
- package/build/src/utils/logger.utils.js +96 -0
- package/build/src/utils/logger.utils.js.map +1 -0
- package/build/src/utils/obj.utils.d.ts +55 -0
- package/build/src/utils/obj.utils.js +103 -0
- package/build/src/utils/obj.utils.js.map +1 -0
- package/build/src/utils/response.utils.d.ts +48 -0
- package/build/src/utils/response.utils.js +63 -0
- package/build/src/utils/response.utils.js.map +1 -0
- package/build/src/utils/string.utils.d.ts +37 -0
- package/build/src/utils/string.utils.js +54 -0
- package/build/src/utils/string.utils.js.map +1 -0
- package/build/src/utils/url.utils.d.ts +24 -0
- package/build/src/utils/url.utils.js +39 -0
- package/build/src/utils/url.utils.js.map +1 -0
- package/build/src/utils/validate.utils.d.ts +60 -0
- package/build/src/utils/validate.utils.js +115 -0
- package/build/src/utils/validate.utils.js.map +1 -0
- package/package.json +80 -0
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Checks whether the object has no own enumerable properties.
|
|
3
|
+
*
|
|
4
|
+
* @param {Record<any, any>} obj - The object to check.
|
|
5
|
+
* @returns {boolean} True if the object is empty, false otherwise.
|
|
6
|
+
*/
|
|
7
|
+
export declare const isObjEmpty: (obj: Record<any, any>) => boolean;
|
|
8
|
+
/**
|
|
9
|
+
* Returns a new object with only the specified keys picked.
|
|
10
|
+
*
|
|
11
|
+
* @template T
|
|
12
|
+
* @template K
|
|
13
|
+
* @param {T} obj - The source object.
|
|
14
|
+
* @param {K[]} keys - Keys to pick from the object.
|
|
15
|
+
* @returns {Pick<T, K>} New object with picked keys.
|
|
16
|
+
*/
|
|
17
|
+
export declare const pick: <T extends object, K extends keyof T>(obj: T, keys: K[]) => Pick<T, K>;
|
|
18
|
+
/**
|
|
19
|
+
* Returns a new object with the specified keys omitted.
|
|
20
|
+
*
|
|
21
|
+
* @template T
|
|
22
|
+
* @template K
|
|
23
|
+
* @param {T} obj - The source object.
|
|
24
|
+
* @param {K[]} keys - Keys to omit from the object.
|
|
25
|
+
* @returns {Omit<T, K>} New object without omitted keys.
|
|
26
|
+
*/
|
|
27
|
+
export declare const omit: <T extends object, K extends keyof T>(obj: T, keys: K[]) => Omit<T, K>;
|
|
28
|
+
/**
|
|
29
|
+
* Deeply merges two objects (mutates and returns the target object, not pure).
|
|
30
|
+
*
|
|
31
|
+
* @template T
|
|
32
|
+
* @param {T} target - The object to merge into (will be mutated).
|
|
33
|
+
* @param {Partial<T>} source - The object to merge from.
|
|
34
|
+
* @returns {T} The merged object (same as target).
|
|
35
|
+
*/
|
|
36
|
+
export declare function deepObjMerge<T extends Record<string, any>>(target: T, source: Partial<T>): T;
|
|
37
|
+
/**
|
|
38
|
+
* Flattens a nested object using dot notation for keys (e.g., `{a: {b: 1}}` → `{ "a.b": 1 }`).
|
|
39
|
+
*
|
|
40
|
+
* @template T
|
|
41
|
+
* @param {T} obj - The object to flatten.
|
|
42
|
+
* @param {string} [prefix=""] - Optional prefix for nested keys (used internally).
|
|
43
|
+
* @returns {Record<string, any>} A new object with flattened keys.
|
|
44
|
+
*/
|
|
45
|
+
export declare function flattenObject<T extends Record<string, any>>(obj: T, prefix?: string): Record<string, any>;
|
|
46
|
+
/**
|
|
47
|
+
* Safely gets the value of a deeply nested key in an object using dot/bracket notation path.
|
|
48
|
+
*
|
|
49
|
+
* @template T
|
|
50
|
+
* @param {T} obj - The object to extract from.
|
|
51
|
+
* @param {string} path - String path using dot and/or bracket notation (e.g., 'user.friends[0].name').
|
|
52
|
+
* @returns {any} The value at the given path, or undefined if not found.
|
|
53
|
+
*/
|
|
54
|
+
export declare function getValueByPath<T extends object>(obj: T, path: string): any;
|
|
55
|
+
//# sourceMappingURL=obj.utils.d.ts.map
|
|
@@ -0,0 +1,103 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.omit = exports.pick = exports.isObjEmpty = void 0;
|
|
4
|
+
exports.deepObjMerge = deepObjMerge;
|
|
5
|
+
exports.flattenObject = flattenObject;
|
|
6
|
+
exports.getValueByPath = getValueByPath;
|
|
7
|
+
/**
|
|
8
|
+
* Checks whether the object has no own enumerable properties.
|
|
9
|
+
*
|
|
10
|
+
* @param {Record<any, any>} obj - The object to check.
|
|
11
|
+
* @returns {boolean} True if the object is empty, false otherwise.
|
|
12
|
+
*/
|
|
13
|
+
const isObjEmpty = (obj) => !!obj && typeof obj === "object" && Object.keys(obj).length === 0;
|
|
14
|
+
exports.isObjEmpty = isObjEmpty;
|
|
15
|
+
/**
|
|
16
|
+
* Returns a new object with only the specified keys picked.
|
|
17
|
+
*
|
|
18
|
+
* @template T
|
|
19
|
+
* @template K
|
|
20
|
+
* @param {T} obj - The source object.
|
|
21
|
+
* @param {K[]} keys - Keys to pick from the object.
|
|
22
|
+
* @returns {Pick<T, K>} New object with picked keys.
|
|
23
|
+
*/
|
|
24
|
+
const pick = (obj, keys) => Object.fromEntries(keys.map((key) => [key, obj[key]]));
|
|
25
|
+
exports.pick = pick;
|
|
26
|
+
/**
|
|
27
|
+
* Returns a new object with the specified keys omitted.
|
|
28
|
+
*
|
|
29
|
+
* @template T
|
|
30
|
+
* @template K
|
|
31
|
+
* @param {T} obj - The source object.
|
|
32
|
+
* @param {K[]} keys - Keys to omit from the object.
|
|
33
|
+
* @returns {Omit<T, K>} New object without omitted keys.
|
|
34
|
+
*/
|
|
35
|
+
const omit = (obj, keys) => Object.fromEntries(Object.entries(obj).filter(([key]) => !keys.includes(key)));
|
|
36
|
+
exports.omit = omit;
|
|
37
|
+
/**
|
|
38
|
+
* Deeply merges two objects (mutates and returns the target object, not pure).
|
|
39
|
+
*
|
|
40
|
+
* @template T
|
|
41
|
+
* @param {T} target - The object to merge into (will be mutated).
|
|
42
|
+
* @param {Partial<T>} source - The object to merge from.
|
|
43
|
+
* @returns {T} The merged object (same as target).
|
|
44
|
+
*/
|
|
45
|
+
function deepObjMerge(target, source) {
|
|
46
|
+
for (const key in source) {
|
|
47
|
+
const sourceVal = source[key];
|
|
48
|
+
const targetVal = target[key];
|
|
49
|
+
if (sourceVal &&
|
|
50
|
+
typeof sourceVal === "object" &&
|
|
51
|
+
!Array.isArray(sourceVal)) {
|
|
52
|
+
if (!targetVal ||
|
|
53
|
+
typeof targetVal !== "object" ||
|
|
54
|
+
Array.isArray(targetVal)) {
|
|
55
|
+
target[key] = {};
|
|
56
|
+
}
|
|
57
|
+
deepObjMerge(target[key], sourceVal);
|
|
58
|
+
}
|
|
59
|
+
else {
|
|
60
|
+
target[key] = sourceVal;
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
return target;
|
|
64
|
+
}
|
|
65
|
+
/**
|
|
66
|
+
* Flattens a nested object using dot notation for keys (e.g., `{a: {b: 1}}` → `{ "a.b": 1 }`).
|
|
67
|
+
*
|
|
68
|
+
* @template T
|
|
69
|
+
* @param {T} obj - The object to flatten.
|
|
70
|
+
* @param {string} [prefix=""] - Optional prefix for nested keys (used internally).
|
|
71
|
+
* @returns {Record<string, any>} A new object with flattened keys.
|
|
72
|
+
*/
|
|
73
|
+
function flattenObject(obj, prefix = "") {
|
|
74
|
+
return Object.entries(obj).reduce((acc, [key, value]) => {
|
|
75
|
+
const newKey = prefix ? `${prefix}.${key}` : key;
|
|
76
|
+
if (value && typeof value === "object" && !Array.isArray(value)) {
|
|
77
|
+
Object.assign(acc, flattenObject(value, newKey));
|
|
78
|
+
}
|
|
79
|
+
else {
|
|
80
|
+
acc[newKey] = value;
|
|
81
|
+
}
|
|
82
|
+
return acc;
|
|
83
|
+
}, {});
|
|
84
|
+
}
|
|
85
|
+
/**
|
|
86
|
+
* Safely gets the value of a deeply nested key in an object using dot/bracket notation path.
|
|
87
|
+
*
|
|
88
|
+
* @template T
|
|
89
|
+
* @param {T} obj - The object to extract from.
|
|
90
|
+
* @param {string} path - String path using dot and/or bracket notation (e.g., 'user.friends[0].name').
|
|
91
|
+
* @returns {any} The value at the given path, or undefined if not found.
|
|
92
|
+
*/
|
|
93
|
+
function getValueByPath(obj, path) {
|
|
94
|
+
if (!obj || typeof obj !== "object")
|
|
95
|
+
return undefined;
|
|
96
|
+
// Convert path like "a.b[0].c" into ["a", "b", "0", "c"]
|
|
97
|
+
const parts = path
|
|
98
|
+
.replace(/\[(\d+)\]/g, ".$1") // convert [0] to .0
|
|
99
|
+
.split(".")
|
|
100
|
+
.filter(Boolean); // remove empty strings
|
|
101
|
+
return parts.reduce((acc, key) => acc === null || acc === void 0 ? void 0 : acc[key], obj);
|
|
102
|
+
}
|
|
103
|
+
//# sourceMappingURL=obj.utils.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"obj.utils.js","sourceRoot":"","sources":["../../../src/utils/obj.utils.ts"],"names":[],"mappings":";;;AAiDA,oCA0BC;AAUD,sCAkBC;AAUD,wCAUC;AA3HD;;;;;GAKG;AACI,MAAM,UAAU,GAAG,CAAC,GAAqB,EAAW,EAAE,CAC3D,CAAC,CAAC,GAAG,IAAI,OAAO,GAAG,KAAK,QAAQ,IAAI,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,MAAM,KAAK,CAAC,CAAC;AADvD,QAAA,UAAU,cAC6C;AAEpE;;;;;;;;GAQG;AACI,MAAM,IAAI,GAAG,CAClB,GAAM,EACN,IAAS,EACG,EAAE,CACd,MAAM,CAAC,WAAW,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,CAAC,GAAG,EAAE,GAAG,CAAC,GAAG,CAAC,CAAC,CAAC,CAAe,CAAC;AAJ1D,QAAA,IAAI,QAIsD;AAEvE;;;;;;;;GAQG;AACI,MAAM,IAAI,GAAG,CAClB,GAAM,EACN,IAAS,EACG,EAAE,CACd,MAAM,CAAC,WAAW,CAChB,MAAM,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,GAAG,CAAC,EAAE,EAAE,CAAC,CAAC,IAAI,CAAC,QAAQ,CAAC,GAAQ,CAAC,CAAC,CAClD,CAAC;AANL,QAAA,IAAI,QAMC;AAElB;;;;;;;GAOG;AACH,SAAgB,YAAY,CAC1B,MAAS,EACT,MAAkB;IAElB,KAAK,MAAM,GAAG,IAAI,MAAM,EAAE,CAAC;QACzB,MAAM,SAAS,GAAG,MAAM,CAAC,GAAG,CAAC,CAAC;QAC9B,MAAM,SAAS,GAAG,MAAM,CAAC,GAAG,CAAC,CAAC;QAE9B,IACE,SAAS;YACT,OAAO,SAAS,KAAK,QAAQ;YAC7B,CAAC,KAAK,CAAC,OAAO,CAAC,SAAS,CAAC,EACzB,CAAC;YACD,IACE,CAAC,SAAS;gBACV,OAAO,SAAS,KAAK,QAAQ;gBAC7B,KAAK,CAAC,OAAO,CAAC,SAAS,CAAC,EACxB,CAAC;gBACD,MAAM,CAAC,GAAG,CAAC,GAAG,EAAS,CAAC;YAC1B,CAAC;YACD,YAAY,CAAC,MAAM,CAAC,GAAG,CAAC,EAAE,SAAgB,CAAC,CAAC;QAC9C,CAAC;aAAM,CAAC;YACN,MAAM,CAAC,GAAG,CAAC,GAAG,SAAwC,CAAC;QACzD,CAAC;IACH,CAAC;IACD,OAAO,MAAM,CAAC;AAChB,CAAC;AAED;;;;;;;GAOG;AACH,SAAgB,aAAa,CAC3B,GAAM,EACN,MAAM,GAAG,EAAE;IAEX,OAAO,MAAM,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC,MAAM,CAC/B,CAAC,GAAwB,EAAE,CAAC,GAAG,EAAE,KAAK,CAAC,EAAE,EAAE;QACzC,MAAM,MAAM,GAAG,MAAM,CAAC,CAAC,CAAC,GAAG,MAAM,IAAI,GAAG,EAAE,CAAC,CAAC,CAAC,GAAG,CAAC;QAEjD,IAAI,KAAK,IAAI,OAAO,KAAK,KAAK,QAAQ,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,EAAE,CAAC;YAChE,MAAM,CAAC,MAAM,CAAC,GAAG,EAAE,aAAa,CAAC,KAAK,EAAE,MAAM,CAAC,CAAC,CAAC;QACnD,CAAC;aAAM,CAAC;YACN,GAAG,CAAC,MAAM,CAAC,GAAG,KAAK,CAAC;QACtB,CAAC;QAED,OAAO,GAAG,CAAC;IACb,CAAC,EACD,EAAE,CACH,CAAC;AACJ,CAAC;AAED;;;;;;;GAOG;AACH,SAAgB,cAAc,CAAmB,GAAM,EAAE,IAAY;IACnE,IAAI,CAAC,GAAG,IAAI,OAAO,GAAG,KAAK,QAAQ;QAAE,OAAO,SAAS,CAAC;IAEtD,yDAAyD;IACzD,MAAM,KAAK,GAAG,IAAI;SACf,OAAO,CAAC,YAAY,EAAE,KAAK,CAAC,CAAC,oBAAoB;SACjD,KAAK,CAAC,GAAG,CAAC;SACV,MAAM,CAAC,OAAO,CAAC,CAAC,CAAC,uBAAuB;IAE3C,OAAO,KAAK,CAAC,MAAM,CAAC,CAAC,GAAQ,EAAE,GAAW,EAAE,EAAE,CAAC,GAAG,aAAH,GAAG,uBAAH,GAAG,CAAG,GAAG,CAAC,EAAE,GAAG,CAAC,CAAC;AAClE,CAAC","sourcesContent":["/**\n * Checks whether the object has no own enumerable properties.\n *\n * @param {Record<any, any>} obj - The object to check.\n * @returns {boolean} True if the object is empty, false otherwise.\n */\nexport const isObjEmpty = (obj: Record<any, any>): boolean =>\n !!obj && typeof obj === \"object\" && Object.keys(obj).length === 0;\n\n/**\n * Returns a new object with only the specified keys picked.\n *\n * @template T\n * @template K\n * @param {T} obj - The source object.\n * @param {K[]} keys - Keys to pick from the object.\n * @returns {Pick<T, K>} New object with picked keys.\n */\nexport const pick = <T extends object, K extends keyof T>(\n obj: T,\n keys: K[],\n): Pick<T, K> =>\n Object.fromEntries(keys.map((key) => [key, obj[key]])) as Pick<T, K>;\n\n/**\n * Returns a new object with the specified keys omitted.\n *\n * @template T\n * @template K\n * @param {T} obj - The source object.\n * @param {K[]} keys - Keys to omit from the object.\n * @returns {Omit<T, K>} New object without omitted keys.\n */\nexport const omit = <T extends object, K extends keyof T>(\n obj: T,\n keys: K[],\n): Omit<T, K> =>\n Object.fromEntries(\n Object.entries(obj).filter(([key]) => !keys.includes(key as K)),\n ) as Omit<T, K>;\n\n/**\n * Deeply merges two objects (mutates and returns the target object, not pure).\n *\n * @template T\n * @param {T} target - The object to merge into (will be mutated).\n * @param {Partial<T>} source - The object to merge from.\n * @returns {T} The merged object (same as target).\n */\nexport function deepObjMerge<T extends Record<string, any>>(\n target: T,\n source: Partial<T>,\n): T {\n for (const key in source) {\n const sourceVal = source[key];\n const targetVal = target[key];\n\n if (\n sourceVal &&\n typeof sourceVal === \"object\" &&\n !Array.isArray(sourceVal)\n ) {\n if (\n !targetVal ||\n typeof targetVal !== \"object\" ||\n Array.isArray(targetVal)\n ) {\n target[key] = {} as any;\n }\n deepObjMerge(target[key], sourceVal as any);\n } else {\n target[key] = sourceVal as T[Extract<keyof T, string>];\n }\n }\n return target;\n}\n\n/**\n * Flattens a nested object using dot notation for keys (e.g., `{a: {b: 1}}` → `{ \"a.b\": 1 }`).\n *\n * @template T\n * @param {T} obj - The object to flatten.\n * @param {string} [prefix=\"\"] - Optional prefix for nested keys (used internally).\n * @returns {Record<string, any>} A new object with flattened keys.\n */\nexport function flattenObject<T extends Record<string, any>>(\n obj: T,\n prefix = \"\",\n): Record<string, any> {\n return Object.entries(obj).reduce(\n (acc: Record<string, any>, [key, value]) => {\n const newKey = prefix ? `${prefix}.${key}` : key;\n\n if (value && typeof value === \"object\" && !Array.isArray(value)) {\n Object.assign(acc, flattenObject(value, newKey));\n } else {\n acc[newKey] = value;\n }\n\n return acc;\n },\n {},\n );\n}\n\n/**\n * Safely gets the value of a deeply nested key in an object using dot/bracket notation path.\n *\n * @template T\n * @param {T} obj - The object to extract from.\n * @param {string} path - String path using dot and/or bracket notation (e.g., 'user.friends[0].name').\n * @returns {any} The value at the given path, or undefined if not found.\n */\nexport function getValueByPath<T extends object>(obj: T, path: string) {\n if (!obj || typeof obj !== \"object\") return undefined;\n\n // Convert path like \"a.b[0].c\" into [\"a\", \"b\", \"0\", \"c\"]\n const parts = path\n .replace(/\\[(\\d+)\\]/g, \".$1\") // convert [0] to .0\n .split(\".\")\n .filter(Boolean); // remove empty strings\n\n return parts.reduce((acc: any, key: string) => acc?.[key], obj);\n}\n"]}
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
import { ApiResponse } from "../types/api-response";
|
|
2
|
+
/**
|
|
3
|
+
* Standard HTTP response wrapper for successful responses.
|
|
4
|
+
* Implements the `ApiResponse<T>` interface and sets default values.
|
|
5
|
+
*
|
|
6
|
+
* @typeParam T - The shape of the data returned in the response.
|
|
7
|
+
*/
|
|
8
|
+
export declare class SuccessResponse<T> implements ApiResponse<T> {
|
|
9
|
+
/** Message describing the result of the operation. */
|
|
10
|
+
message: string;
|
|
11
|
+
/** Whether the response is an error. Always false in success responses. */
|
|
12
|
+
error: boolean;
|
|
13
|
+
/** The payload returned from the API. */
|
|
14
|
+
data: T | null;
|
|
15
|
+
/** Timestamp when the response was generated, in ISO format. */
|
|
16
|
+
timestamp: string;
|
|
17
|
+
/** Unique identifier for this response, useful for request tracing. */
|
|
18
|
+
requestId: string;
|
|
19
|
+
/**
|
|
20
|
+
* Constructs a new success response.
|
|
21
|
+
*
|
|
22
|
+
* @param {string} message - Optional message to override the default.
|
|
23
|
+
* @param {T} [data] - Optional data payload.
|
|
24
|
+
*/
|
|
25
|
+
constructor(message: string, data?: T);
|
|
26
|
+
}
|
|
27
|
+
/**
|
|
28
|
+
* Wrapper for error responses that extends the native `Error` object.
|
|
29
|
+
* Implements `ApiResponse` but omits the `data` field (which should not be present in errors).
|
|
30
|
+
*/
|
|
31
|
+
export declare class ErrorResponse extends Error implements Omit<ApiResponse<never>, "data"> {
|
|
32
|
+
/** HTTP status code associated with the error (e.g., 404, 500). */
|
|
33
|
+
status: number;
|
|
34
|
+
/** Indicates that this is an error. Always true. */
|
|
35
|
+
error: boolean;
|
|
36
|
+
/** Timestamp when the error occurred, in ISO format. */
|
|
37
|
+
timestamp: string;
|
|
38
|
+
/** Unique identifier for this error instance. */
|
|
39
|
+
requestId: string;
|
|
40
|
+
/**
|
|
41
|
+
* Constructs a new error response.
|
|
42
|
+
*
|
|
43
|
+
* @param {string} message - The error message to display or log.
|
|
44
|
+
* @param {number} [status=500] - Optional HTTP status code (defaults to 500).
|
|
45
|
+
*/
|
|
46
|
+
constructor(message: string, status?: number);
|
|
47
|
+
}
|
|
48
|
+
//# sourceMappingURL=response.utils.d.ts.map
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.ErrorResponse = exports.SuccessResponse = void 0;
|
|
4
|
+
const crypto_1 = require("crypto");
|
|
5
|
+
const context_store_utils_1 = require("./context-store.utils");
|
|
6
|
+
/**
|
|
7
|
+
* Standard HTTP response wrapper for successful responses.
|
|
8
|
+
* Implements the `ApiResponse<T>` interface and sets default values.
|
|
9
|
+
*
|
|
10
|
+
* @typeParam T - The shape of the data returned in the response.
|
|
11
|
+
*/
|
|
12
|
+
class SuccessResponse {
|
|
13
|
+
/**
|
|
14
|
+
* Constructs a new success response.
|
|
15
|
+
*
|
|
16
|
+
* @param {string} message - Optional message to override the default.
|
|
17
|
+
* @param {T} [data] - Optional data payload.
|
|
18
|
+
*/
|
|
19
|
+
constructor(message, data) {
|
|
20
|
+
var _a;
|
|
21
|
+
/** Message describing the result of the operation. */
|
|
22
|
+
this.message = "Success";
|
|
23
|
+
/** Whether the response is an error. Always false in success responses. */
|
|
24
|
+
this.error = false;
|
|
25
|
+
/** The payload returned from the API. */
|
|
26
|
+
this.data = null;
|
|
27
|
+
/** Timestamp when the response was generated, in ISO format. */
|
|
28
|
+
this.timestamp = new Date().toISOString();
|
|
29
|
+
/** Unique identifier for this response, useful for request tracing. */
|
|
30
|
+
this.requestId = (_a = (0, context_store_utils_1.getRequestId)()) !== null && _a !== void 0 ? _a : (0, crypto_1.randomUUID)();
|
|
31
|
+
if (message)
|
|
32
|
+
this.message = message;
|
|
33
|
+
this.data = data !== null && data !== void 0 ? data : null;
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
exports.SuccessResponse = SuccessResponse;
|
|
37
|
+
/**
|
|
38
|
+
* Wrapper for error responses that extends the native `Error` object.
|
|
39
|
+
* Implements `ApiResponse` but omits the `data` field (which should not be present in errors).
|
|
40
|
+
*/
|
|
41
|
+
class ErrorResponse extends Error {
|
|
42
|
+
/**
|
|
43
|
+
* Constructs a new error response.
|
|
44
|
+
*
|
|
45
|
+
* @param {string} message - The error message to display or log.
|
|
46
|
+
* @param {number} [status=500] - Optional HTTP status code (defaults to 500).
|
|
47
|
+
*/
|
|
48
|
+
constructor(message, status = 500) {
|
|
49
|
+
var _a;
|
|
50
|
+
super(message);
|
|
51
|
+
/** Indicates that this is an error. Always true. */
|
|
52
|
+
this.error = true;
|
|
53
|
+
/** Timestamp when the error occurred, in ISO format. */
|
|
54
|
+
this.timestamp = new Date().toISOString();
|
|
55
|
+
/** Unique identifier for this error instance. */
|
|
56
|
+
this.requestId = (_a = (0, context_store_utils_1.getRequestId)()) !== null && _a !== void 0 ? _a : (0, crypto_1.randomUUID)();
|
|
57
|
+
this.status = status;
|
|
58
|
+
this.name = this.constructor.name;
|
|
59
|
+
Error.captureStackTrace(this, this.constructor);
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
exports.ErrorResponse = ErrorResponse;
|
|
63
|
+
//# sourceMappingURL=response.utils.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"response.utils.js","sourceRoot":"","sources":["../../../src/utils/response.utils.ts"],"names":[],"mappings":";;;AAAA,mCAAoC;AAEpC,+DAAqD;AAErD;;;;;GAKG;AACH,MAAa,eAAe;IAgB1B;;;;;OAKG;IACH,YAAY,OAAe,EAAE,IAAQ;;QArBrC,sDAAsD;QACtD,YAAO,GAAW,SAAS,CAAC;QAE5B,2EAA2E;QAC3E,UAAK,GAAY,KAAK,CAAC;QAEvB,yCAAyC;QACzC,SAAI,GAAa,IAAI,CAAC;QAEtB,gEAAgE;QAChE,cAAS,GAAW,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE,CAAC;QAE7C,uEAAuE;QACvE,cAAS,GAAW,MAAA,IAAA,kCAAY,GAAE,mCAAI,IAAA,mBAAU,GAAE,CAAC;QASjD,IAAI,OAAO;YAAE,IAAI,CAAC,OAAO,GAAG,OAAO,CAAC;QACpC,IAAI,CAAC,IAAI,GAAG,IAAI,aAAJ,IAAI,cAAJ,IAAI,GAAI,IAAI,CAAC;IAC3B,CAAC;CACF;AA1BD,0CA0BC;AAED;;;GAGG;AACH,MAAa,aACX,SAAQ,KAAK;IAeb;;;;;OAKG;IACH,YAAY,OAAe,EAAE,SAAiB,GAAG;;QAC/C,KAAK,CAAC,OAAO,CAAC,CAAC;QAhBjB,oDAAoD;QACpD,UAAK,GAAY,IAAI,CAAC;QAEtB,wDAAwD;QACxD,cAAS,GAAW,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE,CAAC;QAE7C,iDAAiD;QACjD,cAAS,GAAW,MAAA,IAAA,kCAAY,GAAE,mCAAI,IAAA,mBAAU,GAAE,CAAC;QAUjD,IAAI,CAAC,MAAM,GAAG,MAAM,CAAC;QACrB,IAAI,CAAC,IAAI,GAAG,IAAI,CAAC,WAAW,CAAC,IAAI,CAAC;QAClC,KAAK,CAAC,iBAAiB,CAAC,IAAI,EAAE,IAAI,CAAC,WAAW,CAAC,CAAC;IAClD,CAAC;CACF;AA5BD,sCA4BC","sourcesContent":["import { randomUUID } from \"crypto\";\nimport { ApiResponse } from \"../types/api-response\";\nimport { getRequestId } from \"./context-store.utils\";\n\n/**\n * Standard HTTP response wrapper for successful responses.\n * Implements the `ApiResponse<T>` interface and sets default values.\n *\n * @typeParam T - The shape of the data returned in the response.\n */\nexport class SuccessResponse<T> implements ApiResponse<T> {\n /** Message describing the result of the operation. */\n message: string = \"Success\";\n\n /** Whether the response is an error. Always false in success responses. */\n error: boolean = false;\n\n /** The payload returned from the API. */\n data: T | null = null;\n\n /** Timestamp when the response was generated, in ISO format. */\n timestamp: string = new Date().toISOString();\n\n /** Unique identifier for this response, useful for request tracing. */\n requestId: string = getRequestId() ?? randomUUID();\n\n /**\n * Constructs a new success response.\n *\n * @param {string} message - Optional message to override the default.\n * @param {T} [data] - Optional data payload.\n */\n constructor(message: string, data?: T) {\n if (message) this.message = message;\n this.data = data ?? null;\n }\n}\n\n/**\n * Wrapper for error responses that extends the native `Error` object.\n * Implements `ApiResponse` but omits the `data` field (which should not be present in errors).\n */\nexport class ErrorResponse\n extends Error\n implements Omit<ApiResponse<never>, \"data\">\n{\n /** HTTP status code associated with the error (e.g., 404, 500). */\n status: number;\n\n /** Indicates that this is an error. Always true. */\n error: boolean = true;\n\n /** Timestamp when the error occurred, in ISO format. */\n timestamp: string = new Date().toISOString();\n\n /** Unique identifier for this error instance. */\n requestId: string = getRequestId() ?? randomUUID();\n\n /**\n * Constructs a new error response.\n *\n * @param {string} message - The error message to display or log.\n * @param {number} [status=500] - Optional HTTP status code (defaults to 500).\n */\n constructor(message: string, status: number = 500) {\n super(message);\n this.status = status;\n this.name = this.constructor.name;\n Error.captureStackTrace(this, this.constructor);\n }\n}\n"]}
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Capitalizes the first character of a string.
|
|
3
|
+
*
|
|
4
|
+
* @param {string} str - The input string.
|
|
5
|
+
* @returns {string} The string with the first character in uppercase.
|
|
6
|
+
*/
|
|
7
|
+
export declare const capitalize: (str: string) => string;
|
|
8
|
+
/**
|
|
9
|
+
* Converts a string to kebab-case (e.g., "FooBar test" → "foo-bar-test").
|
|
10
|
+
*
|
|
11
|
+
* @param {string} str - The input string.
|
|
12
|
+
* @returns {string} The kebab-cased string.
|
|
13
|
+
*/
|
|
14
|
+
export declare const toKebabCase: (str: string) => string;
|
|
15
|
+
/**
|
|
16
|
+
* Converts a kebab-case or snake_case string to camelCase.
|
|
17
|
+
*
|
|
18
|
+
* @param {string} str - The input string.
|
|
19
|
+
* @returns {string} The camelCased string.
|
|
20
|
+
*/
|
|
21
|
+
export declare const toCamelCase: (str: string) => string;
|
|
22
|
+
/**
|
|
23
|
+
* Converts a string to a URL-friendly slug (lowercase, dashes, alphanumeric).
|
|
24
|
+
*
|
|
25
|
+
* @param {string} str - The input string.
|
|
26
|
+
* @returns {string} The slugified string.
|
|
27
|
+
*/
|
|
28
|
+
export declare const slugify: (str: string) => string;
|
|
29
|
+
/**
|
|
30
|
+
* Truncates a string to a specific length, appending '...' if truncated.
|
|
31
|
+
*
|
|
32
|
+
* @param {string} str - The input string.
|
|
33
|
+
* @param {number} len - The maximum length.
|
|
34
|
+
* @returns {string} The truncated string.
|
|
35
|
+
*/
|
|
36
|
+
export declare const truncate: (str: string, len: number) => string;
|
|
37
|
+
//# sourceMappingURL=string.utils.d.ts.map
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.truncate = exports.slugify = exports.toCamelCase = exports.toKebabCase = exports.capitalize = void 0;
|
|
4
|
+
/**
|
|
5
|
+
* Capitalizes the first character of a string.
|
|
6
|
+
*
|
|
7
|
+
* @param {string} str - The input string.
|
|
8
|
+
* @returns {string} The string with the first character in uppercase.
|
|
9
|
+
*/
|
|
10
|
+
const capitalize = (str) => str.length === 0 ? "" : str.charAt(0).toUpperCase() + str.slice(1);
|
|
11
|
+
exports.capitalize = capitalize;
|
|
12
|
+
/**
|
|
13
|
+
* Converts a string to kebab-case (e.g., "FooBar test" → "foo-bar-test").
|
|
14
|
+
*
|
|
15
|
+
* @param {string} str - The input string.
|
|
16
|
+
* @returns {string} The kebab-cased string.
|
|
17
|
+
*/
|
|
18
|
+
const toKebabCase = (str) => str
|
|
19
|
+
.replace(/([a-z])([A-Z])/g, "$1-$2") // camelCase -> camel-Case
|
|
20
|
+
.replace(/\s+/g, "-") // spaces to dash
|
|
21
|
+
.replace(/_+/g, "-") // underscores to dash
|
|
22
|
+
.toLowerCase();
|
|
23
|
+
exports.toKebabCase = toKebabCase;
|
|
24
|
+
/**
|
|
25
|
+
* Converts a kebab-case or snake_case string to camelCase.
|
|
26
|
+
*
|
|
27
|
+
* @param {string} str - The input string.
|
|
28
|
+
* @returns {string} The camelCased string.
|
|
29
|
+
*/
|
|
30
|
+
const toCamelCase = (str) => str.replace(/[-_](.)/g, (_, c) => c.toUpperCase());
|
|
31
|
+
exports.toCamelCase = toCamelCase;
|
|
32
|
+
/**
|
|
33
|
+
* Converts a string to a URL-friendly slug (lowercase, dashes, alphanumeric).
|
|
34
|
+
*
|
|
35
|
+
* @param {string} str - The input string.
|
|
36
|
+
* @returns {string} The slugified string.
|
|
37
|
+
*/
|
|
38
|
+
const slugify = (str) => str
|
|
39
|
+
.toLowerCase()
|
|
40
|
+
.replace(/[^\w\s-]/g, "") // remove non-word
|
|
41
|
+
.replace(/\s+/g, "-") // spaces to dash
|
|
42
|
+
.replace(/-+/g, "-") // multiple dashes to one
|
|
43
|
+
.replace(/^-+|-+$/g, ""); // trim leading/trailing dashes
|
|
44
|
+
exports.slugify = slugify;
|
|
45
|
+
/**
|
|
46
|
+
* Truncates a string to a specific length, appending '...' if truncated.
|
|
47
|
+
*
|
|
48
|
+
* @param {string} str - The input string.
|
|
49
|
+
* @param {number} len - The maximum length.
|
|
50
|
+
* @returns {string} The truncated string.
|
|
51
|
+
*/
|
|
52
|
+
const truncate = (str, len) => str.length > len ? str.slice(0, len) + "..." : str;
|
|
53
|
+
exports.truncate = truncate;
|
|
54
|
+
//# sourceMappingURL=string.utils.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"string.utils.js","sourceRoot":"","sources":["../../../src/utils/string.utils.ts"],"names":[],"mappings":";;;AAAA;;;;;GAKG;AACI,MAAM,UAAU,GAAG,CAAC,GAAW,EAAU,EAAE,CAChD,GAAG,CAAC,MAAM,KAAK,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,WAAW,EAAE,GAAG,GAAG,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;AADxD,QAAA,UAAU,cAC8C;AAErE;;;;;GAKG;AACI,MAAM,WAAW,GAAG,CAAC,GAAW,EAAU,EAAE,CACjD,GAAG;KACA,OAAO,CAAC,iBAAiB,EAAE,OAAO,CAAC,CAAC,0BAA0B;KAC9D,OAAO,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC,iBAAiB;KACtC,OAAO,CAAC,KAAK,EAAE,GAAG,CAAC,CAAC,sBAAsB;KAC1C,WAAW,EAAE,CAAC;AALN,QAAA,WAAW,eAKL;AAEnB;;;;;GAKG;AACI,MAAM,WAAW,GAAG,CAAC,GAAW,EAAU,EAAE,CACjD,GAAG,CAAC,OAAO,CAAC,UAAU,EAAE,CAAC,CAAC,EAAE,CAAS,EAAE,EAAE,CAAC,CAAC,CAAC,WAAW,EAAE,CAAC,CAAC;AADhD,QAAA,WAAW,eACqC;AAE7D;;;;;GAKG;AACI,MAAM,OAAO,GAAG,CAAC,GAAW,EAAU,EAAE,CAC7C,GAAG;KACA,WAAW,EAAE;KACb,OAAO,CAAC,WAAW,EAAE,EAAE,CAAC,CAAC,kBAAkB;KAC3C,OAAO,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC,iBAAiB;KACtC,OAAO,CAAC,KAAK,EAAE,GAAG,CAAC,CAAC,yBAAyB;KAC7C,OAAO,CAAC,UAAU,EAAE,EAAE,CAAC,CAAC,CAAC,+BAA+B;AANhD,QAAA,OAAO,WAMS;AAE7B;;;;;;GAMG;AACI,MAAM,QAAQ,GAAG,CAAC,GAAW,EAAE,GAAW,EAAU,EAAE,CAC3D,GAAG,CAAC,MAAM,GAAG,GAAG,CAAC,CAAC,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC,EAAE,GAAG,CAAC,GAAG,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC;AADxC,QAAA,QAAQ,YACgC","sourcesContent":["/**\n * Capitalizes the first character of a string.\n *\n * @param {string} str - The input string.\n * @returns {string} The string with the first character in uppercase.\n */\nexport const capitalize = (str: string): string =>\n str.length === 0 ? \"\" : str.charAt(0).toUpperCase() + str.slice(1);\n\n/**\n * Converts a string to kebab-case (e.g., \"FooBar test\" → \"foo-bar-test\").\n *\n * @param {string} str - The input string.\n * @returns {string} The kebab-cased string.\n */\nexport const toKebabCase = (str: string): string =>\n str\n .replace(/([a-z])([A-Z])/g, \"$1-$2\") // camelCase -> camel-Case\n .replace(/\\s+/g, \"-\") // spaces to dash\n .replace(/_+/g, \"-\") // underscores to dash\n .toLowerCase();\n\n/**\n * Converts a kebab-case or snake_case string to camelCase.\n *\n * @param {string} str - The input string.\n * @returns {string} The camelCased string.\n */\nexport const toCamelCase = (str: string): string =>\n str.replace(/[-_](.)/g, (_, c: string) => c.toUpperCase());\n\n/**\n * Converts a string to a URL-friendly slug (lowercase, dashes, alphanumeric).\n *\n * @param {string} str - The input string.\n * @returns {string} The slugified string.\n */\nexport const slugify = (str: string): string =>\n str\n .toLowerCase()\n .replace(/[^\\w\\s-]/g, \"\") // remove non-word\n .replace(/\\s+/g, \"-\") // spaces to dash\n .replace(/-+/g, \"-\") // multiple dashes to one\n .replace(/^-+|-+$/g, \"\"); // trim leading/trailing dashes\n\n/**\n * Truncates a string to a specific length, appending '...' if truncated.\n *\n * @param {string} str - The input string.\n * @param {number} len - The maximum length.\n * @returns {string} The truncated string.\n */\nexport const truncate = (str: string, len: number): string =>\n str.length > len ? str.slice(0, len) + \"...\" : str;\n"]}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Appends query parameters to a given URL.
|
|
3
|
+
*
|
|
4
|
+
* @param {string} url - The base URL to which query parameters will be appended.
|
|
5
|
+
* @param {Record<string, string | number>} params - Key-value pairs to add as query parameters.
|
|
6
|
+
* @returns {string} The new URL string with query parameters appended.
|
|
7
|
+
*
|
|
8
|
+
* @example
|
|
9
|
+
* appendQueryParams('https://example.com', { page: 1, limit: 10 });
|
|
10
|
+
* // → 'https://example.com/?page=1&limit=10'
|
|
11
|
+
*/
|
|
12
|
+
export declare function appendQueryParams(url: string, params: Record<string, string | number>): string;
|
|
13
|
+
/**
|
|
14
|
+
* Parses a query string into a key-value object.
|
|
15
|
+
*
|
|
16
|
+
* @param {string} query - The query string (with or without leading '?').
|
|
17
|
+
* @returns {Record<string, string>} Object representing parsed query parameters.
|
|
18
|
+
*
|
|
19
|
+
* @example
|
|
20
|
+
* parseQueryString('?page=1&limit=10');
|
|
21
|
+
* // → { page: '1', limit: '10' }
|
|
22
|
+
*/
|
|
23
|
+
export declare function parseQueryString(query: string): Record<string, string>;
|
|
24
|
+
//# sourceMappingURL=url.utils.d.ts.map
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.appendQueryParams = appendQueryParams;
|
|
4
|
+
exports.parseQueryString = parseQueryString;
|
|
5
|
+
const url_1 = require("url");
|
|
6
|
+
/**
|
|
7
|
+
* Appends query parameters to a given URL.
|
|
8
|
+
*
|
|
9
|
+
* @param {string} url - The base URL to which query parameters will be appended.
|
|
10
|
+
* @param {Record<string, string | number>} params - Key-value pairs to add as query parameters.
|
|
11
|
+
* @returns {string} The new URL string with query parameters appended.
|
|
12
|
+
*
|
|
13
|
+
* @example
|
|
14
|
+
* appendQueryParams('https://example.com', { page: 1, limit: 10 });
|
|
15
|
+
* // → 'https://example.com/?page=1&limit=10'
|
|
16
|
+
*/
|
|
17
|
+
function appendQueryParams(url, params) {
|
|
18
|
+
const urlObj = new url_1.URL(url);
|
|
19
|
+
for (const [key, value] of Object.entries(params)) {
|
|
20
|
+
urlObj.searchParams.set(key, value.toString());
|
|
21
|
+
}
|
|
22
|
+
return urlObj.toString();
|
|
23
|
+
}
|
|
24
|
+
/**
|
|
25
|
+
* Parses a query string into a key-value object.
|
|
26
|
+
*
|
|
27
|
+
* @param {string} query - The query string (with or without leading '?').
|
|
28
|
+
* @returns {Record<string, string>} Object representing parsed query parameters.
|
|
29
|
+
*
|
|
30
|
+
* @example
|
|
31
|
+
* parseQueryString('?page=1&limit=10');
|
|
32
|
+
* // → { page: '1', limit: '10' }
|
|
33
|
+
*/
|
|
34
|
+
function parseQueryString(query) {
|
|
35
|
+
const cleanQuery = query.startsWith("?") ? query.slice(1) : query;
|
|
36
|
+
// Object.fromEntries guarantees string values in result
|
|
37
|
+
return Object.fromEntries(new url_1.URLSearchParams(cleanQuery));
|
|
38
|
+
}
|
|
39
|
+
//# sourceMappingURL=url.utils.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"url.utils.js","sourceRoot":"","sources":["../../../src/utils/url.utils.ts"],"names":[],"mappings":";;AAaA,8CASC;AAYD,4CAOC;AAzCD,6BAA2C;AAE3C;;;;;;;;;;GAUG;AACH,SAAgB,iBAAiB,CAC/B,GAAW,EACX,MAAuC;IAEvC,MAAM,MAAM,GAAG,IAAI,SAAG,CAAC,GAAG,CAAC,CAAC;IAC5B,KAAK,MAAM,CAAC,GAAG,EAAE,KAAK,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,MAAM,CAAC,EAAE,CAAC;QAClD,MAAM,CAAC,YAAY,CAAC,GAAG,CAAC,GAAG,EAAE,KAAK,CAAC,QAAQ,EAAE,CAAC,CAAC;IACjD,CAAC;IACD,OAAO,MAAM,CAAC,QAAQ,EAAE,CAAC;AAC3B,CAAC;AAED;;;;;;;;;GASG;AACH,SAAgB,gBAAgB,CAAC,KAAa;IAC5C,MAAM,UAAU,GAAG,KAAK,CAAC,UAAU,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC;IAClE,wDAAwD;IACxD,OAAO,MAAM,CAAC,WAAW,CAAC,IAAI,qBAAe,CAAC,UAAU,CAAC,CAGxD,CAAC;AACJ,CAAC","sourcesContent":["import { URL, URLSearchParams } from \"url\";\n\n/**\n * Appends query parameters to a given URL.\n *\n * @param {string} url - The base URL to which query parameters will be appended.\n * @param {Record<string, string | number>} params - Key-value pairs to add as query parameters.\n * @returns {string} The new URL string with query parameters appended.\n *\n * @example\n * appendQueryParams('https://example.com', { page: 1, limit: 10 });\n * // → 'https://example.com/?page=1&limit=10'\n */\nexport function appendQueryParams(\n url: string,\n params: Record<string, string | number>,\n): string {\n const urlObj = new URL(url);\n for (const [key, value] of Object.entries(params)) {\n urlObj.searchParams.set(key, value.toString());\n }\n return urlObj.toString();\n}\n\n/**\n * Parses a query string into a key-value object.\n *\n * @param {string} query - The query string (with or without leading '?').\n * @returns {Record<string, string>} Object representing parsed query parameters.\n *\n * @example\n * parseQueryString('?page=1&limit=10');\n * // → { page: '1', limit: '10' }\n */\nexport function parseQueryString(query: string): Record<string, string> {\n const cleanQuery = query.startsWith(\"?\") ? query.slice(1) : query;\n // Object.fromEntries guarantees string values in result\n return Object.fromEntries(new URLSearchParams(cleanQuery)) as Record<\n string,\n string\n >;\n}\n"]}
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Collection of common validation helpers for strings, numbers, email, UUID, etc.
|
|
3
|
+
*/
|
|
4
|
+
/**
|
|
5
|
+
* Checks if a string is a valid email address.
|
|
6
|
+
*
|
|
7
|
+
* @param {string} str - The input string.
|
|
8
|
+
* @returns {boolean} True if valid email, else false.
|
|
9
|
+
*/
|
|
10
|
+
export declare function isEmail(str: string): boolean;
|
|
11
|
+
/**
|
|
12
|
+
* Checks if a string is a valid UUID (versions 1-5).
|
|
13
|
+
*
|
|
14
|
+
* @param {string} str - The input string.
|
|
15
|
+
* @returns {boolean} True if valid UUID, else false.
|
|
16
|
+
*/
|
|
17
|
+
export declare function isUUID(str: string): boolean;
|
|
18
|
+
/**
|
|
19
|
+
* Checks if a string is a valid URL.
|
|
20
|
+
*
|
|
21
|
+
* @param {string} str - The input string.
|
|
22
|
+
* @returns {boolean} True if valid URL, else false.
|
|
23
|
+
*/
|
|
24
|
+
export declare function isURL(str: string): boolean;
|
|
25
|
+
/**
|
|
26
|
+
* Checks if a string is a valid international phone number (E.164 or common patterns).
|
|
27
|
+
*
|
|
28
|
+
* @param {string} str - The input string.
|
|
29
|
+
* @returns {boolean} True if looks like a phone number.
|
|
30
|
+
*/
|
|
31
|
+
export declare function isPhone(str: string): boolean;
|
|
32
|
+
/**
|
|
33
|
+
* Checks if a string is strictly alphanumeric (letters/numbers only).
|
|
34
|
+
*
|
|
35
|
+
* @param {string} str - The input string.
|
|
36
|
+
* @returns {boolean} True if alphanumeric.
|
|
37
|
+
*/
|
|
38
|
+
export declare function isAlphanumeric(str: string): boolean;
|
|
39
|
+
/**
|
|
40
|
+
* Checks if a string or number can be safely parsed to a number.
|
|
41
|
+
*
|
|
42
|
+
* @param {string | number} value - The value to check.
|
|
43
|
+
* @returns {boolean} True if the value is numeric.
|
|
44
|
+
*/
|
|
45
|
+
export declare function isNumeric(value: string | number): boolean;
|
|
46
|
+
/**
|
|
47
|
+
* Checks if a string is a valid hex color code (e.g. #FFF or #FFFFFF).
|
|
48
|
+
*
|
|
49
|
+
* @param {string} str - Input string.
|
|
50
|
+
* @returns {boolean}
|
|
51
|
+
*/
|
|
52
|
+
export declare function isHexColor(str: string): boolean;
|
|
53
|
+
/**
|
|
54
|
+
* Checks if a string is a valid date string.
|
|
55
|
+
*
|
|
56
|
+
* @param {string} str - Input string.
|
|
57
|
+
* @returns {boolean}
|
|
58
|
+
*/
|
|
59
|
+
export declare function isISODate(str: string): boolean;
|
|
60
|
+
//# sourceMappingURL=validate.utils.d.ts.map
|
|
@@ -0,0 +1,115 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Collection of common validation helpers for strings, numbers, email, UUID, etc.
|
|
4
|
+
*/
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.isEmail = isEmail;
|
|
7
|
+
exports.isUUID = isUUID;
|
|
8
|
+
exports.isURL = isURL;
|
|
9
|
+
exports.isPhone = isPhone;
|
|
10
|
+
exports.isAlphanumeric = isAlphanumeric;
|
|
11
|
+
exports.isNumeric = isNumeric;
|
|
12
|
+
exports.isHexColor = isHexColor;
|
|
13
|
+
exports.isISODate = isISODate;
|
|
14
|
+
/**
|
|
15
|
+
* Checks if a string is a valid email address.
|
|
16
|
+
*
|
|
17
|
+
* @param {string} str - The input string.
|
|
18
|
+
* @returns {boolean} True if valid email, else false.
|
|
19
|
+
*/
|
|
20
|
+
function isEmail(str) {
|
|
21
|
+
if (!/^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(str))
|
|
22
|
+
return false;
|
|
23
|
+
// Additional checks
|
|
24
|
+
const [local, domain] = str.split("@");
|
|
25
|
+
if (!local || !domain)
|
|
26
|
+
return false;
|
|
27
|
+
// Disallow consecutive dots in local or domain part
|
|
28
|
+
if (local.includes("..") || domain.includes(".."))
|
|
29
|
+
return false;
|
|
30
|
+
return true;
|
|
31
|
+
}
|
|
32
|
+
/**
|
|
33
|
+
* Checks if a string is a valid UUID (versions 1-5).
|
|
34
|
+
*
|
|
35
|
+
* @param {string} str - The input string.
|
|
36
|
+
* @returns {boolean} True if valid UUID, else false.
|
|
37
|
+
*/
|
|
38
|
+
function isUUID(str) {
|
|
39
|
+
return /^[0-9a-f]{8}-[0-9a-f]{4}-[1-5][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i.test(str);
|
|
40
|
+
}
|
|
41
|
+
/**
|
|
42
|
+
* Checks if a string is a valid URL.
|
|
43
|
+
*
|
|
44
|
+
* @param {string} str - The input string.
|
|
45
|
+
* @returns {boolean} True if valid URL, else false.
|
|
46
|
+
*/
|
|
47
|
+
function isURL(str) {
|
|
48
|
+
try {
|
|
49
|
+
new URL(str);
|
|
50
|
+
return true;
|
|
51
|
+
}
|
|
52
|
+
catch (_a) {
|
|
53
|
+
return false;
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
/**
|
|
57
|
+
* Checks if a string is a valid international phone number (E.164 or common patterns).
|
|
58
|
+
*
|
|
59
|
+
* @param {string} str - The input string.
|
|
60
|
+
* @returns {boolean} True if looks like a phone number.
|
|
61
|
+
*/
|
|
62
|
+
function isPhone(str) {
|
|
63
|
+
if (typeof str !== "string")
|
|
64
|
+
return false;
|
|
65
|
+
// Strip non-digit characters to count total digits
|
|
66
|
+
const digitsOnly = str.replace(/\D/g, "");
|
|
67
|
+
if (digitsOnly.length < 6 || digitsOnly.length > 15)
|
|
68
|
+
return false;
|
|
69
|
+
// Accept typical phone characters: +, digits, space, -, (, )
|
|
70
|
+
return /^[+]?[\d\s().-]+$/.test(str);
|
|
71
|
+
}
|
|
72
|
+
/**
|
|
73
|
+
* Checks if a string is strictly alphanumeric (letters/numbers only).
|
|
74
|
+
*
|
|
75
|
+
* @param {string} str - The input string.
|
|
76
|
+
* @returns {boolean} True if alphanumeric.
|
|
77
|
+
*/
|
|
78
|
+
function isAlphanumeric(str) {
|
|
79
|
+
return /^[a-z0-9]+$/i.test(str);
|
|
80
|
+
}
|
|
81
|
+
/**
|
|
82
|
+
* Checks if a string or number can be safely parsed to a number.
|
|
83
|
+
*
|
|
84
|
+
* @param {string | number} value - The value to check.
|
|
85
|
+
* @returns {boolean} True if the value is numeric.
|
|
86
|
+
*/
|
|
87
|
+
function isNumeric(value) {
|
|
88
|
+
if (typeof value === "string" && value.trim() === "")
|
|
89
|
+
return false;
|
|
90
|
+
const num = typeof value === "number" ? value : Number(value);
|
|
91
|
+
return typeof num === "number" && isFinite(num);
|
|
92
|
+
}
|
|
93
|
+
/**
|
|
94
|
+
* Checks if a string is a valid hex color code (e.g. #FFF or #FFFFFF).
|
|
95
|
+
*
|
|
96
|
+
* @param {string} str - Input string.
|
|
97
|
+
* @returns {boolean}
|
|
98
|
+
*/
|
|
99
|
+
function isHexColor(str) {
|
|
100
|
+
return /^#([a-f0-9]{6}|[a-f0-9]{3})$/i.test(str);
|
|
101
|
+
}
|
|
102
|
+
/**
|
|
103
|
+
* Checks if a string is a valid date string.
|
|
104
|
+
*
|
|
105
|
+
* @param {string} str - Input string.
|
|
106
|
+
* @returns {boolean}
|
|
107
|
+
*/
|
|
108
|
+
function isISODate(str) {
|
|
109
|
+
const isoRegex = /^\d{4}-\d{2}-\d{2}(T\d{2}:\d{2}:\d{2}(\.\d+)?(Z|[+-]\d{2}:\d{2})?)?$/;
|
|
110
|
+
if (!isoRegex.test(str))
|
|
111
|
+
return false;
|
|
112
|
+
const date = new Date(str);
|
|
113
|
+
return (!isNaN(date.getTime()) && date.toISOString().startsWith(str.slice(0, 10)));
|
|
114
|
+
}
|
|
115
|
+
//# sourceMappingURL=validate.utils.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"validate.utils.js","sourceRoot":"","sources":["../../../src/utils/validate.utils.ts"],"names":[],"mappings":";AAAA;;GAEG;;AAQH,0BAWC;AAQD,wBAIC;AAQD,sBAOC;AAQD,0BASC;AAQD,wCAEC;AAQD,8BAIC;AAQD,gCAEC;AAQD,8BAUC;AA/GD;;;;;GAKG;AACH,SAAgB,OAAO,CAAC,GAAW;IACjC,IAAI,CAAC,4BAA4B,CAAC,IAAI,CAAC,GAAG,CAAC;QAAE,OAAO,KAAK,CAAC;IAE1D,oBAAoB;IACpB,MAAM,CAAC,KAAK,EAAE,MAAM,CAAC,GAAG,GAAG,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;IACvC,IAAI,CAAC,KAAK,IAAI,CAAC,MAAM;QAAE,OAAO,KAAK,CAAC;IAEpC,oDAAoD;IACpD,IAAI,KAAK,CAAC,QAAQ,CAAC,IAAI,CAAC,IAAI,MAAM,CAAC,QAAQ,CAAC,IAAI,CAAC;QAAE,OAAO,KAAK,CAAC;IAEhE,OAAO,IAAI,CAAC;AACd,CAAC;AAED;;;;;GAKG;AACH,SAAgB,MAAM,CAAC,GAAW;IAChC,OAAO,4EAA4E,CAAC,IAAI,CACtF,GAAG,CACJ,CAAC;AACJ,CAAC;AAED;;;;;GAKG;AACH,SAAgB,KAAK,CAAC,GAAW;IAC/B,IAAI,CAAC;QACH,IAAI,GAAG,CAAC,GAAG,CAAC,CAAC;QACb,OAAO,IAAI,CAAC;IACd,CAAC;IAAC,WAAM,CAAC;QACP,OAAO,KAAK,CAAC;IACf,CAAC;AACH,CAAC;AAED;;;;;GAKG;AACH,SAAgB,OAAO,CAAC,GAAW;IACjC,IAAI,OAAO,GAAG,KAAK,QAAQ;QAAE,OAAO,KAAK,CAAC;IAE1C,mDAAmD;IACnD,MAAM,UAAU,GAAG,GAAG,CAAC,OAAO,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC;IAC1C,IAAI,UAAU,CAAC,MAAM,GAAG,CAAC,IAAI,UAAU,CAAC,MAAM,GAAG,EAAE;QAAE,OAAO,KAAK,CAAC;IAElE,6DAA6D;IAC7D,OAAO,mBAAmB,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;AACvC,CAAC;AAED;;;;;GAKG;AACH,SAAgB,cAAc,CAAC,GAAW;IACxC,OAAO,cAAc,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;AAClC,CAAC;AAED;;;;;GAKG;AACH,SAAgB,SAAS,CAAC,KAAsB;IAC9C,IAAI,OAAO,KAAK,KAAK,QAAQ,IAAI,KAAK,CAAC,IAAI,EAAE,KAAK,EAAE;QAAE,OAAO,KAAK,CAAC;IACnE,MAAM,GAAG,GAAG,OAAO,KAAK,KAAK,QAAQ,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;IAC9D,OAAO,OAAO,GAAG,KAAK,QAAQ,IAAI,QAAQ,CAAC,GAAG,CAAC,CAAC;AAClD,CAAC;AAED;;;;;GAKG;AACH,SAAgB,UAAU,CAAC,GAAW;IACpC,OAAO,+BAA+B,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;AACnD,CAAC;AAED;;;;;GAKG;AACH,SAAgB,SAAS,CAAC,GAAW;IACnC,MAAM,QAAQ,GACZ,sEAAsE,CAAC;IAEzE,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,GAAG,CAAC;QAAE,OAAO,KAAK,CAAC;IAEtC,MAAM,IAAI,GAAG,IAAI,IAAI,CAAC,GAAG,CAAC,CAAC;IAC3B,OAAO,CACL,CAAC,KAAK,CAAC,IAAI,CAAC,OAAO,EAAE,CAAC,IAAI,IAAI,CAAC,WAAW,EAAE,CAAC,UAAU,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAC1E,CAAC;AACJ,CAAC","sourcesContent":["/**\n * Collection of common validation helpers for strings, numbers, email, UUID, etc.\n */\n\n/**\n * Checks if a string is a valid email address.\n *\n * @param {string} str - The input string.\n * @returns {boolean} True if valid email, else false.\n */\nexport function isEmail(str: string): boolean {\n if (!/^[^\\s@]+@[^\\s@]+\\.[^\\s@]+$/.test(str)) return false;\n\n // Additional checks\n const [local, domain] = str.split(\"@\");\n if (!local || !domain) return false;\n\n // Disallow consecutive dots in local or domain part\n if (local.includes(\"..\") || domain.includes(\"..\")) return false;\n\n return true;\n}\n\n/**\n * Checks if a string is a valid UUID (versions 1-5).\n *\n * @param {string} str - The input string.\n * @returns {boolean} True if valid UUID, else false.\n */\nexport function isUUID(str: string): boolean {\n return /^[0-9a-f]{8}-[0-9a-f]{4}-[1-5][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i.test(\n str,\n );\n}\n\n/**\n * Checks if a string is a valid URL.\n *\n * @param {string} str - The input string.\n * @returns {boolean} True if valid URL, else false.\n */\nexport function isURL(str: string): boolean {\n try {\n new URL(str);\n return true;\n } catch {\n return false;\n }\n}\n\n/**\n * Checks if a string is a valid international phone number (E.164 or common patterns).\n *\n * @param {string} str - The input string.\n * @returns {boolean} True if looks like a phone number.\n */\nexport function isPhone(str: string): boolean {\n if (typeof str !== \"string\") return false;\n\n // Strip non-digit characters to count total digits\n const digitsOnly = str.replace(/\\D/g, \"\");\n if (digitsOnly.length < 6 || digitsOnly.length > 15) return false;\n\n // Accept typical phone characters: +, digits, space, -, (, )\n return /^[+]?[\\d\\s().-]+$/.test(str);\n}\n\n/**\n * Checks if a string is strictly alphanumeric (letters/numbers only).\n *\n * @param {string} str - The input string.\n * @returns {boolean} True if alphanumeric.\n */\nexport function isAlphanumeric(str: string): boolean {\n return /^[a-z0-9]+$/i.test(str);\n}\n\n/**\n * Checks if a string or number can be safely parsed to a number.\n *\n * @param {string | number} value - The value to check.\n * @returns {boolean} True if the value is numeric.\n */\nexport function isNumeric(value: string | number): boolean {\n if (typeof value === \"string\" && value.trim() === \"\") return false;\n const num = typeof value === \"number\" ? value : Number(value);\n return typeof num === \"number\" && isFinite(num);\n}\n\n/**\n * Checks if a string is a valid hex color code (e.g. #FFF or #FFFFFF).\n *\n * @param {string} str - Input string.\n * @returns {boolean}\n */\nexport function isHexColor(str: string): boolean {\n return /^#([a-f0-9]{6}|[a-f0-9]{3})$/i.test(str);\n}\n\n/**\n * Checks if a string is a valid date string.\n *\n * @param {string} str - Input string.\n * @returns {boolean}\n */\nexport function isISODate(str: string): boolean {\n const isoRegex =\n /^\\d{4}-\\d{2}-\\d{2}(T\\d{2}:\\d{2}:\\d{2}(\\.\\d+)?(Z|[+-]\\d{2}:\\d{2})?)?$/;\n\n if (!isoRegex.test(str)) return false;\n\n const date = new Date(str);\n return (\n !isNaN(date.getTime()) && date.toISOString().startsWith(str.slice(0, 10))\n );\n}\n"]}
|