@catbee/utils 0.0.1 → 0.0.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +303 -107
- package/build/esm/config.d.ts +12 -0
- package/build/esm/config.js +12 -0
- package/build/esm/config.js.map +1 -1
- package/build/esm/index.d.ts +1 -0
- package/build/esm/index.js +1 -0
- package/build/esm/index.js.map +1 -1
- package/build/esm/types/api-response.d.ts +82 -0
- package/build/esm/types/api-response.js.map +1 -1
- package/build/esm/utils/array.utils.d.ts +64 -1
- package/build/esm/utils/array.utils.js +139 -2
- package/build/esm/utils/array.utils.js.map +1 -1
- package/build/esm/utils/async.utils.d.ts +60 -1
- package/build/esm/utils/async.utils.js +160 -2
- 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 +101 -0
- package/build/esm/utils/context-store.utils.js +182 -0
- 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 -15
- 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 +121 -0
- package/build/esm/utils/dir.utils.js +577 -0
- 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 +233 -0
- package/build/esm/utils/env.utils.js.map +1 -1
- package/build/esm/utils/exception.utils.d.ts +116 -0
- package/build/esm/utils/exception.utils.js +322 -0
- 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 -0
- 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 +29 -20
- package/build/esm/utils/id.utils.js.map +1 -1
- package/build/esm/utils/logger.utils.d.ts +24 -0
- package/build/esm/utils/logger.utils.js +54 -0
- package/build/esm/utils/logger.utils.js.map +1 -1
- package/build/esm/utils/middleware.utils.d.ts +72 -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 +205 -6
- package/build/esm/utils/obj.utils.js.map +1 -1
- package/build/esm/utils/response.utils.d.ts +101 -0
- package/build/esm/utils/response.utils.js +153 -0
- 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 +101 -11
- 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 -0
- 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 +186 -0
- package/build/esm/utils/validate.utils.js.map +1 -1
- package/build/esnext/config.d.ts +12 -0
- package/build/esnext/config.js +12 -0
- package/build/esnext/config.js.map +1 -1
- package/build/esnext/index.d.ts +1 -0
- package/build/esnext/index.js +1 -0
- package/build/esnext/index.js.map +1 -1
- package/build/esnext/types/api-response.d.ts +82 -0
- package/build/esnext/types/api-response.js.map +1 -1
- package/build/esnext/utils/array.utils.d.ts +64 -1
- package/build/esnext/utils/array.utils.js +129 -2
- package/build/esnext/utils/array.utils.js.map +1 -1
- package/build/esnext/utils/async.utils.d.ts +60 -1
- package/build/esnext/utils/async.utils.js +117 -1
- 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 +101 -0
- package/build/esnext/utils/context-store.utils.js +168 -0
- 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 +205 -15
- 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 +121 -0
- package/build/esnext/utils/dir.utils.js +306 -0
- 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 +185 -0
- package/build/esnext/utils/env.utils.js.map +1 -1
- package/build/esnext/utils/exception.utils.d.ts +116 -0
- package/build/esnext/utils/exception.utils.js +213 -0
- 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 -0
- 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 +27 -19
- package/build/esnext/utils/id.utils.js.map +1 -1
- package/build/esnext/utils/logger.utils.d.ts +24 -0
- package/build/esnext/utils/logger.utils.js +42 -0
- package/build/esnext/utils/logger.utils.js.map +1 -1
- package/build/esnext/utils/middleware.utils.d.ts +72 -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 +167 -3
- package/build/esnext/utils/obj.utils.js.map +1 -1
- package/build/esnext/utils/response.utils.d.ts +101 -0
- package/build/esnext/utils/response.utils.js +138 -0
- 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 -0
- 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 +184 -0
- package/build/esnext/utils/validate.utils.js.map +1 -1
- package/build/src/config.d.ts +12 -0
- package/build/src/config.js +12 -0
- package/build/src/config.js.map +1 -1
- package/build/src/index.d.ts +1 -0
- package/build/src/index.js +1 -0
- package/build/src/index.js.map +1 -1
- package/build/src/types/api-response.d.ts +82 -0
- package/build/src/types/api-response.js.map +1 -1
- package/build/src/utils/array.utils.d.ts +64 -1
- package/build/src/utils/array.utils.js +137 -4
- package/build/src/utils/array.utils.js.map +1 -1
- package/build/src/utils/async.utils.d.ts +60 -1
- package/build/src/utils/async.utils.js +124 -4
- 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 +101 -0
- package/build/src/utils/context-store.utils.js +171 -1
- 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 +224 -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 +121 -0
- package/build/src/utils/dir.utils.js +316 -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 +186 -1
- package/build/src/utils/env.utils.js.map +1 -1
- package/build/src/utils/exception.utils.d.ts +116 -0
- package/build/src/utils/exception.utils.js +226 -1
- 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 +282 -0
- 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 +27 -19
- package/build/src/utils/id.utils.js.map +1 -1
- package/build/src/utils/logger.utils.d.ts +24 -0
- package/build/src/utils/logger.utils.js +45 -0
- package/build/src/utils/logger.utils.js.map +1 -1
- package/build/src/utils/middleware.utils.d.ts +72 -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 +177 -7
- package/build/src/utils/obj.utils.js.map +1 -1
- package/build/src/utils/response.utils.d.ts +101 -0
- package/build/src/utils/response.utils.js +146 -1
- 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 +257 -0
- 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 +198 -0
- package/build/src/utils/validate.utils.js.map +1 -1
- package/package.json +20 -12
|
@@ -1,17 +1,27 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.
|
|
3
|
+
exports.isObjEmpty = isObjEmpty;
|
|
4
|
+
exports.pick = pick;
|
|
5
|
+
exports.omit = omit;
|
|
4
6
|
exports.deepObjMerge = deepObjMerge;
|
|
5
7
|
exports.flattenObject = flattenObject;
|
|
6
8
|
exports.getValueByPath = getValueByPath;
|
|
9
|
+
exports.setValueByPath = setValueByPath;
|
|
10
|
+
exports.isEqual = isEqual;
|
|
11
|
+
exports.filterObject = filterObject;
|
|
12
|
+
exports.mapObject = mapObject;
|
|
13
|
+
exports.deepFreeze = deepFreeze;
|
|
14
|
+
exports.isObject = isObject;
|
|
15
|
+
exports.getAllPaths = getAllPaths;
|
|
7
16
|
/**
|
|
8
17
|
* Checks whether the object has no own enumerable properties.
|
|
9
18
|
*
|
|
10
19
|
* @param {Record<any, any>} obj - The object to check.
|
|
11
20
|
* @returns {boolean} True if the object is empty, false otherwise.
|
|
12
21
|
*/
|
|
13
|
-
|
|
14
|
-
|
|
22
|
+
function isObjEmpty(obj) {
|
|
23
|
+
return !!obj && typeof obj === "object" && Object.keys(obj).length === 0;
|
|
24
|
+
}
|
|
15
25
|
/**
|
|
16
26
|
* Returns a new object with only the specified keys picked.
|
|
17
27
|
*
|
|
@@ -21,8 +31,9 @@ exports.isObjEmpty = isObjEmpty;
|
|
|
21
31
|
* @param {K[]} keys - Keys to pick from the object.
|
|
22
32
|
* @returns {Pick<T, K>} New object with picked keys.
|
|
23
33
|
*/
|
|
24
|
-
|
|
25
|
-
|
|
34
|
+
function pick(obj, keys) {
|
|
35
|
+
return Object.fromEntries(keys.map((key) => [key, obj[key]]));
|
|
36
|
+
}
|
|
26
37
|
/**
|
|
27
38
|
* Returns a new object with the specified keys omitted.
|
|
28
39
|
*
|
|
@@ -32,8 +43,9 @@ exports.pick = pick;
|
|
|
32
43
|
* @param {K[]} keys - Keys to omit from the object.
|
|
33
44
|
* @returns {Omit<T, K>} New object without omitted keys.
|
|
34
45
|
*/
|
|
35
|
-
|
|
36
|
-
|
|
46
|
+
function omit(obj, keys) {
|
|
47
|
+
return Object.fromEntries(Object.entries(obj).filter(([key]) => !keys.includes(key)));
|
|
48
|
+
}
|
|
37
49
|
/**
|
|
38
50
|
* Deeply merges two objects (mutates and returns the target object, not pure).
|
|
39
51
|
*
|
|
@@ -100,4 +112,162 @@ function getValueByPath(obj, path) {
|
|
|
100
112
|
.filter(Boolean); // remove empty strings
|
|
101
113
|
return parts.reduce((acc, key) => acc === null || acc === void 0 ? void 0 : acc[key], obj);
|
|
102
114
|
}
|
|
115
|
+
/**
|
|
116
|
+
* Sets a value at a deeply nested key in an object using dot/bracket notation path.
|
|
117
|
+
* Creates intermediate objects and arrays as needed.
|
|
118
|
+
*
|
|
119
|
+
* @template T
|
|
120
|
+
* @param {T} obj - The object to modify.
|
|
121
|
+
* @param {string} path - String path using dot and/or bracket notation (e.g., 'user.friends[0].name').
|
|
122
|
+
* @param {any} value - The value to set at the path.
|
|
123
|
+
* @returns {T} The modified object.
|
|
124
|
+
*/
|
|
125
|
+
function setValueByPath(obj, path, value) {
|
|
126
|
+
if (!obj || typeof obj !== "object")
|
|
127
|
+
return obj;
|
|
128
|
+
// Convert path like "a.b[0].c" into ["a", "b", "0", "c"]
|
|
129
|
+
const parts = path
|
|
130
|
+
.replace(/\[(\d+)\]/g, ".$1") // convert [0] to .0
|
|
131
|
+
.split(".")
|
|
132
|
+
.filter(Boolean); // remove empty strings
|
|
133
|
+
// Handle empty path
|
|
134
|
+
if (parts.length === 0)
|
|
135
|
+
return obj;
|
|
136
|
+
let current = obj;
|
|
137
|
+
// Navigate to the parent of the target property
|
|
138
|
+
for (let i = 0; i < parts.length - 1; i++) {
|
|
139
|
+
const key = parts[i];
|
|
140
|
+
const isArrayIndex = !isNaN(Number(parts[i + 1]));
|
|
141
|
+
if (current[key] === undefined) {
|
|
142
|
+
// Create intermediate object or array based on next key type
|
|
143
|
+
current[key] = isArrayIndex ? [] : {};
|
|
144
|
+
}
|
|
145
|
+
current = current[key];
|
|
146
|
+
}
|
|
147
|
+
// Set the value at the final key
|
|
148
|
+
const finalKey = parts[parts.length - 1];
|
|
149
|
+
current[finalKey] = value;
|
|
150
|
+
return obj;
|
|
151
|
+
}
|
|
152
|
+
/**
|
|
153
|
+
* Performs a deep equality check between two objects.
|
|
154
|
+
*
|
|
155
|
+
* @param {any} a - First value to compare.
|
|
156
|
+
* @param {any} b - Second value to compare.
|
|
157
|
+
* @returns {boolean} True if values are deeply equal.
|
|
158
|
+
*/
|
|
159
|
+
function isEqual(a, b) {
|
|
160
|
+
// Check if primitives or references to the same object
|
|
161
|
+
if (a === b)
|
|
162
|
+
return true;
|
|
163
|
+
// Check if either is null/undefined or not an object
|
|
164
|
+
if (a == null ||
|
|
165
|
+
b == null ||
|
|
166
|
+
typeof a !== "object" ||
|
|
167
|
+
typeof b !== "object") {
|
|
168
|
+
return false;
|
|
169
|
+
}
|
|
170
|
+
// Handle Date objects
|
|
171
|
+
if (a instanceof Date && b instanceof Date) {
|
|
172
|
+
return a.getTime() === b.getTime();
|
|
173
|
+
}
|
|
174
|
+
// If one is Date but the other isn't
|
|
175
|
+
if (a instanceof Date || b instanceof Date) {
|
|
176
|
+
return false;
|
|
177
|
+
}
|
|
178
|
+
// Handle arrays
|
|
179
|
+
if (Array.isArray(a) && Array.isArray(b)) {
|
|
180
|
+
if (a.length !== b.length)
|
|
181
|
+
return false;
|
|
182
|
+
// Check each element
|
|
183
|
+
for (let i = 0; i < a.length; i++) {
|
|
184
|
+
if (!isEqual(a[i], b[i]))
|
|
185
|
+
return false;
|
|
186
|
+
}
|
|
187
|
+
return true;
|
|
188
|
+
}
|
|
189
|
+
// If one is Array but the other isn't
|
|
190
|
+
if (Array.isArray(a) || Array.isArray(b)) {
|
|
191
|
+
return false;
|
|
192
|
+
}
|
|
193
|
+
// Compare object keys
|
|
194
|
+
const keysA = Object.keys(a);
|
|
195
|
+
const keysB = Object.keys(b);
|
|
196
|
+
if (keysA.length !== keysB.length)
|
|
197
|
+
return false;
|
|
198
|
+
// Check if every key in A exists in B and has the same value
|
|
199
|
+
return keysA.every((key) => Object.prototype.hasOwnProperty.call(b, key) && isEqual(a[key], b[key]));
|
|
200
|
+
}
|
|
201
|
+
/**
|
|
202
|
+
* Filters object properties based on a predicate function.
|
|
203
|
+
*
|
|
204
|
+
* @template T
|
|
205
|
+
* @param {T} obj - The source object.
|
|
206
|
+
* @param {(value: any, key: string, obj: T) => boolean} predicate - Filter function.
|
|
207
|
+
* @returns {Partial<T>} New object with filtered properties.
|
|
208
|
+
*/
|
|
209
|
+
function filterObject(obj, predicate) {
|
|
210
|
+
return Object.fromEntries(Object.entries(obj).filter(([key, value]) => predicate(value, key, obj)));
|
|
211
|
+
}
|
|
212
|
+
/**
|
|
213
|
+
* Maps object values to new values using a mapping function.
|
|
214
|
+
*
|
|
215
|
+
* @template T
|
|
216
|
+
* @template U
|
|
217
|
+
* @param {T} obj - The source object.
|
|
218
|
+
* @param {(value: any, key: string, obj: T) => U} mapFn - Mapping function.
|
|
219
|
+
* @returns {Record<keyof T, U>} New object with mapped values.
|
|
220
|
+
*/
|
|
221
|
+
function mapObject(obj, mapFn) {
|
|
222
|
+
return Object.fromEntries(Object.entries(obj).map(([key, value]) => [key, mapFn(value, key, obj)]));
|
|
223
|
+
}
|
|
224
|
+
/**
|
|
225
|
+
* Recursively freezes an object and all its properties.
|
|
226
|
+
* Makes an object immutable.
|
|
227
|
+
*
|
|
228
|
+
* @template T
|
|
229
|
+
* @param {T} obj - The object to freeze.
|
|
230
|
+
* @returns {Readonly<T>} The frozen object.
|
|
231
|
+
*/
|
|
232
|
+
function deepFreeze(obj) {
|
|
233
|
+
// Freeze primitive properties
|
|
234
|
+
Object.freeze(obj);
|
|
235
|
+
// Recursively freeze nested objects
|
|
236
|
+
for (const prop of Object.getOwnPropertyNames(obj)) {
|
|
237
|
+
const value = obj[prop];
|
|
238
|
+
if (value !== null &&
|
|
239
|
+
typeof value === "object" &&
|
|
240
|
+
!Object.isFrozen(value)) {
|
|
241
|
+
deepFreeze(value);
|
|
242
|
+
}
|
|
243
|
+
}
|
|
244
|
+
return obj;
|
|
245
|
+
}
|
|
246
|
+
/**
|
|
247
|
+
* Safely checks if a value is an object (not null, not array).
|
|
248
|
+
*
|
|
249
|
+
* @param {unknown} value - Value to check.
|
|
250
|
+
* @returns {boolean} True if value is a non-null, non-array object.
|
|
251
|
+
*/
|
|
252
|
+
function isObject(value) {
|
|
253
|
+
return value !== null && typeof value === "object" && !Array.isArray(value);
|
|
254
|
+
}
|
|
255
|
+
/**
|
|
256
|
+
* Gets all paths in an object using dot notation.
|
|
257
|
+
*
|
|
258
|
+
* @param {Record<string, any>} obj - Object to analyze.
|
|
259
|
+
* @param {string} [parentPath=""] - Internal param for recursion.
|
|
260
|
+
* @returns {string[]} Array of all paths in dot notation.
|
|
261
|
+
*/
|
|
262
|
+
function getAllPaths(obj, parentPath = "") {
|
|
263
|
+
if (!isObject(obj))
|
|
264
|
+
return [];
|
|
265
|
+
return Object.entries(obj).flatMap(([key, value]) => {
|
|
266
|
+
const currentPath = parentPath ? `${parentPath}.${key}` : key;
|
|
267
|
+
if (isObject(value)) {
|
|
268
|
+
return [currentPath, ...getAllPaths(value, currentPath)];
|
|
269
|
+
}
|
|
270
|
+
return [currentPath];
|
|
271
|
+
});
|
|
272
|
+
}
|
|
103
273
|
//# sourceMappingURL=obj.utils.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"obj.utils.js","sourceRoot":"","sources":["../../../src/utils/obj.utils.ts"],"names":[],"mappings":"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","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"]}
|
|
1
|
+
{"version":3,"file":"obj.utils.js","sourceRoot":"","sources":["../../../src/utils/obj.utils.ts"],"names":[],"mappings":"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","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 function isObjEmpty(obj: Record<any, any>): boolean {\n return !!obj && typeof obj === \"object\" && Object.keys(obj).length === 0;\n}\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 function pick<T extends object, K extends keyof T>(\n obj: T,\n keys: K[],\n): Pick<T, K> {\n return Object.fromEntries(keys.map((key) => [key, obj[key]])) as Pick<T, K>;\n}\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 function omit<T extends object, K extends keyof T>(\n obj: T,\n keys: K[],\n): Omit<T, K> {\n return Object.fromEntries(\n Object.entries(obj).filter(([key]) => !keys.includes(key as K)),\n ) as Omit<T, K>;\n}\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\n/**\n * Sets a value at a deeply nested key in an object using dot/bracket notation path.\n * Creates intermediate objects and arrays as needed.\n *\n * @template T\n * @param {T} obj - The object to modify.\n * @param {string} path - String path using dot and/or bracket notation (e.g., 'user.friends[0].name').\n * @param {any} value - The value to set at the path.\n * @returns {T} The modified object.\n */\nexport function setValueByPath<T extends object>(\n obj: T,\n path: string,\n value: any,\n): T {\n if (!obj || typeof obj !== \"object\") return obj;\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 // Handle empty path\n if (parts.length === 0) return obj;\n\n let current: any = obj;\n\n // Navigate to the parent of the target property\n for (let i = 0; i < parts.length - 1; i++) {\n const key = parts[i];\n const isArrayIndex = !isNaN(Number(parts[i + 1]));\n\n if (current[key] === undefined) {\n // Create intermediate object or array based on next key type\n current[key] = isArrayIndex ? [] : {};\n }\n\n current = current[key];\n }\n\n // Set the value at the final key\n const finalKey = parts[parts.length - 1];\n current[finalKey] = value;\n\n return obj;\n}\n\n/**\n * Performs a deep equality check between two objects.\n *\n * @param {any} a - First value to compare.\n * @param {any} b - Second value to compare.\n * @returns {boolean} True if values are deeply equal.\n */\nexport function isEqual(a: any, b: any): boolean {\n // Check if primitives or references to the same object\n if (a === b) return true;\n\n // Check if either is null/undefined or not an object\n if (\n a == null ||\n b == null ||\n typeof a !== \"object\" ||\n typeof b !== \"object\"\n ) {\n return false;\n }\n\n // Handle Date objects\n if (a instanceof Date && b instanceof Date) {\n return a.getTime() === b.getTime();\n }\n\n // If one is Date but the other isn't\n if (a instanceof Date || b instanceof Date) {\n return false;\n }\n\n // Handle arrays\n if (Array.isArray(a) && Array.isArray(b)) {\n if (a.length !== b.length) return false;\n\n // Check each element\n for (let i = 0; i < a.length; i++) {\n if (!isEqual(a[i], b[i])) return false;\n }\n\n return true;\n }\n\n // If one is Array but the other isn't\n if (Array.isArray(a) || Array.isArray(b)) {\n return false;\n }\n\n // Compare object keys\n const keysA = Object.keys(a);\n const keysB = Object.keys(b);\n\n if (keysA.length !== keysB.length) return false;\n\n // Check if every key in A exists in B and has the same value\n return keysA.every(\n (key) =>\n Object.prototype.hasOwnProperty.call(b, key) && isEqual(a[key], b[key]),\n );\n}\n\n/**\n * Filters object properties based on a predicate function.\n *\n * @template T\n * @param {T} obj - The source object.\n * @param {(value: any, key: string, obj: T) => boolean} predicate - Filter function.\n * @returns {Partial<T>} New object with filtered properties.\n */\nexport function filterObject<T extends object>(\n obj: T,\n predicate: (value: any, key: string, obj: T) => boolean,\n): Partial<T> {\n return Object.fromEntries(\n Object.entries(obj).filter(([key, value]) => predicate(value, key, obj)),\n ) as Partial<T>;\n}\n\n/**\n * Maps object values to new values using a mapping function.\n *\n * @template T\n * @template U\n * @param {T} obj - The source object.\n * @param {(value: any, key: string, obj: T) => U} mapFn - Mapping function.\n * @returns {Record<keyof T, U>} New object with mapped values.\n */\nexport function mapObject<T extends object, U>(\n obj: T,\n mapFn: (value: any, key: string, obj: T) => U,\n): Record<keyof T, U> {\n return Object.fromEntries(\n Object.entries(obj).map(([key, value]) => [key, mapFn(value, key, obj)]),\n ) as Record<keyof T, U>;\n}\n\n/**\n * Recursively freezes an object and all its properties.\n * Makes an object immutable.\n *\n * @template T\n * @param {T} obj - The object to freeze.\n * @returns {Readonly<T>} The frozen object.\n */\nexport function deepFreeze<T extends object>(obj: T): Readonly<T> {\n // Freeze primitive properties\n Object.freeze(obj);\n\n // Recursively freeze nested objects\n for (const prop of Object.getOwnPropertyNames(obj)) {\n const value = (obj as any)[prop];\n if (\n value !== null &&\n typeof value === \"object\" &&\n !Object.isFrozen(value)\n ) {\n deepFreeze(value);\n }\n }\n\n return obj;\n}\n\n/**\n * Safely checks if a value is an object (not null, not array).\n *\n * @param {unknown} value - Value to check.\n * @returns {boolean} True if value is a non-null, non-array object.\n */\nexport function isObject(value: unknown): value is Record<string, any> {\n return value !== null && typeof value === \"object\" && !Array.isArray(value);\n}\n\n/**\n * Gets all paths in an object using dot notation.\n *\n * @param {Record<string, any>} obj - Object to analyze.\n * @param {string} [parentPath=\"\"] - Internal param for recursion.\n * @returns {string[]} Array of all paths in dot notation.\n */\nexport function getAllPaths(\n obj: Record<string, any>,\n parentPath: string = \"\",\n): string[] {\n if (!isObject(obj)) return [];\n\n return Object.entries(obj).flatMap(([key, value]) => {\n const currentPath = parentPath ? `${parentPath}.${key}` : key;\n\n if (isObject(value)) {\n return [currentPath, ...getAllPaths(value, currentPath)];\n }\n\n return [currentPath];\n });\n}\n"]}
|
|
@@ -45,4 +45,105 @@ export declare class ErrorResponse extends Error implements Omit<ApiResponse<nev
|
|
|
45
45
|
*/
|
|
46
46
|
constructor(message: string, status?: number);
|
|
47
47
|
}
|
|
48
|
+
/**
|
|
49
|
+
* Response with paginated data extending the standard success response.
|
|
50
|
+
* Useful for APIs that return large collections of data.
|
|
51
|
+
*
|
|
52
|
+
* @typeParam T - The shape of each item in the paginated collection.
|
|
53
|
+
*/
|
|
54
|
+
export declare class PaginatedResponse<T> extends SuccessResponse<T[]> {
|
|
55
|
+
/** Total number of items across all pages */
|
|
56
|
+
total: number;
|
|
57
|
+
/** Current page number (1-based) */
|
|
58
|
+
page: number;
|
|
59
|
+
/** Number of items per page */
|
|
60
|
+
pageSize: number;
|
|
61
|
+
/** Total number of pages */
|
|
62
|
+
totalPages: number;
|
|
63
|
+
/** Whether there's a next page available */
|
|
64
|
+
hasNext: boolean;
|
|
65
|
+
/** Whether there's a previous page available */
|
|
66
|
+
hasPrevious: boolean;
|
|
67
|
+
/**
|
|
68
|
+
* Constructs a new paginated response.
|
|
69
|
+
*
|
|
70
|
+
* @param {T[]} items - The current page of items.
|
|
71
|
+
* @param {Object} pagination - Pagination information.
|
|
72
|
+
* @param {number} pagination.total - Total number of items across all pages.
|
|
73
|
+
* @param {number} pagination.page - Current page number (1-based).
|
|
74
|
+
* @param {number} pagination.pageSize - Number of items per page.
|
|
75
|
+
* @param {string} [message="Success"] - Optional custom message.
|
|
76
|
+
*/
|
|
77
|
+
constructor(items: T[], pagination: {
|
|
78
|
+
total: number;
|
|
79
|
+
page: number;
|
|
80
|
+
pageSize: number;
|
|
81
|
+
}, message?: string);
|
|
82
|
+
}
|
|
83
|
+
/**
|
|
84
|
+
* Specialized response for operations that don't return data (HTTP 204).
|
|
85
|
+
*/
|
|
86
|
+
export declare class NoContentResponse extends SuccessResponse<null> {
|
|
87
|
+
/**
|
|
88
|
+
* Constructs a new no-content response.
|
|
89
|
+
*
|
|
90
|
+
* @param {string} [message="Operation completed successfully"] - Optional custom message.
|
|
91
|
+
*/
|
|
92
|
+
constructor(message?: string);
|
|
93
|
+
}
|
|
94
|
+
/**
|
|
95
|
+
* Specialized response for redirects.
|
|
96
|
+
*/
|
|
97
|
+
export declare class RedirectResponse {
|
|
98
|
+
/** The URL to redirect to */
|
|
99
|
+
redirectUrl: string;
|
|
100
|
+
/** HTTP status code for the redirect (301, 302, 303, 307, 308) */
|
|
101
|
+
statusCode: number;
|
|
102
|
+
/** Whether the response is a redirect */
|
|
103
|
+
isRedirect: boolean;
|
|
104
|
+
/** Unique identifier for this response */
|
|
105
|
+
requestId: string;
|
|
106
|
+
/**
|
|
107
|
+
* Constructs a new redirect response.
|
|
108
|
+
*
|
|
109
|
+
* @param {string} url - The URL to redirect to.
|
|
110
|
+
* @param {number} [statusCode=302] - HTTP status code for the redirect.
|
|
111
|
+
*/
|
|
112
|
+
constructor(url: string, statusCode?: number);
|
|
113
|
+
}
|
|
114
|
+
/**
|
|
115
|
+
* Creates a standard success response.
|
|
116
|
+
*
|
|
117
|
+
* @typeParam T - The shape of the data returned in the response.
|
|
118
|
+
* @param {T} data - The data to include in the response.
|
|
119
|
+
* @param {string} [message="Success"] - Optional custom message.
|
|
120
|
+
* @returns {SuccessResponse<T>} A properly formatted success response.
|
|
121
|
+
*/
|
|
122
|
+
export declare function createSuccessResponse<T>(data: T, message?: string): SuccessResponse<T>;
|
|
123
|
+
/**
|
|
124
|
+
* Creates a standard error response.
|
|
125
|
+
*
|
|
126
|
+
* @param {string} message - The error message.
|
|
127
|
+
* @param {number} [statusCode=500] - HTTP status code for the error.
|
|
128
|
+
* @returns {ErrorResponse} A properly formatted error response.
|
|
129
|
+
*/
|
|
130
|
+
export declare function createErrorResponse(message: string, statusCode?: number): ErrorResponse;
|
|
131
|
+
/**
|
|
132
|
+
* Creates a paginated response from array data.
|
|
133
|
+
*
|
|
134
|
+
* @typeParam T - The shape of each item in the collection.
|
|
135
|
+
* @param {T[]} allItems - The complete array of items to paginate.
|
|
136
|
+
* @param {number} page - The requested page (1-based).
|
|
137
|
+
* @param {number} pageSize - The number of items per page.
|
|
138
|
+
* @param {string} [message="Success"] - Optional custom message.
|
|
139
|
+
* @returns {PaginatedResponse<T>} A properly formatted paginated response.
|
|
140
|
+
*/
|
|
141
|
+
export declare function createPaginatedResponse<T>(allItems: T[], page: number, pageSize: number, message?: string): PaginatedResponse<T>;
|
|
142
|
+
/**
|
|
143
|
+
* Adapter to convert API responses to Express.js response format.
|
|
144
|
+
*
|
|
145
|
+
* @param {any} res - Express response object.
|
|
146
|
+
* @param {SuccessResponse<any> | ErrorResponse | RedirectResponse} apiResponse - API response instance.
|
|
147
|
+
*/
|
|
148
|
+
export declare function sendResponse(res: any, apiResponse: SuccessResponse<any> | ErrorResponse | RedirectResponse): void;
|
|
48
149
|
//# sourceMappingURL=response.utils.d.ts.map
|
|
@@ -1,6 +1,10 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.ErrorResponse = exports.SuccessResponse = void 0;
|
|
3
|
+
exports.RedirectResponse = exports.NoContentResponse = exports.PaginatedResponse = exports.ErrorResponse = exports.SuccessResponse = void 0;
|
|
4
|
+
exports.createSuccessResponse = createSuccessResponse;
|
|
5
|
+
exports.createErrorResponse = createErrorResponse;
|
|
6
|
+
exports.createPaginatedResponse = createPaginatedResponse;
|
|
7
|
+
exports.sendResponse = sendResponse;
|
|
4
8
|
const crypto_1 = require("crypto");
|
|
5
9
|
const context_store_utils_1 = require("./context-store.utils");
|
|
6
10
|
/**
|
|
@@ -60,4 +64,145 @@ class ErrorResponse extends Error {
|
|
|
60
64
|
}
|
|
61
65
|
}
|
|
62
66
|
exports.ErrorResponse = ErrorResponse;
|
|
67
|
+
/**
|
|
68
|
+
* Response with paginated data extending the standard success response.
|
|
69
|
+
* Useful for APIs that return large collections of data.
|
|
70
|
+
*
|
|
71
|
+
* @typeParam T - The shape of each item in the paginated collection.
|
|
72
|
+
*/
|
|
73
|
+
class PaginatedResponse extends SuccessResponse {
|
|
74
|
+
/**
|
|
75
|
+
* Constructs a new paginated response.
|
|
76
|
+
*
|
|
77
|
+
* @param {T[]} items - The current page of items.
|
|
78
|
+
* @param {Object} pagination - Pagination information.
|
|
79
|
+
* @param {number} pagination.total - Total number of items across all pages.
|
|
80
|
+
* @param {number} pagination.page - Current page number (1-based).
|
|
81
|
+
* @param {number} pagination.pageSize - Number of items per page.
|
|
82
|
+
* @param {string} [message="Success"] - Optional custom message.
|
|
83
|
+
*/
|
|
84
|
+
constructor(items, pagination, message = "Success") {
|
|
85
|
+
super(message, items);
|
|
86
|
+
this.total = pagination.total;
|
|
87
|
+
this.page = pagination.page;
|
|
88
|
+
this.pageSize = pagination.pageSize;
|
|
89
|
+
this.totalPages = Math.ceil(this.total / this.pageSize);
|
|
90
|
+
this.hasNext = this.page < this.totalPages;
|
|
91
|
+
this.hasPrevious = this.page > 1;
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
exports.PaginatedResponse = PaginatedResponse;
|
|
95
|
+
/**
|
|
96
|
+
* Specialized response for operations that don't return data (HTTP 204).
|
|
97
|
+
*/
|
|
98
|
+
class NoContentResponse extends SuccessResponse {
|
|
99
|
+
/**
|
|
100
|
+
* Constructs a new no-content response.
|
|
101
|
+
*
|
|
102
|
+
* @param {string} [message="Operation completed successfully"] - Optional custom message.
|
|
103
|
+
*/
|
|
104
|
+
constructor(message = "Operation completed successfully") {
|
|
105
|
+
super(message, null);
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
exports.NoContentResponse = NoContentResponse;
|
|
109
|
+
/**
|
|
110
|
+
* Specialized response for redirects.
|
|
111
|
+
*/
|
|
112
|
+
class RedirectResponse {
|
|
113
|
+
/**
|
|
114
|
+
* Constructs a new redirect response.
|
|
115
|
+
*
|
|
116
|
+
* @param {string} url - The URL to redirect to.
|
|
117
|
+
* @param {number} [statusCode=302] - HTTP status code for the redirect.
|
|
118
|
+
*/
|
|
119
|
+
constructor(url, statusCode = 302) {
|
|
120
|
+
var _a;
|
|
121
|
+
/** Whether the response is a redirect */
|
|
122
|
+
this.isRedirect = true;
|
|
123
|
+
/** Unique identifier for this response */
|
|
124
|
+
this.requestId = (_a = (0, context_store_utils_1.getRequestId)()) !== null && _a !== void 0 ? _a : (0, crypto_1.randomUUID)();
|
|
125
|
+
this.redirectUrl = url;
|
|
126
|
+
this.statusCode = statusCode;
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
exports.RedirectResponse = RedirectResponse;
|
|
130
|
+
/**
|
|
131
|
+
* Creates a standard success response.
|
|
132
|
+
*
|
|
133
|
+
* @typeParam T - The shape of the data returned in the response.
|
|
134
|
+
* @param {T} data - The data to include in the response.
|
|
135
|
+
* @param {string} [message="Success"] - Optional custom message.
|
|
136
|
+
* @returns {SuccessResponse<T>} A properly formatted success response.
|
|
137
|
+
*/
|
|
138
|
+
function createSuccessResponse(data, message = "Success") {
|
|
139
|
+
return new SuccessResponse(message, data);
|
|
140
|
+
}
|
|
141
|
+
/**
|
|
142
|
+
* Creates a standard error response.
|
|
143
|
+
*
|
|
144
|
+
* @param {string} message - The error message.
|
|
145
|
+
* @param {number} [statusCode=500] - HTTP status code for the error.
|
|
146
|
+
* @returns {ErrorResponse} A properly formatted error response.
|
|
147
|
+
*/
|
|
148
|
+
function createErrorResponse(message, statusCode = 500) {
|
|
149
|
+
return new ErrorResponse(message, statusCode);
|
|
150
|
+
}
|
|
151
|
+
/**
|
|
152
|
+
* Creates a paginated response from array data.
|
|
153
|
+
*
|
|
154
|
+
* @typeParam T - The shape of each item in the collection.
|
|
155
|
+
* @param {T[]} allItems - The complete array of items to paginate.
|
|
156
|
+
* @param {number} page - The requested page (1-based).
|
|
157
|
+
* @param {number} pageSize - The number of items per page.
|
|
158
|
+
* @param {string} [message="Success"] - Optional custom message.
|
|
159
|
+
* @returns {PaginatedResponse<T>} A properly formatted paginated response.
|
|
160
|
+
*/
|
|
161
|
+
function createPaginatedResponse(allItems, page, pageSize, message = "Success") {
|
|
162
|
+
// Ensure valid pagination parameters
|
|
163
|
+
const validPage = Math.max(1, page);
|
|
164
|
+
const validPageSize = Math.max(1, pageSize);
|
|
165
|
+
// Calculate slice indices
|
|
166
|
+
const startIndex = (validPage - 1) * validPageSize;
|
|
167
|
+
const endIndex = startIndex + validPageSize;
|
|
168
|
+
// Get current page items
|
|
169
|
+
const pageItems = allItems.slice(startIndex, endIndex);
|
|
170
|
+
return new PaginatedResponse(pageItems, {
|
|
171
|
+
total: allItems.length,
|
|
172
|
+
page: validPage,
|
|
173
|
+
pageSize: validPageSize,
|
|
174
|
+
}, message);
|
|
175
|
+
}
|
|
176
|
+
/**
|
|
177
|
+
* Adapter to convert API responses to Express.js response format.
|
|
178
|
+
*
|
|
179
|
+
* @param {any} res - Express response object.
|
|
180
|
+
* @param {SuccessResponse<any> | ErrorResponse | RedirectResponse} apiResponse - API response instance.
|
|
181
|
+
*/
|
|
182
|
+
function sendResponse(res, apiResponse) {
|
|
183
|
+
// Handle redirects
|
|
184
|
+
if ("redirectUrl" in apiResponse) {
|
|
185
|
+
res.redirect(apiResponse.statusCode, apiResponse.redirectUrl);
|
|
186
|
+
return;
|
|
187
|
+
}
|
|
188
|
+
// Handle errors
|
|
189
|
+
if ("error" in apiResponse && apiResponse.error) {
|
|
190
|
+
const errorResponse = apiResponse;
|
|
191
|
+
res.status(errorResponse.status).json({
|
|
192
|
+
error: true,
|
|
193
|
+
message: errorResponse.message,
|
|
194
|
+
timestamp: errorResponse.timestamp,
|
|
195
|
+
requestId: errorResponse.requestId,
|
|
196
|
+
});
|
|
197
|
+
return;
|
|
198
|
+
}
|
|
199
|
+
// Handle success responses
|
|
200
|
+
const successResponse = apiResponse;
|
|
201
|
+
// No content (204) shouldn't return a body
|
|
202
|
+
if (successResponse instanceof NoContentResponse) {
|
|
203
|
+
res.status(204).end();
|
|
204
|
+
return;
|
|
205
|
+
}
|
|
206
|
+
res.status(200).json(successResponse);
|
|
207
|
+
}
|
|
63
208
|
//# sourceMappingURL=response.utils.js.map
|
|
@@ -1 +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"]}
|
|
1
|
+
{"version":3,"file":"response.utils.js","sourceRoot":"","sources":["../../../src/utils/response.utils.ts"],"names":[],"mappings":"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","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\n/**\n * Response with paginated data extending the standard success response.\n * Useful for APIs that return large collections of data.\n *\n * @typeParam T - The shape of each item in the paginated collection.\n */\nexport class PaginatedResponse<T> extends SuccessResponse<T[]> {\n /** Total number of items across all pages */\n total: number;\n\n /** Current page number (1-based) */\n page: number;\n\n /** Number of items per page */\n pageSize: number;\n\n /** Total number of pages */\n totalPages: number;\n\n /** Whether there's a next page available */\n hasNext: boolean;\n\n /** Whether there's a previous page available */\n hasPrevious: boolean;\n\n /**\n * Constructs a new paginated response.\n *\n * @param {T[]} items - The current page of items.\n * @param {Object} pagination - Pagination information.\n * @param {number} pagination.total - Total number of items across all pages.\n * @param {number} pagination.page - Current page number (1-based).\n * @param {number} pagination.pageSize - Number of items per page.\n * @param {string} [message=\"Success\"] - Optional custom message.\n */\n constructor(\n items: T[],\n pagination: { total: number; page: number; pageSize: number },\n message: string = \"Success\",\n ) {\n super(message, items);\n\n this.total = pagination.total;\n this.page = pagination.page;\n this.pageSize = pagination.pageSize;\n\n this.totalPages = Math.ceil(this.total / this.pageSize);\n this.hasNext = this.page < this.totalPages;\n this.hasPrevious = this.page > 1;\n }\n}\n\n/**\n * Specialized response for operations that don't return data (HTTP 204).\n */\nexport class NoContentResponse extends SuccessResponse<null> {\n /**\n * Constructs a new no-content response.\n *\n * @param {string} [message=\"Operation completed successfully\"] - Optional custom message.\n */\n constructor(message: string = \"Operation completed successfully\") {\n super(message, null);\n }\n}\n\n/**\n * Specialized response for redirects.\n */\nexport class RedirectResponse {\n /** The URL to redirect to */\n redirectUrl: string;\n\n /** HTTP status code for the redirect (301, 302, 303, 307, 308) */\n statusCode: number;\n\n /** Whether the response is a redirect */\n isRedirect: boolean = true;\n\n /** Unique identifier for this response */\n requestId: string = getRequestId() ?? randomUUID();\n\n /**\n * Constructs a new redirect response.\n *\n * @param {string} url - The URL to redirect to.\n * @param {number} [statusCode=302] - HTTP status code for the redirect.\n */\n constructor(url: string, statusCode: number = 302) {\n this.redirectUrl = url;\n this.statusCode = statusCode;\n }\n}\n\n/**\n * Creates a standard success response.\n *\n * @typeParam T - The shape of the data returned in the response.\n * @param {T} data - The data to include in the response.\n * @param {string} [message=\"Success\"] - Optional custom message.\n * @returns {SuccessResponse<T>} A properly formatted success response.\n */\nexport function createSuccessResponse<T>(\n data: T,\n message: string = \"Success\",\n): SuccessResponse<T> {\n return new SuccessResponse<T>(message, data);\n}\n\n/**\n * Creates a standard error response.\n *\n * @param {string} message - The error message.\n * @param {number} [statusCode=500] - HTTP status code for the error.\n * @returns {ErrorResponse} A properly formatted error response.\n */\nexport function createErrorResponse(\n message: string,\n statusCode: number = 500,\n): ErrorResponse {\n return new ErrorResponse(message, statusCode);\n}\n\n/**\n * Creates a paginated response from array data.\n *\n * @typeParam T - The shape of each item in the collection.\n * @param {T[]} allItems - The complete array of items to paginate.\n * @param {number} page - The requested page (1-based).\n * @param {number} pageSize - The number of items per page.\n * @param {string} [message=\"Success\"] - Optional custom message.\n * @returns {PaginatedResponse<T>} A properly formatted paginated response.\n */\nexport function createPaginatedResponse<T>(\n allItems: T[],\n page: number,\n pageSize: number,\n message: string = \"Success\",\n): PaginatedResponse<T> {\n // Ensure valid pagination parameters\n const validPage = Math.max(1, page);\n const validPageSize = Math.max(1, pageSize);\n\n // Calculate slice indices\n const startIndex = (validPage - 1) * validPageSize;\n const endIndex = startIndex + validPageSize;\n\n // Get current page items\n const pageItems = allItems.slice(startIndex, endIndex);\n\n return new PaginatedResponse<T>(\n pageItems,\n {\n total: allItems.length,\n page: validPage,\n pageSize: validPageSize,\n },\n message,\n );\n}\n\n/**\n * Adapter to convert API responses to Express.js response format.\n *\n * @param {any} res - Express response object.\n * @param {SuccessResponse<any> | ErrorResponse | RedirectResponse} apiResponse - API response instance.\n */\nexport function sendResponse(\n res: any,\n apiResponse: SuccessResponse<any> | ErrorResponse | RedirectResponse,\n): void {\n // Handle redirects\n if (\"redirectUrl\" in apiResponse) {\n res.redirect(apiResponse.statusCode, apiResponse.redirectUrl);\n return;\n }\n\n // Handle errors\n if (\"error\" in apiResponse && apiResponse.error) {\n const errorResponse = apiResponse as ErrorResponse;\n res.status(errorResponse.status).json({\n error: true,\n message: errorResponse.message,\n timestamp: errorResponse.timestamp,\n requestId: errorResponse.requestId,\n });\n return;\n }\n\n // Handle success responses\n const successResponse = apiResponse as SuccessResponse<any>;\n\n // No content (204) shouldn't return a body\n if (successResponse instanceof NoContentResponse) {\n res.status(204).end();\n return;\n }\n\n res.status(200).json(successResponse);\n}\n"]}
|
|
@@ -4,28 +4,28 @@
|
|
|
4
4
|
* @param {string} str - The input string.
|
|
5
5
|
* @returns {string} The string with the first character in uppercase.
|
|
6
6
|
*/
|
|
7
|
-
export declare
|
|
7
|
+
export declare function capitalize(str: string): string;
|
|
8
8
|
/**
|
|
9
9
|
* Converts a string to kebab-case (e.g., "FooBar test" → "foo-bar-test").
|
|
10
10
|
*
|
|
11
11
|
* @param {string} str - The input string.
|
|
12
12
|
* @returns {string} The kebab-cased string.
|
|
13
13
|
*/
|
|
14
|
-
export declare
|
|
14
|
+
export declare function toKebabCase(str: string): string;
|
|
15
15
|
/**
|
|
16
16
|
* Converts a kebab-case or snake_case string to camelCase.
|
|
17
17
|
*
|
|
18
18
|
* @param {string} str - The input string.
|
|
19
19
|
* @returns {string} The camelCased string.
|
|
20
20
|
*/
|
|
21
|
-
export declare
|
|
21
|
+
export declare function toCamelCase(str: string): string;
|
|
22
22
|
/**
|
|
23
23
|
* Converts a string to a URL-friendly slug (lowercase, dashes, alphanumeric).
|
|
24
24
|
*
|
|
25
25
|
* @param {string} str - The input string.
|
|
26
26
|
* @returns {string} The slugified string.
|
|
27
27
|
*/
|
|
28
|
-
export declare
|
|
28
|
+
export declare function slugify(str: string): string;
|
|
29
29
|
/**
|
|
30
30
|
* Truncates a string to a specific length, appending '...' if truncated.
|
|
31
31
|
*
|
|
@@ -33,5 +33,61 @@ export declare const slugify: (str: string) => string;
|
|
|
33
33
|
* @param {number} len - The maximum length.
|
|
34
34
|
* @returns {string} The truncated string.
|
|
35
35
|
*/
|
|
36
|
-
export declare
|
|
36
|
+
export declare function truncate(str: string, len: number): string;
|
|
37
|
+
/**
|
|
38
|
+
* Converts a string to PascalCase (e.g., "foo-bar" → "FooBar").
|
|
39
|
+
*
|
|
40
|
+
* @param {string} str - The input string.
|
|
41
|
+
* @returns {string} The PascalCased string.
|
|
42
|
+
*/
|
|
43
|
+
export declare function toPascalCase(str: string): string;
|
|
44
|
+
/**
|
|
45
|
+
* Converts a string to snake_case (e.g., "FooBar test" → "foo_bar_test").
|
|
46
|
+
*
|
|
47
|
+
* @param {string} str - The input string.
|
|
48
|
+
* @returns {string} The snake_cased string.
|
|
49
|
+
*/
|
|
50
|
+
export declare function toSnakeCase(str: string): string;
|
|
51
|
+
/**
|
|
52
|
+
* Masks a string by replacing characters with a mask character.
|
|
53
|
+
* Useful for hiding sensitive information like credit cards or passwords.
|
|
54
|
+
*
|
|
55
|
+
* @param {string} str - The string to mask.
|
|
56
|
+
* @param {number} [visibleStart=0] - Number of characters to show at start.
|
|
57
|
+
* @param {number} [visibleEnd=0] - Number of characters to show at end.
|
|
58
|
+
* @param {string} [maskChar="*"] - Character to use for masking.
|
|
59
|
+
* @returns {string} The masked string.
|
|
60
|
+
*/
|
|
61
|
+
export declare function mask(str: string, visibleStart?: number, visibleEnd?: number, maskChar?: string): string;
|
|
62
|
+
/**
|
|
63
|
+
* Removes all HTML tags from a string.
|
|
64
|
+
*
|
|
65
|
+
* @param {string} str - The HTML string to process.
|
|
66
|
+
* @returns {string} The string with HTML tags removed.
|
|
67
|
+
*/
|
|
68
|
+
export declare function stripHtml(str: string): string;
|
|
69
|
+
/**
|
|
70
|
+
* Performs case-insensitive string comparison.
|
|
71
|
+
*
|
|
72
|
+
* @param {string} a - First string.
|
|
73
|
+
* @param {string} b - Second string.
|
|
74
|
+
* @returns {boolean} True if the strings are equal ignoring case.
|
|
75
|
+
*/
|
|
76
|
+
export declare function equalsIgnoreCase(a: string, b: string): boolean;
|
|
77
|
+
/**
|
|
78
|
+
* Reverses a string.
|
|
79
|
+
*
|
|
80
|
+
* @param {string} str - The string to reverse.
|
|
81
|
+
* @returns {string} The reversed string.
|
|
82
|
+
*/
|
|
83
|
+
export declare function reverse(str: string): string;
|
|
84
|
+
/**
|
|
85
|
+
* Counts occurrences of a substring within a string.
|
|
86
|
+
*
|
|
87
|
+
* @param {string} str - The source string.
|
|
88
|
+
* @param {string} substring - The substring to count.
|
|
89
|
+
* @param {boolean} [caseSensitive=true] - Whether to perform case-sensitive counting.
|
|
90
|
+
* @returns {number} Number of occurrences.
|
|
91
|
+
*/
|
|
92
|
+
export declare function countOccurrences(str: string, substring: string, caseSensitive?: boolean): number;
|
|
37
93
|
//# sourceMappingURL=string.utils.d.ts.map
|