@catbee/utils 0.0.1 → 0.0.3
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/README.md +303 -107
- package/build/esm/config.d.ts +13 -1
- package/build/esm/config.js +16 -4
- package/build/esm/config.js.map +1 -1
- package/build/esm/index.d.ts +20 -18
- package/build/esm/index.js +20 -18
- package/build/esm/index.js.map +1 -1
- package/build/esm/types/api-response.d.ts +83 -1
- package/build/esm/types/api-response.js.map +1 -1
- package/build/esm/utils/array.utils.d.ts +65 -2
- package/build/esm/utils/array.utils.js +147 -20
- package/build/esm/utils/array.utils.js.map +1 -1
- package/build/esm/utils/async.utils.d.ts +56 -1
- package/build/esm/utils/async.utils.js +166 -11
- package/build/esm/utils/async.utils.js.map +1 -1
- package/build/esm/utils/cache.utils.d.ts +67 -4
- package/build/esm/utils/cache.utils.js +210 -28
- package/build/esm/utils/cache.utils.js.map +1 -1
- package/build/esm/utils/context-store.utils.d.ts +102 -1
- package/build/esm/utils/context-store.utils.js +185 -3
- package/build/esm/utils/context-store.utils.js.map +1 -1
- package/build/esm/utils/crypto.utils.d.ts +110 -8
- package/build/esm/utils/crypto.utils.js +298 -23
- package/build/esm/utils/crypto.utils.js.map +1 -1
- package/build/esm/utils/decorators.utils.d.ts +40 -0
- package/build/esm/utils/decorators.utils.js +312 -0
- package/build/esm/utils/decorators.utils.js.map +1 -0
- package/build/esm/utils/dir.utils.d.ts +122 -1
- package/build/esm/utils/dir.utils.js +578 -3
- package/build/esm/utils/dir.utils.js.map +1 -1
- package/build/esm/utils/env.utils.d.ts +83 -0
- package/build/esm/utils/env.utils.js +235 -6
- package/build/esm/utils/env.utils.js.map +1 -1
- package/build/esm/utils/exception.utils.d.ts +117 -1
- package/build/esm/utils/exception.utils.js +331 -12
- package/build/esm/utils/exception.utils.js.map +1 -1
- package/build/esm/utils/fs.utils.d.ts +132 -0
- package/build/esm/utils/fs.utils.js +421 -4
- package/build/esm/utils/fs.utils.js.map +1 -1
- package/build/esm/utils/http-status-codes.d.ts +87 -178
- package/build/esm/utils/http-status-codes.js +92 -178
- package/build/esm/utils/http-status-codes.js.map +1 -1
- package/build/esm/utils/id.utils.d.ts +11 -10
- package/build/esm/utils/id.utils.js +30 -21
- package/build/esm/utils/id.utils.js.map +1 -1
- package/build/esm/utils/logger.utils.d.ts +35 -2
- package/build/esm/utils/logger.utils.js +68 -14
- package/build/esm/utils/logger.utils.js.map +1 -1
- package/build/esm/utils/middleware.utils.d.ts +73 -0
- package/build/esm/utils/middleware.utils.js +158 -0
- package/build/esm/utils/middleware.utils.js.map +1 -0
- package/build/esm/utils/obj.utils.d.ts +65 -3
- package/build/esm/utils/obj.utils.js +206 -18
- package/build/esm/utils/obj.utils.js.map +1 -1
- package/build/esm/utils/response.utils.d.ts +103 -2
- package/build/esm/utils/response.utils.js +156 -3
- package/build/esm/utils/response.utils.js.map +1 -1
- package/build/esm/utils/string.utils.d.ts +61 -5
- package/build/esm/utils/string.utils.js +109 -19
- package/build/esm/utils/string.utils.js.map +1 -1
- package/build/esm/utils/url.utils.d.ts +117 -0
- package/build/esm/utils/url.utils.js +287 -2
- package/build/esm/utils/url.utils.js.map +1 -1
- package/build/esm/utils/validate.utils.d.ts +110 -0
- package/build/esm/utils/validate.utils.js +190 -8
- package/build/esm/utils/validate.utils.js.map +1 -1
- package/build/esnext/config.d.ts +13 -1
- package/build/esnext/config.js +16 -4
- package/build/esnext/config.js.map +1 -1
- package/build/esnext/index.d.ts +20 -18
- package/build/esnext/index.js +20 -18
- package/build/esnext/index.js.map +1 -1
- package/build/esnext/types/api-response.d.ts +83 -1
- package/build/esnext/types/api-response.js.map +1 -1
- package/build/esnext/utils/array.utils.d.ts +65 -2
- package/build/esnext/utils/array.utils.js +140 -21
- package/build/esnext/utils/array.utils.js.map +1 -1
- package/build/esnext/utils/async.utils.d.ts +56 -1
- package/build/esnext/utils/async.utils.js +130 -14
- package/build/esnext/utils/async.utils.js.map +1 -1
- package/build/esnext/utils/cache.utils.d.ts +67 -4
- package/build/esnext/utils/cache.utils.js +137 -9
- package/build/esnext/utils/cache.utils.js.map +1 -1
- package/build/esnext/utils/context-store.utils.d.ts +102 -1
- package/build/esnext/utils/context-store.utils.js +171 -3
- package/build/esnext/utils/context-store.utils.js.map +1 -1
- package/build/esnext/utils/crypto.utils.d.ts +110 -8
- package/build/esnext/utils/crypto.utils.js +199 -19
- package/build/esnext/utils/crypto.utils.js.map +1 -1
- package/build/esnext/utils/decorators.utils.d.ts +40 -0
- package/build/esnext/utils/decorators.utils.js +155 -0
- package/build/esnext/utils/decorators.utils.js.map +1 -0
- package/build/esnext/utils/dir.utils.d.ts +122 -1
- package/build/esnext/utils/dir.utils.js +307 -3
- package/build/esnext/utils/dir.utils.js.map +1 -1
- package/build/esnext/utils/env.utils.d.ts +83 -0
- package/build/esnext/utils/env.utils.js +191 -8
- package/build/esnext/utils/env.utils.js.map +1 -1
- package/build/esnext/utils/exception.utils.d.ts +117 -1
- package/build/esnext/utils/exception.utils.js +222 -12
- package/build/esnext/utils/exception.utils.js.map +1 -1
- package/build/esnext/utils/fs.utils.d.ts +132 -0
- package/build/esnext/utils/fs.utils.js +268 -4
- package/build/esnext/utils/fs.utils.js.map +1 -1
- package/build/esnext/utils/http-status-codes.d.ts +87 -178
- package/build/esnext/utils/http-status-codes.js +92 -178
- package/build/esnext/utils/http-status-codes.js.map +1 -1
- package/build/esnext/utils/id.utils.d.ts +11 -10
- package/build/esnext/utils/id.utils.js +28 -20
- package/build/esnext/utils/id.utils.js.map +1 -1
- package/build/esnext/utils/logger.utils.d.ts +35 -2
- package/build/esnext/utils/logger.utils.js +56 -14
- package/build/esnext/utils/logger.utils.js.map +1 -1
- package/build/esnext/utils/middleware.utils.d.ts +73 -0
- package/build/esnext/utils/middleware.utils.js +157 -0
- package/build/esnext/utils/middleware.utils.js.map +1 -0
- package/build/esnext/utils/obj.utils.d.ts +65 -3
- package/build/esnext/utils/obj.utils.js +169 -14
- package/build/esnext/utils/obj.utils.js.map +1 -1
- package/build/esnext/utils/response.utils.d.ts +103 -2
- package/build/esnext/utils/response.utils.js +141 -3
- package/build/esnext/utils/response.utils.js.map +1 -1
- package/build/esnext/utils/string.utils.d.ts +61 -5
- package/build/esnext/utils/string.utils.js +110 -14
- package/build/esnext/utils/string.utils.js.map +1 -1
- package/build/esnext/utils/url.utils.d.ts +117 -0
- package/build/esnext/utils/url.utils.js +248 -2
- package/build/esnext/utils/url.utils.js.map +1 -1
- package/build/esnext/utils/validate.utils.d.ts +110 -0
- package/build/esnext/utils/validate.utils.js +190 -8
- package/build/esnext/utils/validate.utils.js.map +1 -1
- package/build/src/config.d.ts +13 -1
- package/build/src/config.js +15 -3
- package/build/src/config.js.map +1 -1
- package/build/src/index.d.ts +20 -18
- package/build/src/index.js +2 -0
- package/build/src/index.js.map +1 -1
- package/build/src/types/api-response.d.ts +83 -1
- package/build/src/types/api-response.js.map +1 -1
- package/build/src/utils/array.utils.d.ts +65 -2
- package/build/src/utils/array.utils.js +147 -22
- package/build/src/utils/array.utils.js.map +1 -1
- package/build/src/utils/async.utils.d.ts +56 -1
- package/build/src/utils/async.utils.js +137 -17
- package/build/src/utils/async.utils.js.map +1 -1
- package/build/src/utils/cache.utils.d.ts +67 -4
- package/build/src/utils/cache.utils.js +137 -9
- package/build/src/utils/cache.utils.js.map +1 -1
- package/build/src/utils/context-store.utils.d.ts +102 -1
- package/build/src/utils/context-store.utils.js +173 -3
- package/build/src/utils/context-store.utils.js.map +1 -1
- package/build/src/utils/crypto.utils.d.ts +110 -8
- package/build/src/utils/crypto.utils.js +214 -27
- package/build/src/utils/crypto.utils.js.map +1 -1
- package/build/src/utils/decorators.utils.d.ts +40 -0
- package/build/src/utils/decorators.utils.js +165 -0
- package/build/src/utils/decorators.utils.js.map +1 -0
- package/build/src/utils/dir.utils.d.ts +122 -1
- package/build/src/utils/dir.utils.js +314 -0
- package/build/src/utils/dir.utils.js.map +1 -1
- package/build/src/utils/env.utils.d.ts +83 -0
- package/build/src/utils/env.utils.js +192 -9
- package/build/src/utils/env.utils.js.map +1 -1
- package/build/src/utils/exception.utils.d.ts +117 -1
- package/build/src/utils/exception.utils.js +233 -11
- package/build/src/utils/exception.utils.js.map +1 -1
- package/build/src/utils/fs.utils.d.ts +132 -0
- package/build/src/utils/fs.utils.js +281 -3
- package/build/src/utils/fs.utils.js.map +1 -1
- package/build/src/utils/http-status-codes.d.ts +87 -178
- package/build/src/utils/http-status-codes.js +92 -178
- package/build/src/utils/http-status-codes.js.map +1 -1
- package/build/src/utils/id.utils.d.ts +11 -10
- package/build/src/utils/id.utils.js +28 -20
- package/build/src/utils/id.utils.js.map +1 -1
- package/build/src/utils/logger.utils.d.ts +35 -2
- package/build/src/utils/logger.utils.js +56 -11
- package/build/src/utils/logger.utils.js.map +1 -1
- package/build/src/utils/middleware.utils.d.ts +73 -0
- package/build/src/utils/middleware.utils.js +163 -0
- package/build/src/utils/middleware.utils.js.map +1 -0
- package/build/src/utils/obj.utils.d.ts +65 -3
- package/build/src/utils/obj.utils.js +179 -18
- package/build/src/utils/obj.utils.js.map +1 -1
- package/build/src/utils/response.utils.d.ts +103 -2
- package/build/src/utils/response.utils.js +147 -2
- package/build/src/utils/response.utils.js.map +1 -1
- package/build/src/utils/string.utils.d.ts +61 -5
- package/build/src/utils/string.utils.js +122 -20
- package/build/src/utils/string.utils.js.map +1 -1
- package/build/src/utils/url.utils.d.ts +117 -0
- package/build/src/utils/url.utils.js +256 -1
- package/build/src/utils/url.utils.js.map +1 -1
- package/build/src/utils/validate.utils.d.ts +110 -0
- package/build/src/utils/validate.utils.js +204 -8
- package/build/src/utils/validate.utils.js.map +1 -1
- package/package.json +20 -12
|
@@ -2,6 +2,15 @@
|
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.appendQueryParams = appendQueryParams;
|
|
4
4
|
exports.parseQueryString = parseQueryString;
|
|
5
|
+
exports.isValidUrl = isValidUrl;
|
|
6
|
+
exports.getDomain = getDomain;
|
|
7
|
+
exports.joinPaths = joinPaths;
|
|
8
|
+
exports.normalizeUrl = normalizeUrl;
|
|
9
|
+
exports.createUrlBuilder = createUrlBuilder;
|
|
10
|
+
exports.extractQueryParams = extractQueryParams;
|
|
11
|
+
exports.removeQueryParams = removeQueryParams;
|
|
12
|
+
exports.getExtension = getExtension;
|
|
13
|
+
exports.parseTypedQueryParams = parseTypedQueryParams;
|
|
5
14
|
const url_1 = require("url");
|
|
6
15
|
/**
|
|
7
16
|
* Appends query parameters to a given URL.
|
|
@@ -32,8 +41,254 @@ function appendQueryParams(url, params) {
|
|
|
32
41
|
* // → { page: '1', limit: '10' }
|
|
33
42
|
*/
|
|
34
43
|
function parseQueryString(query) {
|
|
35
|
-
const cleanQuery = query.startsWith(
|
|
44
|
+
const cleanQuery = query.startsWith('?') ? query.slice(1) : query;
|
|
36
45
|
// Object.fromEntries guarantees string values in result
|
|
37
46
|
return Object.fromEntries(new url_1.URLSearchParams(cleanQuery));
|
|
38
47
|
}
|
|
48
|
+
/**
|
|
49
|
+
* Validates if a string is a valid URL.
|
|
50
|
+
*
|
|
51
|
+
* @param {string} url - The URL string to validate.
|
|
52
|
+
* @param {boolean} [requireHttps=false] - If true, requires the URL to use HTTPS.
|
|
53
|
+
* @returns {boolean} True if the URL is valid, false otherwise.
|
|
54
|
+
*/
|
|
55
|
+
function isValidUrl(url, requireHttps = false) {
|
|
56
|
+
try {
|
|
57
|
+
const parsedUrl = new url_1.URL(url);
|
|
58
|
+
if (!parsedUrl.protocol || !parsedUrl.hostname)
|
|
59
|
+
return false;
|
|
60
|
+
if (requireHttps && parsedUrl.protocol !== 'https:')
|
|
61
|
+
return false;
|
|
62
|
+
return true;
|
|
63
|
+
}
|
|
64
|
+
catch (_a) {
|
|
65
|
+
return false;
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
/**
|
|
69
|
+
* Extracts the domain name from a URL.
|
|
70
|
+
*
|
|
71
|
+
* @param {string} url - The URL to extract the domain from.
|
|
72
|
+
* @param {boolean} [removeSubdomains=false] - If true, removes subdomains (returns root domain only).
|
|
73
|
+
* @returns {string} The domain name.
|
|
74
|
+
*
|
|
75
|
+
* @example
|
|
76
|
+
* getDomain('https://api.example.com/path');
|
|
77
|
+
* // → 'api.example.com'
|
|
78
|
+
*
|
|
79
|
+
* getDomain('https://api.example.com/path', true);
|
|
80
|
+
* // → 'example.com'
|
|
81
|
+
*/
|
|
82
|
+
function getDomain(url, removeSubdomains = false) {
|
|
83
|
+
try {
|
|
84
|
+
const { hostname } = new url_1.URL(url);
|
|
85
|
+
if (!removeSubdomains) {
|
|
86
|
+
return hostname;
|
|
87
|
+
}
|
|
88
|
+
// Extract root domain (remove subdomains)
|
|
89
|
+
const parts = hostname.split('.');
|
|
90
|
+
if (parts.length <= 2)
|
|
91
|
+
return hostname;
|
|
92
|
+
// Handle special cases like co.in, com.au
|
|
93
|
+
const secondLevelDomains = ['co', 'com', 'org', 'net', 'gov', 'edu', 'ac'];
|
|
94
|
+
const sld = parts[parts.length - 2];
|
|
95
|
+
if (secondLevelDomains.includes(sld) && parts.length > 2) {
|
|
96
|
+
return parts.slice(-3).join('.');
|
|
97
|
+
}
|
|
98
|
+
return parts.slice(-2).join('.');
|
|
99
|
+
}
|
|
100
|
+
catch (_a) {
|
|
101
|
+
return '';
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
/**
|
|
105
|
+
* Joins URL paths properly handling slashes.
|
|
106
|
+
*
|
|
107
|
+
* @param {...string[]} segments - URL path segments to join.
|
|
108
|
+
* @returns {string} Joined URL path.
|
|
109
|
+
*
|
|
110
|
+
* @example
|
|
111
|
+
* joinPaths('https://example.com/', '/api/', '/users');
|
|
112
|
+
* // → 'https://example.com/api/users'
|
|
113
|
+
*/
|
|
114
|
+
function joinPaths(...segments) {
|
|
115
|
+
let result = segments
|
|
116
|
+
.filter(s => s !== undefined && s !== null)
|
|
117
|
+
.map((segment, index) => {
|
|
118
|
+
if (index === 0)
|
|
119
|
+
return segment.replace(/\/+$/, '');
|
|
120
|
+
return segment.replace(/^\/+|\/+$/g, '');
|
|
121
|
+
})
|
|
122
|
+
.filter(Boolean)
|
|
123
|
+
.join('/');
|
|
124
|
+
if (segments[0] === '' && !result.startsWith('/'))
|
|
125
|
+
result = '/' + result;
|
|
126
|
+
return result;
|
|
127
|
+
}
|
|
128
|
+
/**
|
|
129
|
+
* Normalizes a URL by resolving relative paths, handling protocol-relative URLs, etc.
|
|
130
|
+
*
|
|
131
|
+
* @param {string} url - The URL to normalize.
|
|
132
|
+
* @param {string} [base] - Optional base URL for resolving relative URLs.
|
|
133
|
+
* @returns {string} Normalized URL.
|
|
134
|
+
*
|
|
135
|
+
* @example
|
|
136
|
+
* normalizeUrl('HTTP://Example.COM/foo/../bar');
|
|
137
|
+
* // → 'http://example.com/bar'
|
|
138
|
+
*/
|
|
139
|
+
function normalizeUrl(url, base) {
|
|
140
|
+
try {
|
|
141
|
+
// Handle protocol-relative URLs
|
|
142
|
+
if (url.startsWith('//')) {
|
|
143
|
+
url = `https:${url}`;
|
|
144
|
+
}
|
|
145
|
+
// Resolve relative URLs against a base
|
|
146
|
+
const parsedUrl = base ? new url_1.URL(url, base) : new url_1.URL(url);
|
|
147
|
+
// Normalize
|
|
148
|
+
parsedUrl.pathname = parsedUrl.pathname.replace(/\/+/g, '/'); // Collapse multiple slashes
|
|
149
|
+
parsedUrl.pathname = parsedUrl.pathname.replace(/\/+$/, ''); // Remove trailing slash
|
|
150
|
+
parsedUrl.hostname = parsedUrl.hostname.toLowerCase();
|
|
151
|
+
return parsedUrl.toString();
|
|
152
|
+
}
|
|
153
|
+
catch (_a) {
|
|
154
|
+
return url; // Return original if invalid
|
|
155
|
+
}
|
|
156
|
+
}
|
|
157
|
+
/**
|
|
158
|
+
* Creates a URL builder for constructing URLs with a base URL.
|
|
159
|
+
*
|
|
160
|
+
* @param {string} baseUrl - The base URL to build upon.
|
|
161
|
+
* @returns {Object} URL builder methods.
|
|
162
|
+
*
|
|
163
|
+
* @example
|
|
164
|
+
* const api = createUrlBuilder('https://api.example.com');
|
|
165
|
+
* api.path('/users', { active: true });
|
|
166
|
+
* // → 'https://api.example.com/users?active=true'
|
|
167
|
+
*/
|
|
168
|
+
function createUrlBuilder(baseUrl) {
|
|
169
|
+
return {
|
|
170
|
+
/**
|
|
171
|
+
* Creates a full URL with the given path and query parameters.
|
|
172
|
+
*
|
|
173
|
+
* @param {string} path - The path to append to the base URL.
|
|
174
|
+
* @param {Record<string, any>} [params] - Query parameters to add.
|
|
175
|
+
* @returns {string} The complete URL.
|
|
176
|
+
*/
|
|
177
|
+
path(path, params) {
|
|
178
|
+
const url = joinPaths(baseUrl, path);
|
|
179
|
+
return params ? appendQueryParams(url, params) : url;
|
|
180
|
+
},
|
|
181
|
+
/**
|
|
182
|
+
* Creates a full URL with query parameters but no additional path.
|
|
183
|
+
*
|
|
184
|
+
* @param {Record<string, any>} params - Query parameters to add.
|
|
185
|
+
* @returns {string} The complete URL with query parameters.
|
|
186
|
+
*/
|
|
187
|
+
query(params) {
|
|
188
|
+
return appendQueryParams(baseUrl, params);
|
|
189
|
+
}
|
|
190
|
+
};
|
|
191
|
+
}
|
|
192
|
+
/**
|
|
193
|
+
* Extracts specific query parameters from a URL.
|
|
194
|
+
*
|
|
195
|
+
* @param {string} url - The URL to extract parameters from.
|
|
196
|
+
* @param {string[]} paramNames - Names of parameters to extract.
|
|
197
|
+
* @returns {Record<string, string>} Object containing the extracted parameters.
|
|
198
|
+
*/
|
|
199
|
+
function extractQueryParams(url, paramNames) {
|
|
200
|
+
try {
|
|
201
|
+
const parsedUrl = new url_1.URL(url);
|
|
202
|
+
const result = {};
|
|
203
|
+
for (const name of paramNames) {
|
|
204
|
+
const value = parsedUrl.searchParams.get(name);
|
|
205
|
+
if (value !== null) {
|
|
206
|
+
result[name] = value;
|
|
207
|
+
}
|
|
208
|
+
}
|
|
209
|
+
return result;
|
|
210
|
+
}
|
|
211
|
+
catch (_a) {
|
|
212
|
+
return {};
|
|
213
|
+
}
|
|
214
|
+
}
|
|
215
|
+
/**
|
|
216
|
+
* Removes specified query parameters from a URL.
|
|
217
|
+
*
|
|
218
|
+
* @param {string} url - The URL to modify.
|
|
219
|
+
* @param {string[]} paramsToRemove - Names of parameters to remove.
|
|
220
|
+
* @returns {string} URL with parameters removed.
|
|
221
|
+
*/
|
|
222
|
+
function removeQueryParams(url, paramsToRemove) {
|
|
223
|
+
try {
|
|
224
|
+
const parsedUrl = new url_1.URL(url);
|
|
225
|
+
for (const param of paramsToRemove) {
|
|
226
|
+
parsedUrl.searchParams.delete(param);
|
|
227
|
+
}
|
|
228
|
+
return parsedUrl.toString();
|
|
229
|
+
}
|
|
230
|
+
catch (_a) {
|
|
231
|
+
return url;
|
|
232
|
+
}
|
|
233
|
+
}
|
|
234
|
+
/**
|
|
235
|
+
* Gets the file extension from a URL path.
|
|
236
|
+
*
|
|
237
|
+
* @param {string} url - The URL to examine.
|
|
238
|
+
* @returns {string} The file extension (without dot) or empty string if none found.
|
|
239
|
+
*
|
|
240
|
+
* @example
|
|
241
|
+
* getExtension('https://example.com/document.pdf?v=1');
|
|
242
|
+
* // → 'pdf'
|
|
243
|
+
*/
|
|
244
|
+
function getExtension(url) {
|
|
245
|
+
try {
|
|
246
|
+
const { pathname } = new url_1.URL(url);
|
|
247
|
+
const match = pathname.match(/\.([^./\\?#]+)$/);
|
|
248
|
+
return match ? match[1].toLowerCase() : '';
|
|
249
|
+
}
|
|
250
|
+
catch (_a) {
|
|
251
|
+
// If URL parsing fails, try a simpler approach
|
|
252
|
+
const match = url.match(/\.([^./\\?#]+)$/);
|
|
253
|
+
return match ? match[1].toLowerCase() : '';
|
|
254
|
+
}
|
|
255
|
+
}
|
|
256
|
+
/**
|
|
257
|
+
* Parses URL query parameters into a strongly-typed object.
|
|
258
|
+
*
|
|
259
|
+
* @template T Expected type of the query parameters
|
|
260
|
+
* @param {string} url - The URL to parse.
|
|
261
|
+
* @param {Record<keyof T, (val: string) => any>} [converters] - Type converters for params.
|
|
262
|
+
* @returns {Partial<T>} Typed query parameters.
|
|
263
|
+
*
|
|
264
|
+
* @example
|
|
265
|
+
* parseTypedQueryParams<{page: number, q: string}>('https://example.com?page=2&q=test', {
|
|
266
|
+
* page: Number,
|
|
267
|
+
* q: String
|
|
268
|
+
* });
|
|
269
|
+
* // → { page: 2, q: 'test' }
|
|
270
|
+
*/
|
|
271
|
+
function parseTypedQueryParams(url, converters) {
|
|
272
|
+
try {
|
|
273
|
+
const { searchParams } = new url_1.URL(url);
|
|
274
|
+
const result = {};
|
|
275
|
+
for (const [key, value] of searchParams.entries()) {
|
|
276
|
+
if (converters && key in converters) {
|
|
277
|
+
try {
|
|
278
|
+
result[key] = converters[key](value);
|
|
279
|
+
}
|
|
280
|
+
catch (_a) {
|
|
281
|
+
// Skip on conversion error
|
|
282
|
+
}
|
|
283
|
+
}
|
|
284
|
+
else {
|
|
285
|
+
result[key] = value;
|
|
286
|
+
}
|
|
287
|
+
}
|
|
288
|
+
return result;
|
|
289
|
+
}
|
|
290
|
+
catch (_b) {
|
|
291
|
+
return {};
|
|
292
|
+
}
|
|
293
|
+
}
|
|
39
294
|
//# sourceMappingURL=url.utils.js.map
|
|
@@ -1 +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"]}
|
|
1
|
+
{"version":3,"file":"url.utils.js","sourceRoot":"","sources":["../../../src/utils/url.utils.ts"],"names":[],"mappings":"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","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(url: string, params: Record<string, string | number>): 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<string, string>;\n}\n\n/**\n * Validates if a string is a valid URL.\n *\n * @param {string} url - The URL string to validate.\n * @param {boolean} [requireHttps=false] - If true, requires the URL to use HTTPS.\n * @returns {boolean} True if the URL is valid, false otherwise.\n */\nexport function isValidUrl(url: string, requireHttps: boolean = false): boolean {\n try {\n const parsedUrl = new URL(url);\n if (!parsedUrl.protocol || !parsedUrl.hostname) return false;\n if (requireHttps && parsedUrl.protocol !== 'https:') return false;\n return true;\n } catch {\n return false;\n }\n}\n\n/**\n * Extracts the domain name from a URL.\n *\n * @param {string} url - The URL to extract the domain from.\n * @param {boolean} [removeSubdomains=false] - If true, removes subdomains (returns root domain only).\n * @returns {string} The domain name.\n *\n * @example\n * getDomain('https://api.example.com/path');\n * // → 'api.example.com'\n *\n * getDomain('https://api.example.com/path', true);\n * // → 'example.com'\n */\nexport function getDomain(url: string, removeSubdomains: boolean = false): string {\n try {\n const { hostname } = new URL(url);\n\n if (!removeSubdomains) {\n return hostname;\n }\n\n // Extract root domain (remove subdomains)\n const parts = hostname.split('.');\n if (parts.length <= 2) return hostname;\n\n // Handle special cases like co.in, com.au\n const secondLevelDomains = ['co', 'com', 'org', 'net', 'gov', 'edu', 'ac'];\n const sld = parts[parts.length - 2];\n\n if (secondLevelDomains.includes(sld) && parts.length > 2) {\n return parts.slice(-3).join('.');\n }\n\n return parts.slice(-2).join('.');\n } catch {\n return '';\n }\n}\n\n/**\n * Joins URL paths properly handling slashes.\n *\n * @param {...string[]} segments - URL path segments to join.\n * @returns {string} Joined URL path.\n *\n * @example\n * joinPaths('https://example.com/', '/api/', '/users');\n * // → 'https://example.com/api/users'\n */\nexport function joinPaths(...segments: string[]): string {\n let result = segments\n .filter(s => s !== undefined && s !== null)\n .map((segment, index) => {\n if (index === 0) return segment.replace(/\\/+$/, '');\n return segment.replace(/^\\/+|\\/+$/g, '');\n })\n .filter(Boolean)\n .join('/');\n if (segments[0] === '' && !result.startsWith('/')) result = '/' + result;\n return result;\n}\n\n/**\n * Normalizes a URL by resolving relative paths, handling protocol-relative URLs, etc.\n *\n * @param {string} url - The URL to normalize.\n * @param {string} [base] - Optional base URL for resolving relative URLs.\n * @returns {string} Normalized URL.\n *\n * @example\n * normalizeUrl('HTTP://Example.COM/foo/../bar');\n * // → 'http://example.com/bar'\n */\nexport function normalizeUrl(url: string, base?: string): string {\n try {\n // Handle protocol-relative URLs\n if (url.startsWith('//')) {\n url = `https:${url}`;\n }\n\n // Resolve relative URLs against a base\n const parsedUrl = base ? new URL(url, base) : new URL(url);\n\n // Normalize\n parsedUrl.pathname = parsedUrl.pathname.replace(/\\/+/g, '/'); // Collapse multiple slashes\n parsedUrl.pathname = parsedUrl.pathname.replace(/\\/+$/, ''); // Remove trailing slash\n parsedUrl.hostname = parsedUrl.hostname.toLowerCase();\n\n return parsedUrl.toString();\n } catch {\n return url; // Return original if invalid\n }\n}\n\n/**\n * Creates a URL builder for constructing URLs with a base URL.\n *\n * @param {string} baseUrl - The base URL to build upon.\n * @returns {Object} URL builder methods.\n *\n * @example\n * const api = createUrlBuilder('https://api.example.com');\n * api.path('/users', { active: true });\n * // → 'https://api.example.com/users?active=true'\n */\nexport function createUrlBuilder(baseUrl: string) {\n return {\n /**\n * Creates a full URL with the given path and query parameters.\n *\n * @param {string} path - The path to append to the base URL.\n * @param {Record<string, any>} [params] - Query parameters to add.\n * @returns {string} The complete URL.\n */\n path(path: string, params?: Record<string, any>): string {\n const url = joinPaths(baseUrl, path);\n return params ? appendQueryParams(url, params as Record<string, string | number>) : url;\n },\n\n /**\n * Creates a full URL with query parameters but no additional path.\n *\n * @param {Record<string, any>} params - Query parameters to add.\n * @returns {string} The complete URL with query parameters.\n */\n query(params: Record<string, any>): string {\n return appendQueryParams(baseUrl, params as Record<string, string | number>);\n }\n };\n}\n\n/**\n * Extracts specific query parameters from a URL.\n *\n * @param {string} url - The URL to extract parameters from.\n * @param {string[]} paramNames - Names of parameters to extract.\n * @returns {Record<string, string>} Object containing the extracted parameters.\n */\nexport function extractQueryParams(url: string, paramNames: string[]): Record<string, string> {\n try {\n const parsedUrl = new URL(url);\n const result: Record<string, string> = {};\n\n for (const name of paramNames) {\n const value = parsedUrl.searchParams.get(name);\n if (value !== null) {\n result[name] = value;\n }\n }\n\n return result;\n } catch {\n return {};\n }\n}\n\n/**\n * Removes specified query parameters from a URL.\n *\n * @param {string} url - The URL to modify.\n * @param {string[]} paramsToRemove - Names of parameters to remove.\n * @returns {string} URL with parameters removed.\n */\nexport function removeQueryParams(url: string, paramsToRemove: string[]): string {\n try {\n const parsedUrl = new URL(url);\n\n for (const param of paramsToRemove) {\n parsedUrl.searchParams.delete(param);\n }\n\n return parsedUrl.toString();\n } catch {\n return url;\n }\n}\n\n/**\n * Gets the file extension from a URL path.\n *\n * @param {string} url - The URL to examine.\n * @returns {string} The file extension (without dot) or empty string if none found.\n *\n * @example\n * getExtension('https://example.com/document.pdf?v=1');\n * // → 'pdf'\n */\nexport function getExtension(url: string): string {\n try {\n const { pathname } = new URL(url);\n const match = pathname.match(/\\.([^./\\\\?#]+)$/);\n return match ? match[1].toLowerCase() : '';\n } catch {\n // If URL parsing fails, try a simpler approach\n const match = url.match(/\\.([^./\\\\?#]+)$/);\n return match ? match[1].toLowerCase() : '';\n }\n}\n\n/**\n * Parses URL query parameters into a strongly-typed object.\n *\n * @template T Expected type of the query parameters\n * @param {string} url - The URL to parse.\n * @param {Record<keyof T, (val: string) => any>} [converters] - Type converters for params.\n * @returns {Partial<T>} Typed query parameters.\n *\n * @example\n * parseTypedQueryParams<{page: number, q: string}>('https://example.com?page=2&q=test', {\n * page: Number,\n * q: String\n * });\n * // → { page: 2, q: 'test' }\n */\nexport function parseTypedQueryParams<T extends Record<string, any>>(\n url: string,\n converters?: Record<keyof T, (val: string) => any>\n): Partial<T> {\n try {\n const { searchParams } = new URL(url);\n const result = {} as Partial<T>;\n\n for (const [key, value] of searchParams.entries()) {\n if (converters && key in converters) {\n try {\n result[key as keyof T] = converters[key as keyof T](value);\n } catch {\n // Skip on conversion error\n }\n } else {\n result[key as keyof T] = value as any;\n }\n }\n\n return result;\n } catch {\n return {};\n }\n}\n"]}
|
|
@@ -57,4 +57,114 @@ export declare function isHexColor(str: string): boolean;
|
|
|
57
57
|
* @returns {boolean}
|
|
58
58
|
*/
|
|
59
59
|
export declare function isISODate(str: string): boolean;
|
|
60
|
+
/**
|
|
61
|
+
* Checks if a string matches a specified length range.
|
|
62
|
+
*
|
|
63
|
+
* @param {string} str - The input string.
|
|
64
|
+
* @param {number} min - Minimum length (inclusive).
|
|
65
|
+
* @param {number} max - Maximum length (inclusive).
|
|
66
|
+
* @returns {boolean} True if string length is within range.
|
|
67
|
+
*/
|
|
68
|
+
export declare function isLengthBetween(str: string, min: number, max: number): boolean;
|
|
69
|
+
/**
|
|
70
|
+
* Validates that a number is between specified min and max values (inclusive).
|
|
71
|
+
*
|
|
72
|
+
* @param {number} value - The number to validate.
|
|
73
|
+
* @param {number} min - Minimum value.
|
|
74
|
+
* @param {number} max - Maximum value.
|
|
75
|
+
* @returns {boolean} True if number is within range.
|
|
76
|
+
*/
|
|
77
|
+
export declare function isNumberBetween(value: number, min: number, max: number): boolean;
|
|
78
|
+
/**
|
|
79
|
+
* Checks if a string contains only alphabetic characters.
|
|
80
|
+
*
|
|
81
|
+
* @param {string} str - The input string.
|
|
82
|
+
* @returns {boolean} True if alphabetic only.
|
|
83
|
+
*/
|
|
84
|
+
export declare function isAlpha(str: string): boolean;
|
|
85
|
+
/**
|
|
86
|
+
* Validates that a string contains at least one uppercase letter,
|
|
87
|
+
* one lowercase letter, one number, and one special character.
|
|
88
|
+
*
|
|
89
|
+
* @param {string} str - The input string.
|
|
90
|
+
* @returns {boolean} True if string meets password complexity requirements.
|
|
91
|
+
*/
|
|
92
|
+
export declare function isStrongPassword(str: string): boolean;
|
|
93
|
+
/**
|
|
94
|
+
* Checks if a string is a valid IPv4 address.
|
|
95
|
+
*
|
|
96
|
+
* @param {string} str - The input string.
|
|
97
|
+
* @returns {boolean} True if valid IPv4 address.
|
|
98
|
+
*/
|
|
99
|
+
export declare function isIPv4(str: string): boolean;
|
|
100
|
+
/**
|
|
101
|
+
* Checks if a string is a valid IPv6 address.
|
|
102
|
+
*
|
|
103
|
+
* @param {string} str - The input string.
|
|
104
|
+
* @returns {boolean} True if valid IPv6 address.
|
|
105
|
+
*/
|
|
106
|
+
export declare function isIPv6(str: string): boolean;
|
|
107
|
+
/**
|
|
108
|
+
* Validates a credit card number using the Luhn algorithm.
|
|
109
|
+
*
|
|
110
|
+
* @param {string} str - The credit card number string.
|
|
111
|
+
* @returns {boolean} True if valid credit card number.
|
|
112
|
+
*/
|
|
113
|
+
export declare function isCreditCard(str: string): boolean;
|
|
114
|
+
/**
|
|
115
|
+
* Checks if a string is a valid JSON.
|
|
116
|
+
*
|
|
117
|
+
* @param {string} str - The input string.
|
|
118
|
+
* @returns {boolean} True if valid JSON.
|
|
119
|
+
*/
|
|
120
|
+
export declare function isValidJSON(str: string): boolean;
|
|
121
|
+
/**
|
|
122
|
+
* Type guard that checks if a value is an array.
|
|
123
|
+
*
|
|
124
|
+
* @template T Optional expected element type
|
|
125
|
+
* @param {unknown} value - The value to check.
|
|
126
|
+
* @param {(item: unknown) => boolean} [itemGuard] - Optional function to validate each item.
|
|
127
|
+
* @returns {boolean} True if value is an array (with optional item validation).
|
|
128
|
+
*/
|
|
129
|
+
export declare function isArray<T = unknown>(value: unknown, itemGuard?: (item: unknown) => item is T): value is T[];
|
|
130
|
+
/**
|
|
131
|
+
* Checks if a string is a valid base64 encoded string.
|
|
132
|
+
*
|
|
133
|
+
* @param {string} str - The input string.
|
|
134
|
+
* @returns {boolean} True if valid base64.
|
|
135
|
+
*/
|
|
136
|
+
export declare function isBase64(str: string): boolean;
|
|
137
|
+
/**
|
|
138
|
+
* Validates that an object has all required properties.
|
|
139
|
+
*
|
|
140
|
+
* @param {object} obj - The object to validate.
|
|
141
|
+
* @param {string[]} requiredProps - Array of required property names.
|
|
142
|
+
* @returns {boolean} True if all required properties exist.
|
|
143
|
+
*/
|
|
144
|
+
export declare function hasRequiredProps(obj: Record<string, unknown>, requiredProps: string[]): boolean;
|
|
145
|
+
/**
|
|
146
|
+
* Validates a date is within a specified range.
|
|
147
|
+
*
|
|
148
|
+
* @param {Date} date - The date to validate.
|
|
149
|
+
* @param {Date} [minDate] - Optional minimum date (inclusive).
|
|
150
|
+
* @param {Date} [maxDate] - Optional maximum date (inclusive).
|
|
151
|
+
* @returns {boolean} True if date is within range.
|
|
152
|
+
*/
|
|
153
|
+
export declare function isDateInRange(date: Date, minDate?: Date, maxDate?: Date): boolean;
|
|
154
|
+
/**
|
|
155
|
+
* Validates a string matches a specific regular expression pattern.
|
|
156
|
+
*
|
|
157
|
+
* @param {string} str - The input string.
|
|
158
|
+
* @param {RegExp} pattern - Regular expression to test against.
|
|
159
|
+
* @returns {boolean} True if string matches pattern.
|
|
160
|
+
*/
|
|
161
|
+
export declare function matchesPattern(str: string, pattern: RegExp): boolean;
|
|
162
|
+
/**
|
|
163
|
+
* Validates data against multiple constraints.
|
|
164
|
+
*
|
|
165
|
+
* @param {unknown} value - The value to validate.
|
|
166
|
+
* @param {Array<(value: unknown) => boolean>} validators - Array of validation functions.
|
|
167
|
+
* @returns {boolean} True if value passes all validations.
|
|
168
|
+
*/
|
|
169
|
+
export declare function validateAll(value: unknown, validators: Array<(value: unknown) => boolean>): boolean;
|
|
60
170
|
//# sourceMappingURL=validate.utils.d.ts.map
|
|
@@ -11,6 +11,20 @@ exports.isAlphanumeric = isAlphanumeric;
|
|
|
11
11
|
exports.isNumeric = isNumeric;
|
|
12
12
|
exports.isHexColor = isHexColor;
|
|
13
13
|
exports.isISODate = isISODate;
|
|
14
|
+
exports.isLengthBetween = isLengthBetween;
|
|
15
|
+
exports.isNumberBetween = isNumberBetween;
|
|
16
|
+
exports.isAlpha = isAlpha;
|
|
17
|
+
exports.isStrongPassword = isStrongPassword;
|
|
18
|
+
exports.isIPv4 = isIPv4;
|
|
19
|
+
exports.isIPv6 = isIPv6;
|
|
20
|
+
exports.isCreditCard = isCreditCard;
|
|
21
|
+
exports.isValidJSON = isValidJSON;
|
|
22
|
+
exports.isArray = isArray;
|
|
23
|
+
exports.isBase64 = isBase64;
|
|
24
|
+
exports.hasRequiredProps = hasRequiredProps;
|
|
25
|
+
exports.isDateInRange = isDateInRange;
|
|
26
|
+
exports.matchesPattern = matchesPattern;
|
|
27
|
+
exports.validateAll = validateAll;
|
|
14
28
|
/**
|
|
15
29
|
* Checks if a string is a valid email address.
|
|
16
30
|
*
|
|
@@ -21,11 +35,11 @@ function isEmail(str) {
|
|
|
21
35
|
if (!/^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(str))
|
|
22
36
|
return false;
|
|
23
37
|
// Additional checks
|
|
24
|
-
const [local, domain] = str.split(
|
|
38
|
+
const [local, domain] = str.split('@');
|
|
25
39
|
if (!local || !domain)
|
|
26
40
|
return false;
|
|
27
41
|
// Disallow consecutive dots in local or domain part
|
|
28
|
-
if (local.includes(
|
|
42
|
+
if (local.includes('..') || domain.includes('..'))
|
|
29
43
|
return false;
|
|
30
44
|
return true;
|
|
31
45
|
}
|
|
@@ -60,10 +74,10 @@ function isURL(str) {
|
|
|
60
74
|
* @returns {boolean} True if looks like a phone number.
|
|
61
75
|
*/
|
|
62
76
|
function isPhone(str) {
|
|
63
|
-
if (typeof str !==
|
|
77
|
+
if (typeof str !== 'string')
|
|
64
78
|
return false;
|
|
65
79
|
// Strip non-digit characters to count total digits
|
|
66
|
-
const digitsOnly = str.replace(/\D/g,
|
|
80
|
+
const digitsOnly = str.replace(/\D/g, '');
|
|
67
81
|
if (digitsOnly.length < 6 || digitsOnly.length > 15)
|
|
68
82
|
return false;
|
|
69
83
|
// Accept typical phone characters: +, digits, space, -, (, )
|
|
@@ -85,10 +99,10 @@ function isAlphanumeric(str) {
|
|
|
85
99
|
* @returns {boolean} True if the value is numeric.
|
|
86
100
|
*/
|
|
87
101
|
function isNumeric(value) {
|
|
88
|
-
if (typeof value ===
|
|
102
|
+
if (typeof value === 'string' && value.trim() === '')
|
|
89
103
|
return false;
|
|
90
|
-
const num = typeof value ===
|
|
91
|
-
return typeof num ===
|
|
104
|
+
const num = typeof value === 'number' ? value : Number(value);
|
|
105
|
+
return typeof num === 'number' && isFinite(num);
|
|
92
106
|
}
|
|
93
107
|
/**
|
|
94
108
|
* Checks if a string is a valid hex color code (e.g. #FFF or #FFFFFF).
|
|
@@ -110,6 +124,188 @@ function isISODate(str) {
|
|
|
110
124
|
if (!isoRegex.test(str))
|
|
111
125
|
return false;
|
|
112
126
|
const date = new Date(str);
|
|
113
|
-
return
|
|
127
|
+
return !isNaN(date.getTime()) && date.toISOString().startsWith(str.slice(0, 10));
|
|
128
|
+
}
|
|
129
|
+
/**
|
|
130
|
+
* Checks if a string matches a specified length range.
|
|
131
|
+
*
|
|
132
|
+
* @param {string} str - The input string.
|
|
133
|
+
* @param {number} min - Minimum length (inclusive).
|
|
134
|
+
* @param {number} max - Maximum length (inclusive).
|
|
135
|
+
* @returns {boolean} True if string length is within range.
|
|
136
|
+
*/
|
|
137
|
+
function isLengthBetween(str, min, max) {
|
|
138
|
+
return str.length >= min && str.length <= max;
|
|
139
|
+
}
|
|
140
|
+
/**
|
|
141
|
+
* Validates that a number is between specified min and max values (inclusive).
|
|
142
|
+
*
|
|
143
|
+
* @param {number} value - The number to validate.
|
|
144
|
+
* @param {number} min - Minimum value.
|
|
145
|
+
* @param {number} max - Maximum value.
|
|
146
|
+
* @returns {boolean} True if number is within range.
|
|
147
|
+
*/
|
|
148
|
+
function isNumberBetween(value, min, max) {
|
|
149
|
+
return value >= min && value <= max;
|
|
150
|
+
}
|
|
151
|
+
/**
|
|
152
|
+
* Checks if a string contains only alphabetic characters.
|
|
153
|
+
*
|
|
154
|
+
* @param {string} str - The input string.
|
|
155
|
+
* @returns {boolean} True if alphabetic only.
|
|
156
|
+
*/
|
|
157
|
+
function isAlpha(str) {
|
|
158
|
+
return /^[a-zA-Z]+$/.test(str);
|
|
159
|
+
}
|
|
160
|
+
/**
|
|
161
|
+
* Validates that a string contains at least one uppercase letter,
|
|
162
|
+
* one lowercase letter, one number, and one special character.
|
|
163
|
+
*
|
|
164
|
+
* @param {string} str - The input string.
|
|
165
|
+
* @returns {boolean} True if string meets password complexity requirements.
|
|
166
|
+
*/
|
|
167
|
+
function isStrongPassword(str) {
|
|
168
|
+
if (str.length < 8)
|
|
169
|
+
return false;
|
|
170
|
+
const hasUpperCase = /[A-Z]/.test(str);
|
|
171
|
+
const hasLowerCase = /[a-z]/.test(str);
|
|
172
|
+
const hasNumbers = /[0-9]/.test(str);
|
|
173
|
+
const hasSpecialChar = /[!@#$%^&*()_+\-=[\]{};':"\\|,.<>?]/.test(str);
|
|
174
|
+
return hasUpperCase && hasLowerCase && hasNumbers && hasSpecialChar;
|
|
175
|
+
}
|
|
176
|
+
/**
|
|
177
|
+
* Checks if a string is a valid IPv4 address.
|
|
178
|
+
*
|
|
179
|
+
* @param {string} str - The input string.
|
|
180
|
+
* @returns {boolean} True if valid IPv4 address.
|
|
181
|
+
*/
|
|
182
|
+
function isIPv4(str) {
|
|
183
|
+
const parts = str.split('.');
|
|
184
|
+
if (parts.length !== 4)
|
|
185
|
+
return false;
|
|
186
|
+
return parts.every(part => {
|
|
187
|
+
const num = parseInt(part, 10);
|
|
188
|
+
return part === num.toString() && num >= 0 && num <= 255;
|
|
189
|
+
});
|
|
190
|
+
}
|
|
191
|
+
/**
|
|
192
|
+
* Checks if a string is a valid IPv6 address.
|
|
193
|
+
*
|
|
194
|
+
* @param {string} str - The input string.
|
|
195
|
+
* @returns {boolean} True if valid IPv6 address.
|
|
196
|
+
*/
|
|
197
|
+
function isIPv6(str) {
|
|
198
|
+
// Simple but effective check for common IPv6 formats
|
|
199
|
+
return /^(([0-9a-fA-F]{1,4}:){7}[0-9a-fA-F]{1,4}|([0-9a-fA-F]{1,4}:){1,7}:|([0-9a-fA-F]{1,4}:){1,6}:[0-9a-fA-F]{1,4}|([0-9a-fA-F]{1,4}:){1,5}(:[0-9a-fA-F]{1,4}){1,2}|([0-9a-fA-F]{1,4}:){1,4}(:[0-9a-fA-F]{1,4}){1,3}|([0-9a-fA-F]{1,4}:){1,3}(:[0-9a-fA-F]{1,4}){1,4}|([0-9a-fA-F]{1,4}:){1,2}(:[0-9a-fA-F]{1,4}){1,5}|[0-9a-fA-F]{1,4}:((:[0-9a-fA-F]{1,4}){1,6})|:((:[0-9a-fA-F]{1,4}){1,7}|:)|fe80:(:[0-9a-fA-F]{0,4}){0,4}%[0-9a-zA-Z]+|::(ffff(:0{1,4})?:)?((25[0-5]|(2[0-4]|1?[0-9])?[0-9])\.){3}(25[0-5]|(2[0-4]|1?[0-9])?[0-9])|([0-9a-fA-F]{1,4}:){1,4}:((25[0-5]|(2[0-4]|1?[0-9])?[0-9])\.){3}(25[0-5]|(2[0-4]|1?[0-9])?[0-9]))$/.test(str);
|
|
200
|
+
}
|
|
201
|
+
/**
|
|
202
|
+
* Validates a credit card number using the Luhn algorithm.
|
|
203
|
+
*
|
|
204
|
+
* @param {string} str - The credit card number string.
|
|
205
|
+
* @returns {boolean} True if valid credit card number.
|
|
206
|
+
*/
|
|
207
|
+
function isCreditCard(str) {
|
|
208
|
+
// Remove non-digit characters
|
|
209
|
+
const cardNumber = str.replace(/\D/g, '');
|
|
210
|
+
if (cardNumber.length < 13 || cardNumber.length > 19)
|
|
211
|
+
return false;
|
|
212
|
+
// Luhn algorithm implementation
|
|
213
|
+
let sum = 0;
|
|
214
|
+
let shouldDouble = false;
|
|
215
|
+
for (let i = cardNumber.length - 1; i >= 0; i--) {
|
|
216
|
+
let digit = parseInt(cardNumber.charAt(i), 10);
|
|
217
|
+
if (shouldDouble) {
|
|
218
|
+
digit *= 2;
|
|
219
|
+
if (digit > 9)
|
|
220
|
+
digit -= 9;
|
|
221
|
+
}
|
|
222
|
+
sum += digit;
|
|
223
|
+
shouldDouble = !shouldDouble;
|
|
224
|
+
}
|
|
225
|
+
return sum % 10 === 0;
|
|
226
|
+
}
|
|
227
|
+
/**
|
|
228
|
+
* Checks if a string is a valid JSON.
|
|
229
|
+
*
|
|
230
|
+
* @param {string} str - The input string.
|
|
231
|
+
* @returns {boolean} True if valid JSON.
|
|
232
|
+
*/
|
|
233
|
+
function isValidJSON(str) {
|
|
234
|
+
try {
|
|
235
|
+
JSON.parse(str);
|
|
236
|
+
return true;
|
|
237
|
+
}
|
|
238
|
+
catch (_a) {
|
|
239
|
+
return false;
|
|
240
|
+
}
|
|
241
|
+
}
|
|
242
|
+
/**
|
|
243
|
+
* Type guard that checks if a value is an array.
|
|
244
|
+
*
|
|
245
|
+
* @template T Optional expected element type
|
|
246
|
+
* @param {unknown} value - The value to check.
|
|
247
|
+
* @param {(item: unknown) => boolean} [itemGuard] - Optional function to validate each item.
|
|
248
|
+
* @returns {boolean} True if value is an array (with optional item validation).
|
|
249
|
+
*/
|
|
250
|
+
function isArray(value, itemGuard) {
|
|
251
|
+
if (!Array.isArray(value))
|
|
252
|
+
return false;
|
|
253
|
+
return !itemGuard || value.every(item => itemGuard(item));
|
|
254
|
+
}
|
|
255
|
+
/**
|
|
256
|
+
* Checks if a string is a valid base64 encoded string.
|
|
257
|
+
*
|
|
258
|
+
* @param {string} str - The input string.
|
|
259
|
+
* @returns {boolean} True if valid base64.
|
|
260
|
+
*/
|
|
261
|
+
function isBase64(str) {
|
|
262
|
+
return /^(?:[A-Za-z0-9+/]{4})*(?:[A-Za-z0-9+/]{2}==|[A-Za-z0-9+/]{3}=)?$/.test(str);
|
|
263
|
+
}
|
|
264
|
+
/**
|
|
265
|
+
* Validates that an object has all required properties.
|
|
266
|
+
*
|
|
267
|
+
* @param {object} obj - The object to validate.
|
|
268
|
+
* @param {string[]} requiredProps - Array of required property names.
|
|
269
|
+
* @returns {boolean} True if all required properties exist.
|
|
270
|
+
*/
|
|
271
|
+
function hasRequiredProps(obj, requiredProps) {
|
|
272
|
+
return requiredProps.every(prop => Object.prototype.hasOwnProperty.call(obj, prop) && obj[prop] !== undefined && obj[prop] !== null);
|
|
273
|
+
}
|
|
274
|
+
/**
|
|
275
|
+
* Validates a date is within a specified range.
|
|
276
|
+
*
|
|
277
|
+
* @param {Date} date - The date to validate.
|
|
278
|
+
* @param {Date} [minDate] - Optional minimum date (inclusive).
|
|
279
|
+
* @param {Date} [maxDate] - Optional maximum date (inclusive).
|
|
280
|
+
* @returns {boolean} True if date is within range.
|
|
281
|
+
*/
|
|
282
|
+
function isDateInRange(date, minDate, maxDate) {
|
|
283
|
+
if (!(date instanceof Date) || isNaN(date.getTime()))
|
|
284
|
+
return false;
|
|
285
|
+
if (minDate && date < minDate)
|
|
286
|
+
return false;
|
|
287
|
+
if (maxDate && date > maxDate)
|
|
288
|
+
return false;
|
|
289
|
+
return true;
|
|
290
|
+
}
|
|
291
|
+
/**
|
|
292
|
+
* Validates a string matches a specific regular expression pattern.
|
|
293
|
+
*
|
|
294
|
+
* @param {string} str - The input string.
|
|
295
|
+
* @param {RegExp} pattern - Regular expression to test against.
|
|
296
|
+
* @returns {boolean} True if string matches pattern.
|
|
297
|
+
*/
|
|
298
|
+
function matchesPattern(str, pattern) {
|
|
299
|
+
return pattern.test(str);
|
|
300
|
+
}
|
|
301
|
+
/**
|
|
302
|
+
* Validates data against multiple constraints.
|
|
303
|
+
*
|
|
304
|
+
* @param {unknown} value - The value to validate.
|
|
305
|
+
* @param {Array<(value: unknown) => boolean>} validators - Array of validation functions.
|
|
306
|
+
* @returns {boolean} True if value passes all validations.
|
|
307
|
+
*/
|
|
308
|
+
function validateAll(value, validators) {
|
|
309
|
+
return validators.every(validator => validator(value));
|
|
114
310
|
}
|
|
115
311
|
//# sourceMappingURL=validate.utils.js.map
|