@catbee/utils 2.0.0-next.1 → 2.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 +1 -1
- package/README.md +55 -38
- package/array/index.cjs +37 -5
- package/array/index.d.ts +59 -8
- package/array/index.mjs +32 -4
- package/async/index.cjs +24 -3
- package/async/index.d.ts +18 -2
- package/async/index.mjs +24 -4
- package/cache/index.cjs +1 -1
- package/cache/index.d.ts +1 -1
- package/cache/index.mjs +1 -1
- package/config/index.cjs +8 -8
- package/config/index.d.ts +1 -1
- package/config/index.mjs +4 -4
- package/context-store/index.cjs +2 -3
- package/context-store/index.d.ts +1 -1
- package/context-store/index.mjs +2 -3
- package/crypto/index.cjs +55 -5
- package/crypto/index.d.ts +63 -2
- package/crypto/index.mjs +52 -7
- package/date/index.cjs +630 -1
- package/date/index.d.ts +487 -2
- package/date/index.mjs +621 -2
- package/{decorators → decorator}/index.cjs +425 -304
- package/{decorators → decorator}/index.d.ts +3 -2
- package/{decorators → decorator}/index.mjs +425 -304
- package/{dir → directory}/index.cjs +1 -1
- package/{dir → directory}/index.d.ts +1 -1
- package/{dir → directory}/index.mjs +1 -1
- package/env/index.cjs +90 -42
- package/env/index.d.ts +12 -1
- package/env/index.mjs +90 -42
- package/exception/index.cjs +1 -1
- package/exception/index.d.ts +1 -1
- package/exception/index.mjs +1 -1
- package/fs/index.cjs +1 -1
- package/fs/index.d.ts +1 -1
- package/fs/index.mjs +1 -1
- package/http-status-codes/index.cjs +1 -1
- package/http-status-codes/index.d.ts +1 -1
- package/http-status-codes/index.mjs +1 -1
- package/id/index.cjs +1 -1
- package/id/index.d.ts +1 -1
- package/id/index.mjs +1 -1
- package/index.cjs +10 -10
- package/index.d.ts +4 -4
- package/index.mjs +4 -4
- package/logger/index.cjs +2 -4
- package/logger/index.d.ts +2 -2
- package/logger/index.mjs +2 -4
- package/middleware/index.cjs +1 -1
- package/middleware/index.d.ts +1 -1
- package/middleware/index.mjs +1 -1
- package/{obj → object}/index.cjs +182 -108
- package/{obj → object}/index.d.ts +38 -2
- package/{obj → object}/index.mjs +180 -109
- package/package.json +31 -13
- package/performance/index.cjs +2 -2
- package/performance/index.d.ts +1 -1
- package/performance/index.mjs +2 -2
- package/request/index.cjs +36 -24
- package/request/index.d.ts +1 -1
- package/request/index.mjs +36 -24
- package/response/index.cjs +1 -1
- package/response/index.d.ts +1 -1
- package/response/index.mjs +1 -1
- package/server/index.cjs +233 -131
- package/server/index.d.ts +81 -1
- package/server/index.mjs +229 -127
- package/stream/index.cjs +1 -1
- package/stream/index.d.ts +1 -1
- package/stream/index.mjs +1 -1
- package/string/index.cjs +34 -1
- package/string/index.d.ts +45 -2
- package/string/index.mjs +31 -2
- package/type/index.cjs +18 -1
- package/type/index.d.ts +38 -2
- package/type/index.mjs +16 -2
- package/types/index.cjs +1 -1
- package/types/index.d.ts +10 -3
- package/types/index.mjs +1 -1
- package/url/index.cjs +61 -1
- package/url/index.d.ts +59 -2
- package/url/index.mjs +57 -2
- package/validation/index.cjs +3 -3
- package/validation/index.d.ts +1 -1
- package/validation/index.mjs +3 -3
package/string/index.mjs
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
/*
|
|
2
2
|
* The MIT License
|
|
3
3
|
*
|
|
4
|
-
* Copyright (c)
|
|
4
|
+
* Copyright (c) 2026 Catbee Technologies. https://catbee.in/license
|
|
5
5
|
*
|
|
6
6
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
7
7
|
* of this software and associated documentation files (the "Software"), to deal
|
|
@@ -91,5 +91,34 @@ function toTitleCase(str) {
|
|
|
91
91
|
return str.split(/(\s+)/).map((part) => part.trim().length === 0 ? part : part.charAt(0).toUpperCase() + part.slice(1).toLowerCase()).join("");
|
|
92
92
|
}
|
|
93
93
|
__name(toTitleCase, "toTitleCase");
|
|
94
|
+
function escapeRegex(str) {
|
|
95
|
+
if (typeof str !== "string") throw new TypeError("Expected a string");
|
|
96
|
+
return str.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
97
|
+
}
|
|
98
|
+
__name(escapeRegex, "escapeRegex");
|
|
99
|
+
function unescapeHtml(str) {
|
|
100
|
+
if (typeof str !== "string") return "";
|
|
101
|
+
const entities = {
|
|
102
|
+
"&": "&",
|
|
103
|
+
"<": "<",
|
|
104
|
+
">": ">",
|
|
105
|
+
""": '"',
|
|
106
|
+
"'": "'",
|
|
107
|
+
"'": "'"
|
|
108
|
+
};
|
|
109
|
+
return str.replace(/&(?:amp|lt|gt|quot|#39|#x27);/g, (match) => entities[match] || match);
|
|
110
|
+
}
|
|
111
|
+
__name(unescapeHtml, "unescapeHtml");
|
|
112
|
+
function isBlank(str) {
|
|
113
|
+
return typeof str === "string" && str.trim().length === 0;
|
|
114
|
+
}
|
|
115
|
+
__name(isBlank, "isBlank");
|
|
116
|
+
function ellipsis(str, maxLength, suffix = "...") {
|
|
117
|
+
if (typeof str !== "string" || str.length <= maxLength) return str;
|
|
118
|
+
const truncated = str.slice(0, maxLength - suffix.length);
|
|
119
|
+
const lastSpace = truncated.lastIndexOf(" ");
|
|
120
|
+
return (lastSpace > 0 ? truncated.slice(0, lastSpace) : truncated) + suffix;
|
|
121
|
+
}
|
|
122
|
+
__name(ellipsis, "ellipsis");
|
|
94
123
|
|
|
95
|
-
export { capitalize, countOccurrences, equalsIgnoreCase, mask, reverse, slugify, stripHtml, toCamelCase, toKebabCase, toPascalCase, toSnakeCase, toTitleCase, truncate };
|
|
124
|
+
export { capitalize, countOccurrences, ellipsis, equalsIgnoreCase, escapeRegex, isBlank, mask, reverse, slugify, stripHtml, toCamelCase, toKebabCase, toPascalCase, toSnakeCase, toTitleCase, truncate, unescapeHtml };
|
package/type/index.cjs
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
/*
|
|
2
2
|
* The MIT License
|
|
3
3
|
*
|
|
4
|
-
* Copyright (c)
|
|
4
|
+
* Copyright (c) 2026 Catbee Technologies. https://catbee.in/license
|
|
5
5
|
*
|
|
6
6
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
7
7
|
* of this software and associated documentation files (the "Software"), to deal
|
|
@@ -117,12 +117,29 @@ function isEmpty(value) {
|
|
|
117
117
|
return false;
|
|
118
118
|
}
|
|
119
119
|
__name(isEmpty, "isEmpty");
|
|
120
|
+
function isIterable(value) {
|
|
121
|
+
return value !== null && value !== void 0 && typeof value[Symbol.iterator] === "function";
|
|
122
|
+
}
|
|
123
|
+
__name(isIterable, "isIterable");
|
|
124
|
+
function isAsyncIterable(value) {
|
|
125
|
+
return value !== null && value !== void 0 && typeof value[Symbol.asyncIterator] === "function";
|
|
126
|
+
}
|
|
127
|
+
__name(isAsyncIterable, "isAsyncIterable");
|
|
128
|
+
function assertType(value, guard, message) {
|
|
129
|
+
if (!guard(value)) {
|
|
130
|
+
throw new TypeError(message || `Type assertion failed`);
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
__name(assertType, "assertType");
|
|
120
134
|
|
|
135
|
+
exports.assertType = assertType;
|
|
121
136
|
exports.ensureType = ensureType;
|
|
122
137
|
exports.getTypeOf = getTypeOf;
|
|
123
138
|
exports.isArrayOf = isArrayOf;
|
|
139
|
+
exports.isAsyncIterable = isAsyncIterable;
|
|
124
140
|
exports.isDefined = isDefined;
|
|
125
141
|
exports.isEmpty = isEmpty;
|
|
142
|
+
exports.isIterable = isIterable;
|
|
126
143
|
exports.isPrimitiveType = isPrimitiveType;
|
|
127
144
|
exports.toBool = toBool;
|
|
128
145
|
exports.toNum = toNum;
|
package/type/index.d.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
/*
|
|
2
2
|
* The MIT License
|
|
3
3
|
*
|
|
4
|
-
* Copyright (c)
|
|
4
|
+
* Copyright (c) 2026 Catbee Technologies. https://catbee.in/license
|
|
5
5
|
*
|
|
6
6
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
7
7
|
* of this software and associated documentation files (the "Software"), to deal
|
|
@@ -127,5 +127,41 @@ declare function isDefined<T>(value: T | null | undefined): value is T;
|
|
|
127
127
|
* @returns True when value is considered empty
|
|
128
128
|
*/
|
|
129
129
|
declare function isEmpty(value: any): boolean;
|
|
130
|
+
/**
|
|
131
|
+
* Type guard to check if a value is iterable.
|
|
132
|
+
*
|
|
133
|
+
* @param {unknown} value - Value to check.
|
|
134
|
+
* @returns {boolean} True if value is iterable.
|
|
135
|
+
*
|
|
136
|
+
* @example
|
|
137
|
+
* isIterable([1, 2, 3]); // true
|
|
138
|
+
* isIterable('hello'); // true
|
|
139
|
+
* isIterable(new Set([1, 2])); // true
|
|
140
|
+
*/
|
|
141
|
+
declare function isIterable<T = any>(value: unknown): value is Iterable<T>;
|
|
142
|
+
/**
|
|
143
|
+
* Type guard to check if a value is an async iterable.
|
|
144
|
+
*
|
|
145
|
+
* @param {unknown} value - Value to check.
|
|
146
|
+
* @returns {boolean} True if value is async iterable.
|
|
147
|
+
*
|
|
148
|
+
* @example
|
|
149
|
+
* async function* gen() { yield 1; }
|
|
150
|
+
* isAsyncIterable(gen()); // true
|
|
151
|
+
*/
|
|
152
|
+
declare function isAsyncIterable<T = any>(value: unknown): value is AsyncIterable<T>;
|
|
153
|
+
/**
|
|
154
|
+
* Asserts that a value is of a specific type, throwing an error if not.
|
|
155
|
+
*
|
|
156
|
+
* @template T
|
|
157
|
+
* @param {unknown} value - Value to assert.
|
|
158
|
+
* @param {(value: unknown) => value is T} guard - Type guard function.
|
|
159
|
+
* @param {string} [message] - Error message if assertion fails.
|
|
160
|
+
* @returns {asserts value is T}
|
|
161
|
+
*
|
|
162
|
+
* @example
|
|
163
|
+
* assertType(value, (v): v is string => typeof v === 'string', 'Expected string');
|
|
164
|
+
*/
|
|
165
|
+
declare function assertType<T>(value: unknown, guard: (value: unknown) => value is T, message?: string): asserts value is T;
|
|
130
166
|
|
|
131
|
-
export { ensureType, getTypeOf, isArrayOf, isDefined, isEmpty, isPrimitiveType, toBool, toNum, toStr };
|
|
167
|
+
export { assertType, ensureType, getTypeOf, isArrayOf, isAsyncIterable, isDefined, isEmpty, isIterable, isPrimitiveType, toBool, toNum, toStr };
|
package/type/index.mjs
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
/*
|
|
2
2
|
* The MIT License
|
|
3
3
|
*
|
|
4
|
-
* Copyright (c)
|
|
4
|
+
* Copyright (c) 2026 Catbee Technologies. https://catbee.in/license
|
|
5
5
|
*
|
|
6
6
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
7
7
|
* of this software and associated documentation files (the "Software"), to deal
|
|
@@ -115,5 +115,19 @@ function isEmpty(value) {
|
|
|
115
115
|
return false;
|
|
116
116
|
}
|
|
117
117
|
__name(isEmpty, "isEmpty");
|
|
118
|
+
function isIterable(value) {
|
|
119
|
+
return value !== null && value !== void 0 && typeof value[Symbol.iterator] === "function";
|
|
120
|
+
}
|
|
121
|
+
__name(isIterable, "isIterable");
|
|
122
|
+
function isAsyncIterable(value) {
|
|
123
|
+
return value !== null && value !== void 0 && typeof value[Symbol.asyncIterator] === "function";
|
|
124
|
+
}
|
|
125
|
+
__name(isAsyncIterable, "isAsyncIterable");
|
|
126
|
+
function assertType(value, guard, message) {
|
|
127
|
+
if (!guard(value)) {
|
|
128
|
+
throw new TypeError(message || `Type assertion failed`);
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
__name(assertType, "assertType");
|
|
118
132
|
|
|
119
|
-
export { ensureType, getTypeOf, isArrayOf, isDefined, isEmpty, isPrimitiveType, toBool, toNum, toStr };
|
|
133
|
+
export { assertType, ensureType, getTypeOf, isArrayOf, isAsyncIterable, isDefined, isEmpty, isIterable, isPrimitiveType, toBool, toNum, toStr };
|
package/types/index.cjs
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
/*
|
|
2
2
|
* The MIT License
|
|
3
3
|
*
|
|
4
|
-
* Copyright (c)
|
|
4
|
+
* Copyright (c) 2026 Catbee Technologies. https://catbee.in/license
|
|
5
5
|
*
|
|
6
6
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
7
7
|
* of this software and associated documentation files (the "Software"), to deal
|
package/types/index.d.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
/*
|
|
2
2
|
* The MIT License
|
|
3
3
|
*
|
|
4
|
-
* Copyright (c)
|
|
4
|
+
* Copyright (c) 2026 Catbee Technologies. https://catbee.in/license
|
|
5
5
|
*
|
|
6
6
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
7
7
|
* of this software and associated documentation files (the "Software"), to deal
|
|
@@ -24,6 +24,7 @@
|
|
|
24
24
|
|
|
25
25
|
import { json, urlencoded, Request, Response, Express, NextFunction } from 'express';
|
|
26
26
|
import http from 'node:http';
|
|
27
|
+
import https from 'node:https';
|
|
27
28
|
import { ExpressServer } from '@catbee/utils/server';
|
|
28
29
|
import { HelmetOptions } from 'helmet';
|
|
29
30
|
import { CompressionOptions } from 'compression';
|
|
@@ -554,8 +555,14 @@ interface CatbeeServerConfig {
|
|
|
554
555
|
interface CatbeeServerHooks {
|
|
555
556
|
/** Called before middleware & routes initialize */
|
|
556
557
|
beforeInit?: (server: ExpressServer) => Promise<void> | void;
|
|
558
|
+
/** Called before any routes are registered */
|
|
559
|
+
beforeRoutes?: (app: Express) => Promise<void> | void;
|
|
560
|
+
/** Called after all routes are registered, before error handling middleware */
|
|
561
|
+
afterRoutes?: (app: Express) => Promise<void> | void;
|
|
557
562
|
/** Called after middleware & routes initialize */
|
|
558
563
|
afterInit?: (server: ExpressServer) => Promise<void> | void;
|
|
564
|
+
/** Called when the underlying HTTP/HTTPS server instance is created */
|
|
565
|
+
onServerCreated?: (server: http.Server | https.Server) => Promise<void> | void;
|
|
559
566
|
/** Called before server starts listening */
|
|
560
567
|
beforeStart?: (app: Express) => Promise<void> | void;
|
|
561
568
|
/** Called after server is ready */
|
|
@@ -575,7 +582,7 @@ interface GlobalServerAddons {
|
|
|
575
582
|
/**
|
|
576
583
|
* Skip healthz endpoint even if health checks are configured
|
|
577
584
|
* - **default**: `false`
|
|
578
|
-
* - **env**: `
|
|
585
|
+
* - **env**: `SERVER_SKIP_HEALTHZ_CHECKS_VALIDATION`
|
|
579
586
|
*
|
|
580
587
|
* @additionalInfo
|
|
581
588
|
* Set to true to return `200 OK` for `/healthz` without checks
|
|
@@ -586,7 +593,7 @@ interface GlobalServerAddons {
|
|
|
586
593
|
* Health checks can still be performed programmatically
|
|
587
594
|
* or via other endpoints if needed
|
|
588
595
|
*/
|
|
589
|
-
|
|
596
|
+
skipHealthzChecksValidation: boolean;
|
|
590
597
|
}
|
|
591
598
|
/** Combined global server configuration type */
|
|
592
599
|
type CatbeeGlobalServerConfig = CatbeeServerConfig & GlobalServerAddons;
|
package/types/index.mjs
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
/*
|
|
2
2
|
* The MIT License
|
|
3
3
|
*
|
|
4
|
-
* Copyright (c)
|
|
4
|
+
* Copyright (c) 2026 Catbee Technologies. https://catbee.in/license
|
|
5
5
|
*
|
|
6
6
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
7
7
|
* of this software and associated documentation files (the "Software"), to deal
|
package/url/index.cjs
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
/*
|
|
2
2
|
* The MIT License
|
|
3
3
|
*
|
|
4
|
-
* Copyright (c)
|
|
4
|
+
* Copyright (c) 2026 Catbee Technologies. https://catbee.in/license
|
|
5
5
|
*
|
|
6
6
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
7
7
|
* of this software and associated documentation files (the "Software"), to deal
|
|
@@ -101,6 +101,16 @@ function normalizeUrl(url$1, base) {
|
|
|
101
101
|
}
|
|
102
102
|
}
|
|
103
103
|
__name(normalizeUrl, "normalizeUrl");
|
|
104
|
+
function updateQueryParam(url$1, key, value) {
|
|
105
|
+
try {
|
|
106
|
+
const urlObj = new url.URL(url$1);
|
|
107
|
+
urlObj.searchParams.set(key, String(value));
|
|
108
|
+
return urlObj.toString();
|
|
109
|
+
} catch {
|
|
110
|
+
return url$1;
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
__name(updateQueryParam, "updateQueryParam");
|
|
104
114
|
function createUrlBuilder(baseUrl) {
|
|
105
115
|
return {
|
|
106
116
|
/**
|
|
@@ -185,15 +195,65 @@ function parseTypedQueryParams(url$1, converters) {
|
|
|
185
195
|
}
|
|
186
196
|
}
|
|
187
197
|
__name(parseTypedQueryParams, "parseTypedQueryParams");
|
|
198
|
+
function getSubdomain(url$1) {
|
|
199
|
+
try {
|
|
200
|
+
const { hostname } = new url.URL(url$1);
|
|
201
|
+
const parts = hostname.split(".");
|
|
202
|
+
if (parts.length <= 2) return "";
|
|
203
|
+
return parts.slice(0, -2).join(".");
|
|
204
|
+
} catch {
|
|
205
|
+
return "";
|
|
206
|
+
}
|
|
207
|
+
}
|
|
208
|
+
__name(getSubdomain, "getSubdomain");
|
|
209
|
+
function isRelativeUrl(url$1) {
|
|
210
|
+
if (!url$1 || typeof url$1 !== "string") return false;
|
|
211
|
+
try {
|
|
212
|
+
new url.URL(url$1);
|
|
213
|
+
return false;
|
|
214
|
+
} catch {
|
|
215
|
+
return url$1.startsWith("/") || url$1.startsWith("./") || url$1.startsWith("../");
|
|
216
|
+
}
|
|
217
|
+
}
|
|
218
|
+
__name(isRelativeUrl, "isRelativeUrl");
|
|
219
|
+
function toAbsoluteUrl(relativeUrl, baseUrl) {
|
|
220
|
+
try {
|
|
221
|
+
return new url.URL(relativeUrl, baseUrl).toString();
|
|
222
|
+
} catch {
|
|
223
|
+
return relativeUrl;
|
|
224
|
+
}
|
|
225
|
+
}
|
|
226
|
+
__name(toAbsoluteUrl, "toAbsoluteUrl");
|
|
227
|
+
function sanitizeUrl(url$1, allowedProtocols = [
|
|
228
|
+
"http",
|
|
229
|
+
"https"
|
|
230
|
+
]) {
|
|
231
|
+
try {
|
|
232
|
+
const parsedUrl = new url.URL(url$1);
|
|
233
|
+
const protocol = parsedUrl.protocol.replace(":", "");
|
|
234
|
+
if (!allowedProtocols.includes(protocol)) {
|
|
235
|
+
return null;
|
|
236
|
+
}
|
|
237
|
+
return parsedUrl.toString();
|
|
238
|
+
} catch {
|
|
239
|
+
return null;
|
|
240
|
+
}
|
|
241
|
+
}
|
|
242
|
+
__name(sanitizeUrl, "sanitizeUrl");
|
|
188
243
|
|
|
189
244
|
exports.appendQueryParams = appendQueryParams;
|
|
190
245
|
exports.createUrlBuilder = createUrlBuilder;
|
|
191
246
|
exports.extractQueryParams = extractQueryParams;
|
|
192
247
|
exports.getDomain = getDomain;
|
|
193
248
|
exports.getExtension = getExtension;
|
|
249
|
+
exports.getSubdomain = getSubdomain;
|
|
250
|
+
exports.isRelativeUrl = isRelativeUrl;
|
|
194
251
|
exports.isValidUrl = isValidUrl;
|
|
195
252
|
exports.joinPaths = joinPaths;
|
|
196
253
|
exports.normalizeUrl = normalizeUrl;
|
|
197
254
|
exports.parseQueryString = parseQueryString;
|
|
198
255
|
exports.parseTypedQueryParams = parseTypedQueryParams;
|
|
199
256
|
exports.removeQueryParams = removeQueryParams;
|
|
257
|
+
exports.sanitizeUrl = sanitizeUrl;
|
|
258
|
+
exports.toAbsoluteUrl = toAbsoluteUrl;
|
|
259
|
+
exports.updateQueryParam = updateQueryParam;
|
package/url/index.d.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
/*
|
|
2
2
|
* The MIT License
|
|
3
3
|
*
|
|
4
|
-
* Copyright (c)
|
|
4
|
+
* Copyright (c) 2026 Catbee Technologies. https://catbee.in/license
|
|
5
5
|
*
|
|
6
6
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
7
7
|
* of this software and associated documentation files (the "Software"), to deal
|
|
@@ -91,6 +91,18 @@ declare function joinPaths(...segments: string[]): string;
|
|
|
91
91
|
* // -> 'http://example.com/bar'
|
|
92
92
|
*/
|
|
93
93
|
declare function normalizeUrl(url: string, base?: string): string;
|
|
94
|
+
/**
|
|
95
|
+
* Updates or sets a single query parameter in a URL.
|
|
96
|
+
*
|
|
97
|
+
* @param {string} url - The source URL.
|
|
98
|
+
* @param {string} key - Parameter key.
|
|
99
|
+
* @param {string | number} value - Parameter value.
|
|
100
|
+
* @returns {string} URL with updated parameter.
|
|
101
|
+
*
|
|
102
|
+
* @example
|
|
103
|
+
* updateQueryParam('https://example.com?page=1', 'page', 2); // 'https://example.com?page=2'
|
|
104
|
+
*/
|
|
105
|
+
declare function updateQueryParam(url: string, key: string, value: string | number): string;
|
|
94
106
|
/**
|
|
95
107
|
* Creates a URL builder for constructing URLs with a base URL.
|
|
96
108
|
*
|
|
@@ -162,5 +174,50 @@ declare function getExtension(url: string): string;
|
|
|
162
174
|
* // -> { page: 2, q: 'test' }
|
|
163
175
|
*/
|
|
164
176
|
declare function parseTypedQueryParams<T extends Record<string, any>>(url: string, converters?: Record<keyof T, (val: string) => any>): Partial<T>;
|
|
177
|
+
/**
|
|
178
|
+
* Extracts the subdomain from a URL.
|
|
179
|
+
*
|
|
180
|
+
* @param {string} url - The URL.
|
|
181
|
+
* @returns {string} Subdomain or empty string.
|
|
182
|
+
*
|
|
183
|
+
* @example
|
|
184
|
+
* getSubdomain('https://api.example.com'); // 'api'
|
|
185
|
+
* getSubdomain('https://www.blog.example.com'); // 'www.blog'
|
|
186
|
+
*/
|
|
187
|
+
declare function getSubdomain(url: string): string;
|
|
188
|
+
/**
|
|
189
|
+
* Checks if a URL is relative (not absolute).
|
|
190
|
+
*
|
|
191
|
+
* @param {string} url - The URL to check.
|
|
192
|
+
* @returns {boolean} True if relative.
|
|
193
|
+
*
|
|
194
|
+
* @example
|
|
195
|
+
* isRelativeUrl('/path/to/page'); // true
|
|
196
|
+
* isRelativeUrl('https://example.com/page'); // false
|
|
197
|
+
*/
|
|
198
|
+
declare function isRelativeUrl(url: string): boolean;
|
|
199
|
+
/**
|
|
200
|
+
* Converts a relative URL to an absolute URL using a base URL.
|
|
201
|
+
*
|
|
202
|
+
* @param {string} relativeUrl - The relative URL.
|
|
203
|
+
* @param {string} baseUrl - The base URL.
|
|
204
|
+
* @returns {string} Absolute URL.
|
|
205
|
+
*
|
|
206
|
+
* @example
|
|
207
|
+
* toAbsoluteUrl('/api/users', 'https://example.com'); // 'https://example.com/api/users'
|
|
208
|
+
*/
|
|
209
|
+
declare function toAbsoluteUrl(relativeUrl: string, baseUrl: string): string;
|
|
210
|
+
/**
|
|
211
|
+
* Sanitizes a URL by removing dangerous protocols and normalizing.
|
|
212
|
+
*
|
|
213
|
+
* @param {string} url - The URL to sanitize.
|
|
214
|
+
* @param {string[]} [allowedProtocols=['http', 'https']] - Allowed protocols.
|
|
215
|
+
* @returns {string | null} Sanitized URL or null if unsafe.
|
|
216
|
+
*
|
|
217
|
+
* @example
|
|
218
|
+
* sanitizeUrl('javascript:alert(1)'); // null
|
|
219
|
+
* sanitizeUrl('https://example.com'); // 'https://example.com/'
|
|
220
|
+
*/
|
|
221
|
+
declare function sanitizeUrl(url: string, allowedProtocols?: string[]): string | null;
|
|
165
222
|
|
|
166
|
-
export { appendQueryParams, createUrlBuilder, extractQueryParams, getDomain, getExtension, isValidUrl, joinPaths, normalizeUrl, parseQueryString, parseTypedQueryParams, removeQueryParams };
|
|
223
|
+
export { appendQueryParams, createUrlBuilder, extractQueryParams, getDomain, getExtension, getSubdomain, isRelativeUrl, isValidUrl, joinPaths, normalizeUrl, parseQueryString, parseTypedQueryParams, removeQueryParams, sanitizeUrl, toAbsoluteUrl, updateQueryParam };
|
package/url/index.mjs
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
/*
|
|
2
2
|
* The MIT License
|
|
3
3
|
*
|
|
4
|
-
* Copyright (c)
|
|
4
|
+
* Copyright (c) 2026 Catbee Technologies. https://catbee.in/license
|
|
5
5
|
*
|
|
6
6
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
7
7
|
* of this software and associated documentation files (the "Software"), to deal
|
|
@@ -99,6 +99,16 @@ function normalizeUrl(url, base) {
|
|
|
99
99
|
}
|
|
100
100
|
}
|
|
101
101
|
__name(normalizeUrl, "normalizeUrl");
|
|
102
|
+
function updateQueryParam(url, key, value) {
|
|
103
|
+
try {
|
|
104
|
+
const urlObj = new URL(url);
|
|
105
|
+
urlObj.searchParams.set(key, String(value));
|
|
106
|
+
return urlObj.toString();
|
|
107
|
+
} catch {
|
|
108
|
+
return url;
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
__name(updateQueryParam, "updateQueryParam");
|
|
102
112
|
function createUrlBuilder(baseUrl) {
|
|
103
113
|
return {
|
|
104
114
|
/**
|
|
@@ -183,5 +193,50 @@ function parseTypedQueryParams(url, converters) {
|
|
|
183
193
|
}
|
|
184
194
|
}
|
|
185
195
|
__name(parseTypedQueryParams, "parseTypedQueryParams");
|
|
196
|
+
function getSubdomain(url) {
|
|
197
|
+
try {
|
|
198
|
+
const { hostname } = new URL(url);
|
|
199
|
+
const parts = hostname.split(".");
|
|
200
|
+
if (parts.length <= 2) return "";
|
|
201
|
+
return parts.slice(0, -2).join(".");
|
|
202
|
+
} catch {
|
|
203
|
+
return "";
|
|
204
|
+
}
|
|
205
|
+
}
|
|
206
|
+
__name(getSubdomain, "getSubdomain");
|
|
207
|
+
function isRelativeUrl(url) {
|
|
208
|
+
if (!url || typeof url !== "string") return false;
|
|
209
|
+
try {
|
|
210
|
+
new URL(url);
|
|
211
|
+
return false;
|
|
212
|
+
} catch {
|
|
213
|
+
return url.startsWith("/") || url.startsWith("./") || url.startsWith("../");
|
|
214
|
+
}
|
|
215
|
+
}
|
|
216
|
+
__name(isRelativeUrl, "isRelativeUrl");
|
|
217
|
+
function toAbsoluteUrl(relativeUrl, baseUrl) {
|
|
218
|
+
try {
|
|
219
|
+
return new URL(relativeUrl, baseUrl).toString();
|
|
220
|
+
} catch {
|
|
221
|
+
return relativeUrl;
|
|
222
|
+
}
|
|
223
|
+
}
|
|
224
|
+
__name(toAbsoluteUrl, "toAbsoluteUrl");
|
|
225
|
+
function sanitizeUrl(url, allowedProtocols = [
|
|
226
|
+
"http",
|
|
227
|
+
"https"
|
|
228
|
+
]) {
|
|
229
|
+
try {
|
|
230
|
+
const parsedUrl = new URL(url);
|
|
231
|
+
const protocol = parsedUrl.protocol.replace(":", "");
|
|
232
|
+
if (!allowedProtocols.includes(protocol)) {
|
|
233
|
+
return null;
|
|
234
|
+
}
|
|
235
|
+
return parsedUrl.toString();
|
|
236
|
+
} catch {
|
|
237
|
+
return null;
|
|
238
|
+
}
|
|
239
|
+
}
|
|
240
|
+
__name(sanitizeUrl, "sanitizeUrl");
|
|
186
241
|
|
|
187
|
-
export { appendQueryParams, createUrlBuilder, extractQueryParams, getDomain, getExtension, isValidUrl, joinPaths, normalizeUrl, parseQueryString, parseTypedQueryParams, removeQueryParams };
|
|
242
|
+
export { appendQueryParams, createUrlBuilder, extractQueryParams, getDomain, getExtension, getSubdomain, isRelativeUrl, isValidUrl, joinPaths, normalizeUrl, parseQueryString, parseTypedQueryParams, removeQueryParams, sanitizeUrl, toAbsoluteUrl, updateQueryParam };
|
package/validation/index.cjs
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
/*
|
|
2
2
|
* The MIT License
|
|
3
3
|
*
|
|
4
|
-
* Copyright (c)
|
|
4
|
+
* Copyright (c) 2026 Catbee Technologies. https://catbee.in/license
|
|
5
5
|
*
|
|
6
6
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
7
7
|
* of this software and associated documentation files (the "Software"), to deal
|
|
@@ -68,7 +68,7 @@ function isEmail(str) {
|
|
|
68
68
|
if (!labelRegex.test(label)) return false;
|
|
69
69
|
if (label.startsWith("-") || label.endsWith("-")) return false;
|
|
70
70
|
}
|
|
71
|
-
const tld = labels
|
|
71
|
+
const tld = labels.at(-1) || "";
|
|
72
72
|
if (!TLD_REGEX.test(tld)) return false;
|
|
73
73
|
return true;
|
|
74
74
|
}
|
|
@@ -207,7 +207,7 @@ function isBase64(str) {
|
|
|
207
207
|
__name(isBase64, "isBase64");
|
|
208
208
|
function hasRequiredProps(obj, requiredProps) {
|
|
209
209
|
if (!obj || typeof obj !== "object") return false;
|
|
210
|
-
return requiredProps.every((prop) => Object.
|
|
210
|
+
return requiredProps.every((prop) => Object.hasOwn(obj, prop) && obj[prop] != null);
|
|
211
211
|
}
|
|
212
212
|
__name(hasRequiredProps, "hasRequiredProps");
|
|
213
213
|
function isDateInRange(date, minDate, maxDate) {
|
package/validation/index.d.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
/*
|
|
2
2
|
* The MIT License
|
|
3
3
|
*
|
|
4
|
-
* Copyright (c)
|
|
4
|
+
* Copyright (c) 2026 Catbee Technologies. https://catbee.in/license
|
|
5
5
|
*
|
|
6
6
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
7
7
|
* of this software and associated documentation files (the "Software"), to deal
|
package/validation/index.mjs
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
/*
|
|
2
2
|
* The MIT License
|
|
3
3
|
*
|
|
4
|
-
* Copyright (c)
|
|
4
|
+
* Copyright (c) 2026 Catbee Technologies. https://catbee.in/license
|
|
5
5
|
*
|
|
6
6
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
7
7
|
* of this software and associated documentation files (the "Software"), to deal
|
|
@@ -62,7 +62,7 @@ function isEmail(str) {
|
|
|
62
62
|
if (!labelRegex.test(label)) return false;
|
|
63
63
|
if (label.startsWith("-") || label.endsWith("-")) return false;
|
|
64
64
|
}
|
|
65
|
-
const tld = labels
|
|
65
|
+
const tld = labels.at(-1) || "";
|
|
66
66
|
if (!TLD_REGEX.test(tld)) return false;
|
|
67
67
|
return true;
|
|
68
68
|
}
|
|
@@ -201,7 +201,7 @@ function isBase64(str) {
|
|
|
201
201
|
__name(isBase64, "isBase64");
|
|
202
202
|
function hasRequiredProps(obj, requiredProps) {
|
|
203
203
|
if (!obj || typeof obj !== "object") return false;
|
|
204
|
-
return requiredProps.every((prop) => Object.
|
|
204
|
+
return requiredProps.every((prop) => Object.hasOwn(obj, prop) && obj[prop] != null);
|
|
205
205
|
}
|
|
206
206
|
__name(hasRequiredProps, "hasRequiredProps");
|
|
207
207
|
function isDateInRange(date, minDate, maxDate) {
|