@catbee/utils 2.0.0-next.0 → 2.0.0-next.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/README.md +52 -16
- package/array/index.cjs +180 -71
- package/array/index.d.ts +293 -1
- package/array/index.mjs +171 -72
- package/async/index.cjs +92 -36
- package/async/index.d.ts +275 -1
- package/async/index.mjs +92 -36
- package/cache/index.cjs +1 -1
- package/cache/index.d.ts +155 -1
- package/cache/index.mjs +2 -2
- package/config/index.cjs +78 -64
- package/config/index.d.ts +64 -2
- package/config/index.mjs +76 -64
- package/context-store/index.d.ts +192 -1
- package/crypto/index.d.ts +163 -1
- package/date/index.cjs +46 -1
- package/date/index.d.ts +190 -1
- package/date/index.mjs +45 -2
- package/decorators/index.cjs +1156 -18
- package/decorators/index.d.ts +684 -1
- package/decorators/index.mjs +1156 -18
- package/dir/index.cjs +4 -3
- package/dir/index.d.ts +195 -1
- package/dir/index.mjs +4 -3
- package/env/index.cjs +10 -26
- package/env/index.d.ts +379 -1
- package/env/index.mjs +10 -26
- package/exception/index.d.ts +232 -1
- package/fs/index.cjs +70 -36
- package/fs/index.d.ts +205 -1
- package/fs/index.mjs +64 -34
- package/http-status-codes/index.d.ts +267 -1
- package/id/index.d.ts +37 -1
- package/index.cjs +3 -3
- package/index.d.ts +1 -1
- package/index.mjs +1 -1
- package/logger/index.cjs +11 -11
- package/logger/index.d.ts +189 -1
- package/logger/index.mjs +12 -12
- package/middleware/index.d.ts +103 -1
- package/obj/index.cjs +150 -162
- package/obj/index.d.ts +136 -1
- package/obj/index.mjs +150 -162
- package/package.json +11 -11
- package/performance/index.cjs +2 -2
- package/performance/index.d.ts +138 -1
- package/performance/index.mjs +2 -2
- package/request/index.cjs +1 -1
- package/request/index.d.ts +241 -2
- package/request/index.mjs +1 -1
- package/response/index.d.ts +318 -2
- package/server/index.cjs +27 -23
- package/server/index.d.ts +785 -4
- package/server/index.mjs +28 -23
- package/stream/index.d.ts +90 -1
- package/string/index.d.ts +102 -1
- package/type/index.cjs +1 -1
- package/type/index.d.ts +107 -1
- package/type/index.mjs +1 -1
- package/types/index.d.ts +774 -4
- package/url/index.cjs +2 -4
- package/url/index.d.ts +142 -1
- package/url/index.mjs +2 -4
- package/{validate → validation}/index.cjs +89 -42
- package/{validate/validate.utils.d.ts → validation/index.d.ts} +32 -23
- package/{validate → validation}/index.mjs +85 -42
- package/array/array.utils.d.ts +0 -191
- package/async/async.utils.d.ts +0 -296
- package/cache/cache.utils.d.ts +0 -176
- package/config/config.d.ts +0 -57
- package/context-store/context-store.utils.d.ts +0 -212
- package/crypto/crypto.utils.d.ts +0 -183
- package/date/date.utils.d.ts +0 -190
- package/decorators/decorators.utils.d.ts +0 -705
- package/dir/dir.utils.d.ts +0 -216
- package/env/env.utils.d.ts +0 -400
- package/exception/exception.utils.d.ts +0 -253
- package/fs/fs.utils.d.ts +0 -196
- package/http-status-codes/http-status-codes.d.ts +0 -289
- package/id/id.utils.d.ts +0 -59
- package/logger/logger.utils.d.ts +0 -210
- package/middleware/middleware.utils.d.ts +0 -123
- package/obj/obj.utils.d.ts +0 -156
- package/performance/performance.utils.d.ts +0 -159
- package/request/request.utils.d.ts +0 -109
- package/response/response.utils.d.ts +0 -186
- package/server/server.builder.d.ts +0 -531
- package/server/server.d.ts +0 -303
- package/stream/stream.utils.d.ts +0 -111
- package/string/string.utils.d.ts +0 -124
- package/type/type.utils.d.ts +0 -129
- package/types/api-response.d.ts +0 -175
- package/types/common.d.ts +0 -148
- package/types/config.d.ts +0 -88
- package/types/server.d.ts +0 -291
- package/url/url.utils.d.ts +0 -164
- package/validate/index.d.ts +0 -25
package/obj/index.mjs
CHANGED
|
@@ -26,8 +26,12 @@ var __defProp = Object.defineProperty;
|
|
|
26
26
|
var __name = (target, value) => __defProp(target, "name", { value, configurable: true });
|
|
27
27
|
|
|
28
28
|
// src/obj/obj.utils.ts
|
|
29
|
+
function isObject(value) {
|
|
30
|
+
return value !== null && typeof value === "object" && !Array.isArray(value);
|
|
31
|
+
}
|
|
32
|
+
__name(isObject, "isObject");
|
|
29
33
|
function isObjEmpty(obj) {
|
|
30
|
-
return
|
|
34
|
+
return isObject(obj) && Object.keys(obj).length === 0;
|
|
31
35
|
}
|
|
32
36
|
__name(isObjEmpty, "isObjEmpty");
|
|
33
37
|
function pick(obj, keys) {
|
|
@@ -42,117 +46,38 @@ function omit(obj, keys) {
|
|
|
42
46
|
}
|
|
43
47
|
__name(omit, "omit");
|
|
44
48
|
function deepObjMerge(target, ...sources) {
|
|
45
|
-
if (!sources.length) return target;
|
|
46
49
|
const seen = /* @__PURE__ */ new WeakMap();
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
if (s
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
if (value === null || typeof value !== "object") return value;
|
|
55
|
-
if (seen.has(value)) return seen.get(value);
|
|
56
|
-
if (value instanceof Date) {
|
|
57
|
-
return new Date(value.getTime());
|
|
58
|
-
}
|
|
59
|
-
if (Array.isArray(value)) {
|
|
60
|
-
const clone2 = [];
|
|
61
|
-
seen.set(value, clone2);
|
|
62
|
-
value.forEach((item, i) => clone2[i] = deepClone2(item));
|
|
63
|
-
return clone2;
|
|
64
|
-
}
|
|
65
|
-
if (value instanceof Set) {
|
|
66
|
-
const clone2 = /* @__PURE__ */ new Set();
|
|
67
|
-
seen.set(value, clone2);
|
|
68
|
-
value.forEach((item) => clone2.add(deepClone2(item)));
|
|
69
|
-
return clone2;
|
|
70
|
-
}
|
|
71
|
-
if (value instanceof Map) {
|
|
72
|
-
const clone2 = /* @__PURE__ */ new Map();
|
|
73
|
-
seen.set(value, clone2);
|
|
74
|
-
value.forEach((val, key) => clone2.set(key, deepClone2(val)));
|
|
75
|
-
return clone2;
|
|
76
|
-
}
|
|
77
|
-
if (value instanceof RegExp) {
|
|
78
|
-
return new RegExp(value.source, value.flags);
|
|
50
|
+
const mergeInto = /* @__PURE__ */ __name((t, s) => {
|
|
51
|
+
if (s === void 0) return t;
|
|
52
|
+
if (typeof s === "function" || typeof s === "symbol") return s;
|
|
53
|
+
if (Array.isArray(s)) {
|
|
54
|
+
const cloned = deepClone(s);
|
|
55
|
+
seen.set(s, cloned);
|
|
56
|
+
return cloned;
|
|
79
57
|
}
|
|
80
|
-
if (
|
|
81
|
-
return
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
const typedArrayCtors = [
|
|
87
|
-
Int8Array,
|
|
88
|
-
Uint8Array,
|
|
89
|
-
Uint8ClampedArray,
|
|
90
|
-
Int16Array,
|
|
91
|
-
Uint16Array,
|
|
92
|
-
Int32Array,
|
|
93
|
-
Uint32Array,
|
|
94
|
-
Float32Array,
|
|
95
|
-
Float64Array,
|
|
96
|
-
BigInt64Array,
|
|
97
|
-
BigUint64Array
|
|
98
|
-
].filter(Boolean);
|
|
99
|
-
const typedArrayCtorSet = new Set(typedArrayCtors);
|
|
100
|
-
if (typeof ctor === "function" && typedArrayCtorSet.has(ctor)) {
|
|
101
|
-
const buffer = typed.buffer && typeof typed.buffer.slice === "function" ? typed.buffer.slice(0) : typed.buffer;
|
|
102
|
-
const clone2 = new ctor(buffer, typed.byteOffset, typed.length);
|
|
103
|
-
seen.set(value, clone2);
|
|
104
|
-
return clone2;
|
|
105
|
-
} else if (typeof typed.slice === "function") {
|
|
106
|
-
const clone2 = typed.slice();
|
|
107
|
-
seen.set(value, clone2);
|
|
108
|
-
return clone2;
|
|
109
|
-
} else {
|
|
110
|
-
throw new Error("Cannot deep clone unknown TypedArray type: " + (typed && typed.constructor && typed.constructor.name));
|
|
58
|
+
if (s && typeof s === "object") {
|
|
59
|
+
if (seen.has(s)) return seen.get(s);
|
|
60
|
+
if (s instanceof Date || s instanceof Map || s instanceof Set || s instanceof RegExp || s instanceof ArrayBuffer || ArrayBuffer.isView(s)) {
|
|
61
|
+
const cloned = deepClone(s);
|
|
62
|
+
seen.set(s, cloned);
|
|
63
|
+
return cloned;
|
|
111
64
|
}
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
seen.set(value, clone);
|
|
115
|
-
Reflect.ownKeys(value).forEach((key) => {
|
|
116
|
-
const descriptor = Object.getOwnPropertyDescriptor(value, key);
|
|
117
|
-
if (descriptor.get || descriptor.set) {
|
|
118
|
-
Object.defineProperty(clone, key, descriptor);
|
|
119
|
-
} else {
|
|
120
|
-
clone[key] = deepClone2(value[key]);
|
|
65
|
+
if (!t || typeof t !== "object") {
|
|
66
|
+
t = Object.create(Object.getPrototypeOf(s));
|
|
121
67
|
}
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
const sourceValue = source[key];
|
|
129
|
-
if (sourceValue === void 0) return;
|
|
130
|
-
if (sourceValue === null || typeof sourceValue !== "object") {
|
|
131
|
-
target2[key] = sourceValue;
|
|
132
|
-
return;
|
|
133
|
-
}
|
|
134
|
-
if (Array.isArray(sourceValue)) {
|
|
135
|
-
target2[key] = deepClone2(sourceValue);
|
|
136
|
-
return;
|
|
137
|
-
}
|
|
138
|
-
if (sourceValue instanceof Date || sourceValue instanceof RegExp || sourceValue instanceof Set || sourceValue instanceof Map || sourceValue instanceof ArrayBuffer || ArrayBuffer.isView(sourceValue) && !(sourceValue instanceof DataView)) {
|
|
139
|
-
target2[key] = deepClone2(sourceValue);
|
|
140
|
-
return;
|
|
141
|
-
}
|
|
142
|
-
if (isPlainObject(sourceValue) && isPlainObject(targetValue)) {
|
|
143
|
-
for (const k of Reflect.ownKeys(sourceValue)) {
|
|
144
|
-
mergeProp(targetValue, sourceValue, k);
|
|
68
|
+
seen.set(s, t);
|
|
69
|
+
for (const key of Reflect.ownKeys(s)) {
|
|
70
|
+
if (key === "__proto__") continue;
|
|
71
|
+
const sv = s[key];
|
|
72
|
+
if (sv === void 0) continue;
|
|
73
|
+
t[key] = mergeInto(t[key], sv);
|
|
145
74
|
}
|
|
146
|
-
return;
|
|
147
|
-
}
|
|
148
|
-
target2[key] = deepClone2(sourceValue);
|
|
149
|
-
}
|
|
150
|
-
__name(mergeProp, "mergeProp");
|
|
151
|
-
for (const source of sources) {
|
|
152
|
-
if (source == null) continue;
|
|
153
|
-
for (const key of Reflect.ownKeys(source)) {
|
|
154
|
-
mergeProp(target, source, key);
|
|
75
|
+
return t;
|
|
155
76
|
}
|
|
77
|
+
return s;
|
|
78
|
+
}, "mergeInto");
|
|
79
|
+
for (const s of sources) {
|
|
80
|
+
target = mergeInto(target, s);
|
|
156
81
|
}
|
|
157
82
|
return target;
|
|
158
83
|
}
|
|
@@ -167,6 +92,7 @@ __name(isPlainObject, "isPlainObject");
|
|
|
167
92
|
function flattenObject(obj, prefix = "") {
|
|
168
93
|
return Object.entries(obj).reduce((acc, [key, value]) => {
|
|
169
94
|
const newKey = prefix ? `${prefix}.${key}` : key;
|
|
95
|
+
if (key === "__proto__") return acc;
|
|
170
96
|
if (value && typeof value === "object" && !Array.isArray(value)) {
|
|
171
97
|
Object.assign(acc, flattenObject(value, newKey));
|
|
172
98
|
} else {
|
|
@@ -182,63 +108,52 @@ function getValueByPath(obj, path) {
|
|
|
182
108
|
return parts.reduce((acc, key) => acc?.[key], obj);
|
|
183
109
|
}
|
|
184
110
|
__name(getValueByPath, "getValueByPath");
|
|
111
|
+
function ensureNextContainer(curr, nextIsIndex) {
|
|
112
|
+
if (curr === void 0 || typeof curr !== "object" || curr === null) {
|
|
113
|
+
return nextIsIndex ? [] : /* @__PURE__ */ Object.create(null);
|
|
114
|
+
}
|
|
115
|
+
return curr;
|
|
116
|
+
}
|
|
117
|
+
__name(ensureNextContainer, "ensureNextContainer");
|
|
185
118
|
function setValueByPath(obj, path, value) {
|
|
186
119
|
if (!obj || typeof obj !== "object") return obj;
|
|
120
|
+
const clone = deepClone(obj);
|
|
187
121
|
const parts = path.replace(/\[(\d+)\]/g, ".$1").split(".").filter(Boolean);
|
|
188
|
-
if (parts.length === 0) return
|
|
122
|
+
if (parts.length === 0) return clone;
|
|
189
123
|
const forbiddenKeys = /* @__PURE__ */ new Set([
|
|
190
124
|
"__proto__",
|
|
191
125
|
"prototype",
|
|
192
126
|
"constructor"
|
|
193
127
|
]);
|
|
194
|
-
let current =
|
|
128
|
+
let current = clone;
|
|
195
129
|
for (let i = 0; i < parts.length - 1; i++) {
|
|
196
130
|
const key = parts[i];
|
|
197
|
-
if (forbiddenKeys.has(key))
|
|
198
|
-
return obj;
|
|
199
|
-
}
|
|
131
|
+
if (forbiddenKeys.has(key)) return clone;
|
|
200
132
|
const nextKey = parts[i + 1];
|
|
201
|
-
const
|
|
202
|
-
|
|
203
|
-
current[key] = isArrayIndex ? [] : /* @__PURE__ */ Object.create(null);
|
|
204
|
-
} else if (typeof current[key] !== "object" || current[key] === null) {
|
|
205
|
-
current[key] = isArrayIndex ? [] : /* @__PURE__ */ Object.create(null);
|
|
206
|
-
}
|
|
133
|
+
const nextIsIndex = !Number.isNaN(Number(nextKey));
|
|
134
|
+
current[key] = ensureNextContainer(current[key], nextIsIndex);
|
|
207
135
|
current = current[key];
|
|
208
136
|
}
|
|
209
|
-
const finalKey = parts
|
|
210
|
-
if (forbiddenKeys.has(finalKey))
|
|
211
|
-
return obj;
|
|
212
|
-
}
|
|
137
|
+
const finalKey = parts.at(-1);
|
|
138
|
+
if (forbiddenKeys.has(finalKey)) return clone;
|
|
213
139
|
current[finalKey] = value;
|
|
214
|
-
return
|
|
140
|
+
return clone;
|
|
215
141
|
}
|
|
216
142
|
__name(setValueByPath, "setValueByPath");
|
|
217
143
|
function isEqual(a, b) {
|
|
218
144
|
if (a === b) return true;
|
|
219
|
-
if (a == null || b == null || typeof a !== "object" || typeof b !== "object")
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
if (a instanceof
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
if (a instanceof
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
if (
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
if (!isEqual(a[i], b[i])) return false;
|
|
232
|
-
}
|
|
233
|
-
return true;
|
|
234
|
-
}
|
|
235
|
-
if (Array.isArray(a) || Array.isArray(b)) {
|
|
236
|
-
return false;
|
|
237
|
-
}
|
|
238
|
-
const keysA = Object.keys(a);
|
|
239
|
-
const keysB = Object.keys(b);
|
|
240
|
-
if (keysA.length !== keysB.length) return false;
|
|
241
|
-
return keysA.every((key) => Object.prototype.hasOwnProperty.call(b, key) && isEqual(a[key], b[key]));
|
|
145
|
+
if (a == null || b == null || typeof a !== "object" || typeof b !== "object") return false;
|
|
146
|
+
if (a instanceof Date && b instanceof Date) return a.getTime() === b.getTime();
|
|
147
|
+
if (a instanceof RegExp && b instanceof RegExp) return a.source === b.source && a.flags === b.flags;
|
|
148
|
+
if (a instanceof Set && b instanceof Set) return a.size === b.size && [
|
|
149
|
+
...a
|
|
150
|
+
].every((v) => b.has(v));
|
|
151
|
+
if (a instanceof Map && b instanceof Map) return a.size === b.size && [
|
|
152
|
+
...a
|
|
153
|
+
].every(([k, v]) => isEqual(v, b.get(k)));
|
|
154
|
+
if (a instanceof ArrayBuffer && b instanceof ArrayBuffer) return isEqual(new Uint8Array(a), new Uint8Array(b));
|
|
155
|
+
if (Array.isArray(a) && Array.isArray(b)) return a.length === b.length && a.every((v, i) => isEqual(v, b[i]));
|
|
156
|
+
return Object.keys(a).length === Object.keys(b).length && Object.keys(a).every((key) => isEqual(a[key], b[key]));
|
|
242
157
|
}
|
|
243
158
|
__name(isEqual, "isEqual");
|
|
244
159
|
function filterObject(obj, predicate) {
|
|
@@ -252,35 +167,108 @@ function mapObject(obj, mapFn) {
|
|
|
252
167
|
]));
|
|
253
168
|
}
|
|
254
169
|
__name(mapObject, "mapObject");
|
|
255
|
-
function
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
return globalThis.structuredClone(value);
|
|
259
|
-
}
|
|
260
|
-
} catch (_) {
|
|
170
|
+
function _deepClone(value, seen) {
|
|
171
|
+
if (typeof value === "function" || typeof value === "symbol") {
|
|
172
|
+
return value;
|
|
261
173
|
}
|
|
262
|
-
|
|
263
|
-
return JSON.parse(JSON.stringify(value));
|
|
264
|
-
} catch (_) {
|
|
174
|
+
if (value === null || typeof value !== "object") {
|
|
265
175
|
return value;
|
|
266
176
|
}
|
|
177
|
+
if (seen.has(value)) {
|
|
178
|
+
return seen.get(value);
|
|
179
|
+
}
|
|
180
|
+
let result;
|
|
181
|
+
if (Array.isArray(value)) {
|
|
182
|
+
result = [];
|
|
183
|
+
seen.set(value, result);
|
|
184
|
+
for (const item of value) {
|
|
185
|
+
result.push(_deepClone(item, seen));
|
|
186
|
+
}
|
|
187
|
+
return result;
|
|
188
|
+
}
|
|
189
|
+
if (value instanceof Date) {
|
|
190
|
+
result = new Date(value.getTime());
|
|
191
|
+
seen.set(value, result);
|
|
192
|
+
return result;
|
|
193
|
+
}
|
|
194
|
+
if (value instanceof Map) {
|
|
195
|
+
result = /* @__PURE__ */ new Map();
|
|
196
|
+
seen.set(value, result);
|
|
197
|
+
for (const [k, v] of value) {
|
|
198
|
+
result.set(_deepClone(k, seen), _deepClone(v, seen));
|
|
199
|
+
}
|
|
200
|
+
return result;
|
|
201
|
+
}
|
|
202
|
+
if (value instanceof Set) {
|
|
203
|
+
result = /* @__PURE__ */ new Set();
|
|
204
|
+
seen.set(value, result);
|
|
205
|
+
for (const v of value) {
|
|
206
|
+
result.add(_deepClone(v, seen));
|
|
207
|
+
}
|
|
208
|
+
return result;
|
|
209
|
+
}
|
|
210
|
+
if (value instanceof RegExp) {
|
|
211
|
+
result = new RegExp(value.source, value.flags);
|
|
212
|
+
seen.set(value, result);
|
|
213
|
+
return result;
|
|
214
|
+
}
|
|
215
|
+
if (ArrayBuffer.isView(value)) {
|
|
216
|
+
if (value instanceof DataView) {
|
|
217
|
+
const buf2 = _deepClone(value.buffer, seen);
|
|
218
|
+
const clone2 = new DataView(buf2, value.byteOffset, value.byteLength);
|
|
219
|
+
seen.set(value, clone2);
|
|
220
|
+
return clone2;
|
|
221
|
+
}
|
|
222
|
+
const typed = value;
|
|
223
|
+
const buf = _deepClone(typed.buffer, seen);
|
|
224
|
+
const clone = new typed.constructor(buf, typed.byteOffset, typed.length);
|
|
225
|
+
seen.set(value, clone);
|
|
226
|
+
return clone;
|
|
227
|
+
}
|
|
228
|
+
if (value instanceof ArrayBuffer) {
|
|
229
|
+
result = value.slice(0);
|
|
230
|
+
seen.set(value, result);
|
|
231
|
+
return result;
|
|
232
|
+
}
|
|
233
|
+
result = Object.create(Object.getPrototypeOf(value));
|
|
234
|
+
seen.set(value, result);
|
|
235
|
+
for (const key of Reflect.ownKeys(value)) {
|
|
236
|
+
const desc = Object.getOwnPropertyDescriptor(value, key);
|
|
237
|
+
if (desc?.get || desc?.set) {
|
|
238
|
+
Object.defineProperty(result, key, {
|
|
239
|
+
get: desc.get,
|
|
240
|
+
set: desc.set,
|
|
241
|
+
enumerable: desc.enumerable,
|
|
242
|
+
configurable: desc.configurable
|
|
243
|
+
});
|
|
244
|
+
} else {
|
|
245
|
+
Object.defineProperty(result, key, {
|
|
246
|
+
value: _deepClone(value[key], seen),
|
|
247
|
+
writable: desc?.writable ?? true,
|
|
248
|
+
enumerable: desc?.enumerable ?? true,
|
|
249
|
+
configurable: desc?.configurable ?? true
|
|
250
|
+
});
|
|
251
|
+
}
|
|
252
|
+
}
|
|
253
|
+
return result;
|
|
254
|
+
}
|
|
255
|
+
__name(_deepClone, "_deepClone");
|
|
256
|
+
function deepClone(value) {
|
|
257
|
+
const seen = /* @__PURE__ */ new WeakMap();
|
|
258
|
+
return _deepClone(value, seen);
|
|
267
259
|
}
|
|
268
260
|
__name(deepClone, "deepClone");
|
|
269
261
|
function deepFreeze(obj) {
|
|
270
262
|
Object.freeze(obj);
|
|
271
|
-
for (const
|
|
272
|
-
const
|
|
273
|
-
if (
|
|
274
|
-
deepFreeze(
|
|
263
|
+
for (const key of Reflect.ownKeys(obj)) {
|
|
264
|
+
const val = obj[key];
|
|
265
|
+
if (isObject(val) && !Object.isFrozen(val)) {
|
|
266
|
+
deepFreeze(val);
|
|
275
267
|
}
|
|
276
268
|
}
|
|
277
269
|
return obj;
|
|
278
270
|
}
|
|
279
271
|
__name(deepFreeze, "deepFreeze");
|
|
280
|
-
function isObject(value) {
|
|
281
|
-
return value !== null && typeof value === "object" && !Array.isArray(value);
|
|
282
|
-
}
|
|
283
|
-
__name(isObject, "isObject");
|
|
284
272
|
function getAllPaths(obj, parentPath = "") {
|
|
285
273
|
if (!isObject(obj)) return [];
|
|
286
274
|
return Object.entries(obj).flatMap(([key, value]) => {
|
package/package.json
CHANGED
|
@@ -1,13 +1,10 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@catbee/utils",
|
|
3
|
-
"version": "2.0.0-next.
|
|
3
|
+
"version": "2.0.0-next.1",
|
|
4
4
|
"description": "A modular, production-grade utility toolkit for Node.js and TypeScript, designed for robust, scalable applications (including Express-based services). All utilities are tree-shakable and can be imported independently.",
|
|
5
5
|
"publishConfig": {
|
|
6
6
|
"access": "public"
|
|
7
7
|
},
|
|
8
|
-
"main": "index.cjs",
|
|
9
|
-
"module": "index.mjs",
|
|
10
|
-
"types": "index.d.ts",
|
|
11
8
|
"author": "Hari G <harig@catbee.in>",
|
|
12
9
|
"maintainers": [
|
|
13
10
|
"Hari G <harig@catbee.in>",
|
|
@@ -23,8 +20,7 @@
|
|
|
23
20
|
},
|
|
24
21
|
"license": "MIT",
|
|
25
22
|
"dependencies": {
|
|
26
|
-
"pino": "^10.1.0"
|
|
27
|
-
"reflect-metadata": "^0.2.2"
|
|
23
|
+
"pino": "^10.1.0"
|
|
28
24
|
},
|
|
29
25
|
"optionalDependencies": {
|
|
30
26
|
"@scalar/express-api-reference": "^0.8.30",
|
|
@@ -36,7 +32,8 @@
|
|
|
36
32
|
"express-rate-limit": "^8.2.1",
|
|
37
33
|
"helmet": "^8.1.0",
|
|
38
34
|
"pino-pretty": "^13.1.3",
|
|
39
|
-
"prom-client": "^15.1.3"
|
|
35
|
+
"prom-client": "^15.1.3",
|
|
36
|
+
"reflect-metadata": "^0.2.2"
|
|
40
37
|
},
|
|
41
38
|
"peerDependencies": {
|
|
42
39
|
"express": "^5.1.0"
|
|
@@ -49,6 +46,9 @@
|
|
|
49
46
|
"engines": {
|
|
50
47
|
"node": ">=18.4"
|
|
51
48
|
},
|
|
49
|
+
"main": "index.cjs",
|
|
50
|
+
"module": "index.mjs",
|
|
51
|
+
"types": "index.d.ts",
|
|
52
52
|
"files": [
|
|
53
53
|
"**/*.mjs",
|
|
54
54
|
"**/*.cjs",
|
|
@@ -193,10 +193,10 @@
|
|
|
193
193
|
"require": "./url/index.cjs",
|
|
194
194
|
"types": "./url/index.d.ts"
|
|
195
195
|
},
|
|
196
|
-
"./
|
|
197
|
-
"import": "./
|
|
198
|
-
"require": "./
|
|
199
|
-
"types": "./
|
|
196
|
+
"./validation": {
|
|
197
|
+
"import": "./validation/index.mjs",
|
|
198
|
+
"require": "./validation/index.cjs",
|
|
199
|
+
"types": "./validation/index.d.ts"
|
|
200
200
|
}
|
|
201
201
|
}
|
|
202
202
|
}
|
package/performance/index.cjs
CHANGED
|
@@ -193,8 +193,8 @@ function memoize(fn, options = {}) {
|
|
|
193
193
|
__name(memoize, "memoize");
|
|
194
194
|
function trackMemoryUsage(fn, options = {}) {
|
|
195
195
|
const { log = false, label = fn.name || "anonymous function" } = options;
|
|
196
|
-
if (
|
|
197
|
-
|
|
196
|
+
if (globalThis.gc) {
|
|
197
|
+
globalThis.gc();
|
|
198
198
|
}
|
|
199
199
|
const beforeMemory = process.memoryUsage();
|
|
200
200
|
const result = fn();
|
package/performance/index.d.ts
CHANGED
|
@@ -22,4 +22,141 @@
|
|
|
22
22
|
* SOFTWARE.
|
|
23
23
|
*/
|
|
24
24
|
|
|
25
|
-
|
|
25
|
+
/**
|
|
26
|
+
* Options for timing function execution.
|
|
27
|
+
*/
|
|
28
|
+
interface TimingOptions {
|
|
29
|
+
/** Optional label for the timing (defaults to function name) */
|
|
30
|
+
label?: string;
|
|
31
|
+
/** Whether to log the timing (default: false) */
|
|
32
|
+
log?: boolean;
|
|
33
|
+
/** Log level to use if logging is enabled (default: 'debug') */
|
|
34
|
+
logLevel?: 'trace' | 'debug' | 'info' | 'warn' | 'error';
|
|
35
|
+
}
|
|
36
|
+
/**
|
|
37
|
+
* Result of a timing operation.
|
|
38
|
+
*/
|
|
39
|
+
interface TimingResult {
|
|
40
|
+
/** Duration in milliseconds */
|
|
41
|
+
durationMs: number;
|
|
42
|
+
/** Duration in seconds */
|
|
43
|
+
durationSec: number;
|
|
44
|
+
/** Start timestamp */
|
|
45
|
+
startTime: number;
|
|
46
|
+
/** End timestamp */
|
|
47
|
+
endTime: number;
|
|
48
|
+
/** Label used for the timing */
|
|
49
|
+
label: string;
|
|
50
|
+
}
|
|
51
|
+
/**
|
|
52
|
+
* Measure the execution time of a synchronous function.
|
|
53
|
+
*
|
|
54
|
+
* @param fn - Function to measure
|
|
55
|
+
* @param options - Timing options
|
|
56
|
+
* @returns Result containing the return value and timing information
|
|
57
|
+
*
|
|
58
|
+
* @example
|
|
59
|
+
* ```typescript
|
|
60
|
+
* const { result, timing } = timeSync(() => {
|
|
61
|
+
* // Some expensive operation
|
|
62
|
+
* return computeResult();
|
|
63
|
+
* }, { label: 'Computation', log: true });
|
|
64
|
+
*
|
|
65
|
+
* console.log(`Result: ${result}, took ${timing.durationMs}ms`);
|
|
66
|
+
* ```
|
|
67
|
+
*/
|
|
68
|
+
declare function timeSync<T>(fn: () => T, options?: TimingOptions): {
|
|
69
|
+
result: T;
|
|
70
|
+
timing: TimingResult;
|
|
71
|
+
};
|
|
72
|
+
/**
|
|
73
|
+
* Measure the execution time of an asynchronous function.
|
|
74
|
+
*
|
|
75
|
+
* @param fn - Async function to measure
|
|
76
|
+
* @param options - Timing options
|
|
77
|
+
* @returns Promise resolving to result and timing information
|
|
78
|
+
*
|
|
79
|
+
* @example
|
|
80
|
+
* ```typescript
|
|
81
|
+
* const { result, timing } = await timeAsync(async () => {
|
|
82
|
+
* // Some expensive async operation
|
|
83
|
+
* const data = await fetchData();
|
|
84
|
+
* return processData(data);
|
|
85
|
+
* }, { label: 'API Request', log: true });
|
|
86
|
+
*
|
|
87
|
+
* console.log(`Fetched ${result.length} items in ${timing.durationSec.toFixed(2)}s`);
|
|
88
|
+
* ```
|
|
89
|
+
*/
|
|
90
|
+
declare function timeAsync<T>(fn: () => Promise<T>, options?: TimingOptions): Promise<{
|
|
91
|
+
result: T;
|
|
92
|
+
timing: TimingResult;
|
|
93
|
+
}>;
|
|
94
|
+
/**
|
|
95
|
+
* Create a timing decorator for class methods.
|
|
96
|
+
*
|
|
97
|
+
* @param options - Timing options
|
|
98
|
+
* @returns Method decorator
|
|
99
|
+
*
|
|
100
|
+
* @example
|
|
101
|
+
* ```typescript
|
|
102
|
+
* class DataService {
|
|
103
|
+
* @timed({ log: true, logLevel: 'info' })
|
|
104
|
+
* async fetchData() {
|
|
105
|
+
* // ...implementation
|
|
106
|
+
* }
|
|
107
|
+
* }
|
|
108
|
+
* ```
|
|
109
|
+
*/
|
|
110
|
+
declare function timed(options?: TimingOptions): (target: any, propertyKeyOrContext: string | symbol | any, descriptor?: PropertyDescriptor) => void;
|
|
111
|
+
/**
|
|
112
|
+
* Memoize function results with optional TTL and max cache size.
|
|
113
|
+
*
|
|
114
|
+
* @param fn - Function to memoize
|
|
115
|
+
* @param options - Memoization options
|
|
116
|
+
* @returns Memoized function
|
|
117
|
+
*
|
|
118
|
+
* @example
|
|
119
|
+
* ```typescript
|
|
120
|
+
* // Cache results for 30 seconds, with a maximum of 100 entries
|
|
121
|
+
* const cachedFetch = memoize(
|
|
122
|
+
* async (url) => {
|
|
123
|
+
* const response = await fetch(url);
|
|
124
|
+
* return response.json();
|
|
125
|
+
* },
|
|
126
|
+
* { ttl: 30000, maxSize: 100, cacheKey: (url) => url }
|
|
127
|
+
* );
|
|
128
|
+
* ```
|
|
129
|
+
*/
|
|
130
|
+
declare function memoize<T, Args extends any[]>(fn: (...args: Args) => T, options?: {
|
|
131
|
+
/** Time-to-live in milliseconds (default: indefinite) */
|
|
132
|
+
ttl?: number;
|
|
133
|
+
/** Maximum cache size (default: unlimited) */
|
|
134
|
+
maxSize?: number;
|
|
135
|
+
/** Function to generate a cache key from arguments */
|
|
136
|
+
cacheKey?: (...args: Args) => string;
|
|
137
|
+
/** Auto-cleanup interval in milliseconds (default: disabled) */
|
|
138
|
+
autoCleanupMs?: number;
|
|
139
|
+
}): (...args: Args) => T;
|
|
140
|
+
/**
|
|
141
|
+
* Track memory usage for a function execution.
|
|
142
|
+
*
|
|
143
|
+
* @param fn - Function to track
|
|
144
|
+
* @param options - Memory tracking options
|
|
145
|
+
* @returns Result and memory usage information
|
|
146
|
+
*/
|
|
147
|
+
declare function trackMemoryUsage<T>(fn: () => T, options?: {
|
|
148
|
+
/** Whether to log the memory usage (default: false) */
|
|
149
|
+
log?: boolean;
|
|
150
|
+
/** Label for the memory tracking (default: function name) */
|
|
151
|
+
label?: string;
|
|
152
|
+
}): {
|
|
153
|
+
result: T;
|
|
154
|
+
memoryUsage: {
|
|
155
|
+
before: NodeJS.MemoryUsage;
|
|
156
|
+
after: NodeJS.MemoryUsage;
|
|
157
|
+
diff: Record<string, number>;
|
|
158
|
+
};
|
|
159
|
+
};
|
|
160
|
+
|
|
161
|
+
export { memoize, timeAsync, timeSync, timed, trackMemoryUsage };
|
|
162
|
+
export type { TimingOptions, TimingResult };
|
package/performance/index.mjs
CHANGED
|
@@ -191,8 +191,8 @@ function memoize(fn, options = {}) {
|
|
|
191
191
|
__name(memoize, "memoize");
|
|
192
192
|
function trackMemoryUsage(fn, options = {}) {
|
|
193
193
|
const { log = false, label = fn.name || "anonymous function" } = options;
|
|
194
|
-
if (
|
|
195
|
-
|
|
194
|
+
if (globalThis.gc) {
|
|
195
|
+
globalThis.gc();
|
|
196
196
|
}
|
|
197
197
|
const beforeMemory = process.memoryUsage();
|
|
198
198
|
const result = fn();
|
package/request/index.cjs
CHANGED