@catbee/utils 1.0.1 → 1.0.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/build/index.mjs CHANGED
@@ -9,6 +9,7 @@ import { rateLimit as rateLimit$1 } from 'express-rate-limit';
9
9
  import os, { tmpdir } from 'os';
10
10
  import fsp from 'fs/promises';
11
11
  import { pipeline } from 'stream/promises';
12
+ import { Readable, Transform } from 'stream';
12
13
  import { URL as URL$1, URLSearchParams } from 'url';
13
14
  import express from 'express';
14
15
  import https from 'https';
@@ -1060,6 +1061,10 @@ var config = {
1060
1061
  */
1061
1062
  pretty: Env.getBoolean("LOGGER_PRETTY", true),
1062
1063
  /**
1064
+ * Enables colorized output for pretty-print (default: true)
1065
+ */
1066
+ colorize: Env.getBoolean("LOGGER_PRETTY_COLORIZE", true),
1067
+ /**
1063
1068
  * Single line output for pretty-print (default: false)
1064
1069
  */
1065
1070
  singleLine: Env.getBoolean("LOGGER_PRETTY_SINGLE_LINE", false)
@@ -1069,6 +1074,20 @@ var config = {
1069
1074
  * Default TTL (time to live) for cache entries in seconds
1070
1075
  */
1071
1076
  defaultTtl: Env.getNumber("CACHE_DEFAULT_TTL_SECONDS", 3600) * 1e3
1077
+ },
1078
+ server: {
1079
+ /**
1080
+ * Skip healthz endpoint even if health checks are configured
1081
+ * Default: false
1082
+ * Set to true to return 200 OK for /healthz without checks
1083
+ * Useful in environments where a simple liveness probe is needed
1084
+ * without performing actual health checks
1085
+ * Example: Kubernetes liveness probe
1086
+ * Note: This does not disable the health check functionality itself
1087
+ * Health checks can still be performed programmatically
1088
+ * or via other endpoints if needed
1089
+ */
1090
+ skipHealthz: Env.getBoolean("SERVER_SKIP_HEALTHZ", false)
1072
1091
  }
1073
1092
  };
1074
1093
  var defaultServerConfig = {
@@ -1672,10 +1691,10 @@ function setupLogger(isGlobal = true) {
1672
1691
  },
1673
1692
  timestamp: stdTimeFunctions.isoTime
1674
1693
  };
1675
- const logger2 = config.logger.pretty && Env.isDev() ? pino(logParams, pino.transport({
1694
+ const logger2 = config.logger.pretty ? pino(logParams, pino.transport({
1676
1695
  target: "pino-pretty",
1677
1696
  options: {
1678
- colorize: true,
1697
+ colorize: config.logger.colorize,
1679
1698
  translateTime: "SYS:standard",
1680
1699
  ignore: "pid,hostname",
1681
1700
  singleLine: config.logger.singleLine,
@@ -2492,6 +2511,234 @@ function verifySignedToken(token, secret) {
2492
2511
  }
2493
2512
  __name(verifySignedToken, "verifySignedToken");
2494
2513
 
2514
+ // src/utils/date.utils.ts
2515
+ function formatDate(date, options = {}) {
2516
+ const { format = "yyyy-MM-dd", locale, timeZone } = options;
2517
+ const d = date instanceof Date ? date : new Date(date);
2518
+ if (format === "yyyy-MM-dd") {
2519
+ const yyyy = d.getFullYear();
2520
+ const mm = String(d.getMonth() + 1).padStart(2, "0");
2521
+ const dd = String(d.getDate()).padStart(2, "0");
2522
+ return `${yyyy}-${mm}-${dd}`;
2523
+ }
2524
+ if (format === "yyyy-MM-dd HH:mm:ss") {
2525
+ const yyyy = d.getFullYear();
2526
+ const mm = String(d.getMonth() + 1).padStart(2, "0");
2527
+ const dd = String(d.getDate()).padStart(2, "0");
2528
+ const HH = String(d.getHours()).padStart(2, "0");
2529
+ const MM = String(d.getMinutes()).padStart(2, "0");
2530
+ const SS = String(d.getSeconds()).padStart(2, "0");
2531
+ return `${yyyy}-${mm}-${dd} ${HH}:${MM}:${SS}`;
2532
+ }
2533
+ if (format === "relative") {
2534
+ return formatRelativeTime(date);
2535
+ }
2536
+ return new Intl.DateTimeFormat(locale, {
2537
+ timeZone,
2538
+ year: format.includes("yyyy") || format.includes("y") ? "numeric" : void 0,
2539
+ month: format.includes("MM") || format.includes("M") ? "numeric" : void 0,
2540
+ day: format.includes("dd") || format.includes("d") ? "numeric" : void 0,
2541
+ hour: format.includes("HH") || format.includes("H") ? "numeric" : void 0,
2542
+ minute: format.includes("mm") || format.includes("m") ? "numeric" : void 0,
2543
+ second: format.includes("ss") || format.includes("s") ? "numeric" : void 0,
2544
+ hour12: !format.includes("HH") && !format.includes("H")
2545
+ }).format(d);
2546
+ }
2547
+ __name(formatDate, "formatDate");
2548
+ function formatRelativeTime(date, now = /* @__PURE__ */ new Date(), locale) {
2549
+ const d1 = date instanceof Date ? date : new Date(date);
2550
+ const d2 = now instanceof Date ? now : new Date(now);
2551
+ const diffMs = d1.getTime() - d2.getTime();
2552
+ const diffSecs = Math.round(diffMs / 1e3);
2553
+ const diffMins = Math.round(diffSecs / 60);
2554
+ const diffHours = Math.round(diffMins / 60);
2555
+ const diffDays = Math.round(diffHours / 24);
2556
+ const diffMonths = Math.round(diffDays / 30);
2557
+ const diffYears = Math.round(diffDays / 365);
2558
+ const formatter = new Intl.RelativeTimeFormat(locale, {
2559
+ numeric: "auto"
2560
+ });
2561
+ if (Math.abs(diffSecs) < 60) return formatter.format(diffSecs, "second");
2562
+ if (Math.abs(diffMins) < 60) return formatter.format(diffMins, "minute");
2563
+ if (Math.abs(diffHours) < 24) return formatter.format(diffHours, "hour");
2564
+ if (Math.abs(diffDays) < 30) return formatter.format(diffDays, "day");
2565
+ if (Math.abs(diffMonths) < 12) return formatter.format(diffMonths, "month");
2566
+ return formatter.format(diffYears, "year");
2567
+ }
2568
+ __name(formatRelativeTime, "formatRelativeTime");
2569
+ function parseDate(input, fallback) {
2570
+ if (typeof input === "number") {
2571
+ return new Date(input);
2572
+ }
2573
+ try {
2574
+ const date = new Date(input);
2575
+ if (isNaN(date.getTime())) {
2576
+ return fallback || null;
2577
+ }
2578
+ return date;
2579
+ } catch {
2580
+ return fallback || null;
2581
+ }
2582
+ }
2583
+ __name(parseDate, "parseDate");
2584
+ function dateDiff(date1, date2 = /* @__PURE__ */ new Date(), unit = "days") {
2585
+ const d1 = date1 instanceof Date ? date1 : new Date(date1);
2586
+ const d2 = date2 instanceof Date ? date2 : new Date(date2);
2587
+ const diffMs = d1.getTime() - d2.getTime();
2588
+ switch (unit) {
2589
+ case "milliseconds":
2590
+ return diffMs;
2591
+ case "seconds":
2592
+ return diffMs / 1e3;
2593
+ case "minutes":
2594
+ return diffMs / (1e3 * 60);
2595
+ case "hours":
2596
+ return diffMs / (1e3 * 60 * 60);
2597
+ case "days":
2598
+ return diffMs / (1e3 * 60 * 60 * 24);
2599
+ case "months":
2600
+ return (d1.getFullYear() - d2.getFullYear()) * 12 + d1.getMonth() - d2.getMonth();
2601
+ case "years":
2602
+ return d1.getFullYear() - d2.getFullYear();
2603
+ default:
2604
+ throw new Error(`Unsupported unit: ${unit}`);
2605
+ }
2606
+ }
2607
+ __name(dateDiff, "dateDiff");
2608
+ function addToDate(date, amount, unit) {
2609
+ const d = date instanceof Date ? new Date(date) : new Date(date);
2610
+ switch (unit) {
2611
+ case "milliseconds":
2612
+ d.setMilliseconds(d.getMilliseconds() + amount);
2613
+ break;
2614
+ case "seconds":
2615
+ d.setSeconds(d.getSeconds() + amount);
2616
+ break;
2617
+ case "minutes":
2618
+ d.setMinutes(d.getMinutes() + amount);
2619
+ break;
2620
+ case "hours":
2621
+ d.setHours(d.getHours() + amount);
2622
+ break;
2623
+ case "days":
2624
+ d.setDate(d.getDate() + amount);
2625
+ break;
2626
+ case "months": {
2627
+ const origDate = d.getDate();
2628
+ const origMonth = d.getMonth();
2629
+ d.setDate(1);
2630
+ d.setMonth(origMonth + amount);
2631
+ const lastDay = new Date(d.getFullYear(), d.getMonth() + 1, 0).getDate();
2632
+ d.setDate(Math.min(origDate, lastDay));
2633
+ break;
2634
+ }
2635
+ case "years":
2636
+ d.setFullYear(d.getFullYear() + amount);
2637
+ break;
2638
+ default:
2639
+ throw new Error(`Unsupported unit: ${unit}`);
2640
+ }
2641
+ return d;
2642
+ }
2643
+ __name(addToDate, "addToDate");
2644
+ function startOf(date, unit) {
2645
+ const d = date instanceof Date ? new Date(date) : new Date(date);
2646
+ switch (unit) {
2647
+ case "second":
2648
+ d.setMilliseconds(0);
2649
+ break;
2650
+ case "minute":
2651
+ d.setSeconds(0, 0);
2652
+ break;
2653
+ case "hour":
2654
+ d.setMinutes(0, 0, 0);
2655
+ break;
2656
+ case "day":
2657
+ d.setHours(0, 0, 0, 0);
2658
+ break;
2659
+ case "week":
2660
+ d.setHours(0, 0, 0, 0);
2661
+ d.setDate(d.getDate() - d.getDay());
2662
+ break;
2663
+ case "month":
2664
+ d.setDate(1);
2665
+ d.setHours(0, 0, 0, 0);
2666
+ break;
2667
+ case "quarter":
2668
+ d.setMonth(Math.floor(d.getMonth() / 3) * 3, 1);
2669
+ d.setHours(0, 0, 0, 0);
2670
+ break;
2671
+ case "year":
2672
+ d.setMonth(0, 1);
2673
+ d.setHours(0, 0, 0, 0);
2674
+ break;
2675
+ default:
2676
+ throw new Error(`Unsupported unit: ${unit}`);
2677
+ }
2678
+ return d;
2679
+ }
2680
+ __name(startOf, "startOf");
2681
+ function endOf(date, unit) {
2682
+ const d = date instanceof Date ? new Date(date) : new Date(date);
2683
+ switch (unit) {
2684
+ case "second":
2685
+ d.setMilliseconds(999);
2686
+ break;
2687
+ case "minute":
2688
+ d.setSeconds(59, 999);
2689
+ break;
2690
+ case "hour":
2691
+ d.setMinutes(59, 59, 999);
2692
+ break;
2693
+ case "day":
2694
+ d.setHours(23, 59, 59, 999);
2695
+ break;
2696
+ case "week":
2697
+ d.setDate(d.getDate() - d.getDay() + 6);
2698
+ d.setHours(23, 59, 59, 999);
2699
+ break;
2700
+ case "month":
2701
+ d.setMonth(d.getMonth() + 1, 0);
2702
+ d.setHours(23, 59, 59, 999);
2703
+ break;
2704
+ case "quarter":
2705
+ d.setMonth(Math.floor(d.getMonth() / 3) * 3 + 3, 0);
2706
+ d.setHours(23, 59, 59, 999);
2707
+ break;
2708
+ case "year":
2709
+ d.setMonth(11, 31);
2710
+ d.setHours(23, 59, 59, 999);
2711
+ break;
2712
+ default:
2713
+ throw new Error(`Unsupported unit: ${unit}`);
2714
+ }
2715
+ return d;
2716
+ }
2717
+ __name(endOf, "endOf");
2718
+ function isBetween(date, start, end, inclusive = true) {
2719
+ const d = date instanceof Date ? date.getTime() : date;
2720
+ const s = start instanceof Date ? start.getTime() : start;
2721
+ const e = end instanceof Date ? end.getTime() : end;
2722
+ return inclusive ? d >= s && d <= e : d > s && d < e;
2723
+ }
2724
+ __name(isBetween, "isBetween");
2725
+ function isLeapYear(year) {
2726
+ const y = year instanceof Date ? year.getFullYear() : year;
2727
+ return y % 4 === 0 && y % 100 !== 0 || y % 400 === 0;
2728
+ }
2729
+ __name(isLeapYear, "isLeapYear");
2730
+ function daysInMonth(year, month) {
2731
+ if (year instanceof Date) {
2732
+ month = year.getMonth();
2733
+ year = year.getFullYear();
2734
+ }
2735
+ if (month === void 0) {
2736
+ throw new Error("Month is required when year is a number");
2737
+ }
2738
+ return new Date(year, month + 1, 0).getDate();
2739
+ }
2740
+ __name(daysInMonth, "daysInMonth");
2741
+
2495
2742
  // src/utils/response.utils.ts
2496
2743
  var SuccessResponse = class {
2497
2744
  static {
@@ -3515,7 +3762,7 @@ function registerControllers(router, controllers) {
3515
3762
  diContainer.register(ControllerClass);
3516
3763
  }
3517
3764
  const instance = diContainer.get(ControllerClass);
3518
- const basePath = Reflect.getMetadata("basePath", ControllerClass) || "";
3765
+ let basePath = Reflect.getMetadata("basePath", ControllerClass) || "";
3519
3766
  const routes = Reflect.getMetadata(ROUTES_KEY, ControllerClass) || [];
3520
3767
  const controllerRateLimit = Reflect.getMetadata(RATE_LIMIT_KEY, ControllerClass);
3521
3768
  const controllerCache = Reflect.getMetadata(CACHE_KEY, ControllerClass);
@@ -3528,6 +3775,9 @@ function registerControllers(router, controllers) {
3528
3775
  const controllerBeforeHooks = Reflect.getMetadata(BEFORE_KEY, ControllerClass) || [];
3529
3776
  const controllerAfterHooks = Reflect.getMetadata(AFTER_KEY, ControllerClass) || [];
3530
3777
  const controllerContentType = Reflect.getMetadata(CONTENT_TYPE_KEY, ControllerClass);
3778
+ if (controllerVersion?.options?.addPrefix) {
3779
+ basePath = `/${controllerVersion.version}${basePath || ""}`;
3780
+ }
3531
3781
  routes.forEach(({ path: path3, method, handlerName }) => {
3532
3782
  const methodMiddlewares = Reflect.getMetadata(MIDDLEWARE_KEY, instance, handlerName) || [];
3533
3783
  const params = Reflect.getMetadata(PARAMS_KEY, instance, handlerName) || [];
@@ -3557,7 +3807,8 @@ function registerControllers(router, controllers) {
3557
3807
  const roles = Reflect.getMetadata(ROLES_KEY, instance, handlerName) || controllerRoles || [];
3558
3808
  const cache = Reflect.getMetadata(CACHE_KEY, instance, handlerName) || controllerCache;
3559
3809
  const rateLimitOptions = Reflect.getMetadata(RATE_LIMIT_KEY, instance, handlerName) || controllerRateLimit;
3560
- const version = Reflect.getMetadata(VERSION_KEY, instance, handlerName) || controllerVersion;
3810
+ const methodVersion = Reflect.getMetadata(VERSION_KEY, instance, handlerName);
3811
+ const version = methodVersion || controllerVersion;
3561
3812
  const timeout2 = Reflect.getMetadata(TIMEOUT_KEY, instance, handlerName) || controllerTimeout;
3562
3813
  const logConfig = Reflect.getMetadata(LOG_KEY, instance, handlerName) || controllerLogConfig;
3563
3814
  let rateLimiter = null;
@@ -3571,8 +3822,8 @@ function registerControllers(router, controllers) {
3571
3822
  }
3572
3823
  }
3573
3824
  let finalPath = path3;
3574
- if (version?.options?.addPrefix) {
3575
- finalPath = `/${version.version}${path3}`;
3825
+ if (methodVersion?.options?.addPrefix && methodVersion.version !== controllerVersion?.version) {
3826
+ finalPath = `/${methodVersion.version}${path3}`;
3576
3827
  }
3577
3828
  const handler = /* @__PURE__ */ __name(async (req, res, next) => {
3578
3829
  req["startTime"] = Date.now();
@@ -4561,6 +4812,202 @@ function healthCheck(options) {
4561
4812
  }
4562
4813
  __name(healthCheck, "healthCheck");
4563
4814
 
4815
+ // src/utils/performance.utils.ts
4816
+ function timeSync(fn, options = {}) {
4817
+ const { label = fn.name || "anonymous function", log = false, logLevel = "debug" } = options;
4818
+ const startTime = performance.now();
4819
+ const result = fn();
4820
+ const endTime = performance.now();
4821
+ const durationMs = endTime - startTime;
4822
+ const durationSec = durationMs / 1e3;
4823
+ const timing = {
4824
+ durationMs,
4825
+ durationSec,
4826
+ startTime,
4827
+ endTime,
4828
+ label
4829
+ };
4830
+ if (log) {
4831
+ const logger2 = getLogger();
4832
+ const message = `${label} completed in ${durationMs.toFixed(2)}ms`;
4833
+ switch (logLevel) {
4834
+ case "trace":
4835
+ logger2.trace({
4836
+ timing
4837
+ }, message);
4838
+ break;
4839
+ case "debug":
4840
+ logger2.debug({
4841
+ timing
4842
+ }, message);
4843
+ break;
4844
+ case "info":
4845
+ logger2.info({
4846
+ timing
4847
+ }, message);
4848
+ break;
4849
+ case "warn":
4850
+ logger2.warn({
4851
+ timing
4852
+ }, message);
4853
+ break;
4854
+ case "error":
4855
+ logger2.error({
4856
+ timing
4857
+ }, message);
4858
+ break;
4859
+ default:
4860
+ logger2.debug({
4861
+ timing
4862
+ }, message);
4863
+ break;
4864
+ }
4865
+ }
4866
+ return {
4867
+ result,
4868
+ timing
4869
+ };
4870
+ }
4871
+ __name(timeSync, "timeSync");
4872
+ async function timeAsync(fn, options = {}) {
4873
+ const { label = fn.name || "anonymous async function", log = false, logLevel = "debug" } = options;
4874
+ const startTime = performance.now();
4875
+ const result = await fn();
4876
+ const endTime = performance.now();
4877
+ const durationMs = endTime - startTime;
4878
+ const durationSec = durationMs / 1e3;
4879
+ const timing = {
4880
+ durationMs,
4881
+ durationSec,
4882
+ startTime,
4883
+ endTime,
4884
+ label
4885
+ };
4886
+ if (log) {
4887
+ const logger2 = getLogger();
4888
+ const message = `${label} completed in ${durationMs.toFixed(2)}ms`;
4889
+ switch (logLevel) {
4890
+ case "trace":
4891
+ logger2.trace({
4892
+ timing
4893
+ }, message);
4894
+ break;
4895
+ case "debug":
4896
+ logger2.debug({
4897
+ timing
4898
+ }, message);
4899
+ break;
4900
+ case "info":
4901
+ logger2.info({
4902
+ timing
4903
+ }, message);
4904
+ break;
4905
+ case "warn":
4906
+ logger2.warn({
4907
+ timing
4908
+ }, message);
4909
+ break;
4910
+ case "error":
4911
+ logger2.error({
4912
+ timing
4913
+ }, message);
4914
+ break;
4915
+ default:
4916
+ logger2.debug({
4917
+ timing
4918
+ }, message);
4919
+ break;
4920
+ }
4921
+ }
4922
+ return {
4923
+ result,
4924
+ timing
4925
+ };
4926
+ }
4927
+ __name(timeAsync, "timeAsync");
4928
+ function timed(options = {}) {
4929
+ return function(target, propertyKeyOrContext, descriptor) {
4930
+ let propertyKey;
4931
+ let actualDescriptor;
4932
+ if (typeof propertyKeyOrContext === "object" && propertyKeyOrContext !== null && "name" in propertyKeyOrContext) {
4933
+ propertyKey = propertyKeyOrContext.name;
4934
+ actualDescriptor = descriptor ?? Object.getOwnPropertyDescriptor(target, propertyKey);
4935
+ } else {
4936
+ propertyKey = propertyKeyOrContext;
4937
+ actualDescriptor = descriptor ?? Object.getOwnPropertyDescriptor(target, propertyKey);
4938
+ }
4939
+ const originalMethod = actualDescriptor.value;
4940
+ actualDescriptor.value = function(...args) {
4941
+ const methodOptions = {
4942
+ ...options,
4943
+ label: options.label || `${target.constructor.name}.${String(propertyKey)}`
4944
+ };
4945
+ if (originalMethod.constructor.name === "AsyncFunction") {
4946
+ return timeAsync(() => originalMethod.apply(this, args), methodOptions).then(({ result }) => result);
4947
+ } else {
4948
+ return timeSync(() => originalMethod.apply(this, args), methodOptions).result;
4949
+ }
4950
+ };
4951
+ if (descriptor) {
4952
+ descriptor.value = actualDescriptor.value;
4953
+ } else {
4954
+ Object.defineProperty(target, propertyKey, actualDescriptor);
4955
+ }
4956
+ };
4957
+ }
4958
+ __name(timed, "timed");
4959
+ function memoize(fn, options = {}) {
4960
+ const { ttl, maxSize, autoCleanupMs, cacheKey = /* @__PURE__ */ __name((...args) => JSON.stringify(args), "cacheKey") } = options;
4961
+ const cache = new TTLCache({
4962
+ ttlMs: ttl,
4963
+ maxSize,
4964
+ autoCleanupMs
4965
+ });
4966
+ return function(...args) {
4967
+ const key = cacheKey(...args);
4968
+ const cachedValue = cache.get(key);
4969
+ if (cachedValue !== void 0) {
4970
+ return cachedValue;
4971
+ }
4972
+ const value = fn(...args);
4973
+ cache.set(key, value);
4974
+ return value;
4975
+ };
4976
+ }
4977
+ __name(memoize, "memoize");
4978
+ function trackMemoryUsage(fn, options = {}) {
4979
+ const { log = false, label = fn.name || "anonymous function" } = options;
4980
+ if (global.gc) {
4981
+ global.gc();
4982
+ }
4983
+ const beforeMemory = process.memoryUsage();
4984
+ const result = fn();
4985
+ const afterMemory = process.memoryUsage();
4986
+ const diff = {};
4987
+ for (const key in afterMemory) {
4988
+ if (Object.prototype.hasOwnProperty.call(afterMemory, key)) {
4989
+ diff[key] = afterMemory[key] - beforeMemory[key];
4990
+ }
4991
+ }
4992
+ if (log) {
4993
+ getLogger().info({
4994
+ label,
4995
+ memoryBefore: beforeMemory,
4996
+ memoryAfter: afterMemory,
4997
+ memoryDiff: diff
4998
+ }, `Memory usage for ${label}`);
4999
+ }
5000
+ return {
5001
+ result,
5002
+ memoryUsage: {
5003
+ before: beforeMemory,
5004
+ after: afterMemory,
5005
+ diff
5006
+ }
5007
+ };
5008
+ }
5009
+ __name(trackMemoryUsage, "trackMemoryUsage");
5010
+
4564
5011
  // src/utils/request.utils.ts
4565
5012
  var getPaginationParams = /* @__PURE__ */ __name((req) => {
4566
5013
  const query = req.query;
@@ -4719,6 +5166,120 @@ function extractFilterParams(query, allowedFilters) {
4719
5166
  return filters;
4720
5167
  }
4721
5168
  __name(extractFilterParams, "extractFilterParams");
5169
+ function bufferToStream(data) {
5170
+ const readable = new Readable();
5171
+ readable.push(data);
5172
+ readable.push(null);
5173
+ return readable;
5174
+ }
5175
+ __name(bufferToStream, "bufferToStream");
5176
+ async function streamToBuffer(stream) {
5177
+ return new Promise((resolve2, reject) => {
5178
+ const chunks = [];
5179
+ stream.on("data", (chunk2) => chunks.push(Buffer.isBuffer(chunk2) ? chunk2 : Buffer.from(chunk2)));
5180
+ stream.on("end", () => resolve2(Buffer.concat(chunks)));
5181
+ stream.on("error", reject);
5182
+ });
5183
+ }
5184
+ __name(streamToBuffer, "streamToBuffer");
5185
+ async function streamToString(stream, encoding = "utf8") {
5186
+ const buffer = await streamToBuffer(stream);
5187
+ return buffer.toString(encoding);
5188
+ }
5189
+ __name(streamToString, "streamToString");
5190
+ function createThrottleStream(bytesPerSecond) {
5191
+ let bytesSent = 0;
5192
+ let startTime = Date.now();
5193
+ return new Transform({
5194
+ transform(chunk2, _encoding, callback) {
5195
+ const elapsedSeconds = (Date.now() - startTime) / 1e3;
5196
+ const targetBytes = bytesPerSecond * elapsedSeconds;
5197
+ const chunkSize = chunk2.length;
5198
+ if (bytesSent + chunkSize <= targetBytes) {
5199
+ bytesSent += chunkSize;
5200
+ callback(null, chunk2);
5201
+ return;
5202
+ }
5203
+ const delay = ((bytesSent + chunkSize) / bytesPerSecond - elapsedSeconds) * 1e3;
5204
+ setTimeout(() => {
5205
+ bytesSent += chunkSize;
5206
+ callback(null, chunk2);
5207
+ }, delay);
5208
+ }
5209
+ });
5210
+ }
5211
+ __name(createThrottleStream, "createThrottleStream");
5212
+ function createBatchStream(size, options = {}) {
5213
+ const objectMode = options.objectMode !== false;
5214
+ let batch = [];
5215
+ let buffers = [];
5216
+ let bufferSize = 0;
5217
+ return new Transform({
5218
+ objectMode,
5219
+ transform(chunk2, _encoding, callback) {
5220
+ if (objectMode) {
5221
+ batch.push(chunk2);
5222
+ if (batch.length >= size) {
5223
+ this.push(batch);
5224
+ batch = [];
5225
+ }
5226
+ } else {
5227
+ const buffer = Buffer.isBuffer(chunk2) ? chunk2 : Buffer.from(chunk2);
5228
+ buffers.push(buffer);
5229
+ bufferSize += buffer.length;
5230
+ let combined = Buffer.concat(buffers, bufferSize);
5231
+ while (combined.length >= size) {
5232
+ this.push(combined.slice(0, size));
5233
+ combined = combined.slice(size);
5234
+ }
5235
+ buffers = combined.length > 0 ? [
5236
+ combined
5237
+ ] : [];
5238
+ bufferSize = combined.length;
5239
+ }
5240
+ callback();
5241
+ },
5242
+ flush(callback) {
5243
+ if (objectMode && batch.length > 0) {
5244
+ this.push(batch);
5245
+ } else if (!objectMode && buffers.length > 0 && bufferSize > 0) {
5246
+ let combined = Buffer.concat(buffers, bufferSize);
5247
+ while (combined.length >= size) {
5248
+ this.push(combined.slice(0, size));
5249
+ combined = combined.slice(size);
5250
+ }
5251
+ if (combined.length > 0) {
5252
+ this.push(combined);
5253
+ }
5254
+ }
5255
+ callback();
5256
+ }
5257
+ });
5258
+ }
5259
+ __name(createBatchStream, "createBatchStream");
5260
+ function createLineStream(options = {}) {
5261
+ const { encoding = "utf8", includeNewlines = false } = options;
5262
+ let buffer = "";
5263
+ return new Transform({
5264
+ objectMode: true,
5265
+ transform(chunk2, _encoding, callback) {
5266
+ const str = buffer + (Buffer.isBuffer(chunk2) ? chunk2.toString(encoding) : chunk2);
5267
+ const lines = str.split(/\r?\n/);
5268
+ buffer = lines.pop() || "";
5269
+ for (const line of lines) {
5270
+ this.push(includeNewlines ? line + "\n" : line);
5271
+ }
5272
+ callback();
5273
+ },
5274
+ flush(callback) {
5275
+ if (buffer) {
5276
+ this.push(buffer);
5277
+ }
5278
+ callback();
5279
+ }
5280
+ });
5281
+ }
5282
+ __name(createLineStream, "createLineStream");
4722
5283
 
4723
5284
  // src/utils/string.utils.ts
4724
5285
  function capitalize(str) {
@@ -4778,6 +5339,84 @@ function countOccurrences(str, substring, caseSensitive = true) {
4778
5339
  return str.split(substring).length - 1;
4779
5340
  }
4780
5341
  __name(countOccurrences, "countOccurrences");
5342
+
5343
+ // src/utils/type.utils.ts
5344
+ function isPrimitiveType(value, type) {
5345
+ if (type === "array") {
5346
+ return Array.isArray(value);
5347
+ }
5348
+ if (type === "null") {
5349
+ return value === null;
5350
+ }
5351
+ if (type === "undefined") {
5352
+ return value === void 0;
5353
+ }
5354
+ if (type === "object") {
5355
+ return typeof value === "object" && value !== null && !Array.isArray(value);
5356
+ }
5357
+ return typeof value === type;
5358
+ }
5359
+ __name(isPrimitiveType, "isPrimitiveType");
5360
+ function getTypeOf(value) {
5361
+ if (value === null) return "null";
5362
+ if (value === void 0) return "undefined";
5363
+ if (Array.isArray(value)) return "array";
5364
+ return typeof value;
5365
+ }
5366
+ __name(getTypeOf, "getTypeOf");
5367
+ function isArrayOf(value, itemTypeGuard) {
5368
+ if (!Array.isArray(value)) return false;
5369
+ return value.every((item) => itemTypeGuard(item));
5370
+ }
5371
+ __name(isArrayOf, "isArrayOf");
5372
+ function toStr(value, defaultValue = "") {
5373
+ if (value === null || value === void 0) return defaultValue;
5374
+ try {
5375
+ if (typeof value === "object") {
5376
+ return JSON.stringify(value);
5377
+ }
5378
+ return String(value);
5379
+ } catch {
5380
+ return defaultValue;
5381
+ }
5382
+ }
5383
+ __name(toStr, "toStr");
5384
+ function toNum(value, defaultValue = 0) {
5385
+ if (value === null || value === void 0) return defaultValue;
5386
+ if (typeof value === "number") return value;
5387
+ try {
5388
+ const num = Number(value);
5389
+ return isNaN(num) ? defaultValue : num;
5390
+ } catch {
5391
+ return defaultValue;
5392
+ }
5393
+ }
5394
+ __name(toNum, "toNum");
5395
+ function toBool(value, defaultValue = false) {
5396
+ if (value === null || value === void 0) return defaultValue;
5397
+ if (typeof value === "boolean") return value;
5398
+ if (typeof value === "string") {
5399
+ const lowercased = value.toLowerCase();
5400
+ if (lowercased === "true" || lowercased === "yes" || lowercased === "y" || lowercased === "1") {
5401
+ return true;
5402
+ }
5403
+ if (lowercased === "false" || lowercased === "no" || lowercased === "n" || lowercased === "0") {
5404
+ return false;
5405
+ }
5406
+ }
5407
+ if (typeof value === "number") {
5408
+ return value !== 0;
5409
+ }
5410
+ return defaultValue;
5411
+ }
5412
+ __name(toBool, "toBool");
5413
+ function ensureType(value, expectedType, defaultValue) {
5414
+ if (getTypeOf(value) === expectedType) {
5415
+ return value;
5416
+ }
5417
+ return defaultValue;
5418
+ }
5419
+ __name(ensureType, "ensureType");
4781
5420
  function appendQueryParams(url, params) {
4782
5421
  const urlObj = new URL$1(url);
4783
5422
  for (const [key, value] of Object.entries(params)) {
@@ -6167,7 +6806,7 @@ var ExpressServer = class _ExpressServer {
6167
6806
  const healthCheckPath = this.normalizePath(this.config.healthCheck?.path || "/healthz", this.config.healthCheck?.withGlobalPrefix);
6168
6807
  this.app.get(healthCheckPath, async (_req, res) => {
6169
6808
  try {
6170
- if (!this.healthChecks.length) {
6809
+ if (!this.healthChecks.length || config.server.skipHealthz) {
6171
6810
  return res.status(HttpStatusCodes.OK).json(new SuccessResponse("OK"));
6172
6811
  }
6173
6812
  const checkResults = await Promise.allSettled(this.healthChecks.map(async ({ name, check }) => {
@@ -6632,4 +7271,4 @@ var ExpressServer = class _ExpressServer {
6632
7271
  }
6633
7272
  };
6634
7273
 
6635
- export { After, BUILD_MARKER, BadGatewayException, BadRequestException, Before, Body, Cache, CircuitBreakerOpenError, CircuitBreakerState, ConflictException, Connect, ContentType, ContextStore, Controller, DIContainer, Delete, Env, Environment, ErrorResponse, ExpressServer, ForbiddenException, GatewayTimeoutException, Get, Head, Header, Headers, HttpCode, HttpError, HttpStatusCodes, Inject, Injectable, InsufficientStorageException, InternalServerErrorException, Log, MethodNotAllowedException, NoContentResponse, NotAcceptableException, NotFoundException, Options, PaginatedResponse, Param, Patch, PayloadTooLargeException, Post, Put, Query, RateLimit, Redirect, RedirectResponse, Req, ReqCookie, ReqHeader, ReqId, ReqLogger, RequestTimeoutException, Res, Roles, ServerConfigBuilder, ServiceUnavailableException, SortDirection, StoreKeys, SuccessResponse, TTLCache, Timeout, TooManyRequestsException, Trace, TypedContextKey, UnauthorizedException, UnprocessableEntityException, UnsupportedMediaTypeException, Use, Version, _globalThis, abortable, addRedactFields, addSensitiveFields, appendQueryParams, appendTextFile, capitalize, chunk, circuitBreaker, compact, copyDir, copyFile, countBy, countOccurrences, createChildLogger, createDeferred, createDirectory, createErrorResponse, createFinalErrorResponse, createHttpError, createPaginatedResponse, createParamDecorator, createParamDecoratorWithoutParam, createRequestLogger, createSignedToken, createSuccessResponse, createTaskQueue, createTempDir, createTempFile, createUrlBuilder, debounce, decrypt, deepFreeze, deepObjMerge, defaultSensitiveFields, deleteDirRecursive, deleteFileIfExists, difference, emptyDir, encrypt, ensureDir, ensureEmptyDir, equalsIgnoreCase, errorHandler, extractFilterParams, extractPaginationParams, extractQueryParams, extractSortParams, fileExists, filterObject, findFilesByPattern, findInDir, findNewestFile, findOldestFile, flattenDeep, flattenObject, generateApiKey, generateRandomBytes, generateRandomBytesAsString, getAllPaths, getConfig, getDirSize, getDirStats, getDomain, getErrorMessage, getExtension, getFileSize, getFileStats, getFromContext, getLogger, getPaginationParams, getRedactCensor, getRequestId, getSubdirectories, getValueByPath, groupBy, hasErrorShape, hasRequiredProps, hash, healthCheck, hmac, inject, intersect, isAlpha, isAlphanumeric, isArray, isBase64, isCreditCard, isDateInRange, isDirectory, isEmail, isEqual, isFile, isHexColor, isHttpError, isIPv4, isIPv6, isISODate, isLengthBetween, isNumberBetween, isNumeric, isObjEmpty, isObject, isPhone, isPlainObject, isPort, isStrongPassword, isURL, isUUID, isValidJSON, isValidUrl, joinPaths, listFiles, logError, logger, mapObject, mask, matchesPattern, md5, memoizeAsync, mergeSort, moveDir, moveFile, nanoId, normalizeUrl, omit, parseBooleanParam, parseNumberParam, parseQueryString, parseTypedQueryParams, partition, pick, pluck, random, randomBase64, randomHex, randomInt, randomString, range, rateLimit, readDirectory, readFileBuffer, readJsonFile, readTextFile, redact, registerControllers, removeQueryParams, requestId, responseTime, retry, reverse, runInBatches, runInSeries, runWithConcurrency, safeCompare, safeReadJsonFile, sendResponse, setConfig, setRedactCensor, setSensitiveFields, setValueByPath, settleAll, setupRequestContext, sha1, sha256, sha256Hmac, shuffle, singletonAsync, sleep, slugify, streamFile, stripHtml, take, takeWhile, throttle, timeout, toCamelCase, toKebabCase, toPascalCase, toSnakeCase, truncate, unique, uuid, validateAll, verifySignedToken, walkDir, watchDir, watchDirRecursive, waterfall, withErrorHandling, withTimeout, writeJsonFile, writeTextFile, zip };
7274
+ export { After, BUILD_MARKER, BadGatewayException, BadRequestException, Before, Body, Cache, CircuitBreakerOpenError, CircuitBreakerState, ConflictException, Connect, ContentType, ContextStore, Controller, DIContainer, Delete, Env, Environment, ErrorResponse, ExpressServer, ForbiddenException, GatewayTimeoutException, Get, Head, Header, Headers, HttpCode, HttpError, HttpStatusCodes, Inject, Injectable, InsufficientStorageException, InternalServerErrorException, Log, MethodNotAllowedException, NoContentResponse, NotAcceptableException, NotFoundException, Options, PaginatedResponse, Param, Patch, PayloadTooLargeException, Post, Put, Query, RateLimit, Redirect, RedirectResponse, Req, ReqCookie, ReqHeader, ReqId, ReqLogger, RequestTimeoutException, Res, Roles, ServerConfigBuilder, ServiceUnavailableException, SortDirection, StoreKeys, SuccessResponse, TTLCache, Timeout, TooManyRequestsException, Trace, TypedContextKey, UnauthorizedException, UnprocessableEntityException, UnsupportedMediaTypeException, Use, Version, _globalThis, abortable, addRedactFields, addSensitiveFields, addToDate, appendQueryParams, appendTextFile, bufferToStream, capitalize, chunk, circuitBreaker, compact, copyDir, copyFile, countBy, countOccurrences, createBatchStream, createChildLogger, createDeferred, createDirectory, createErrorResponse, createFinalErrorResponse, createHttpError, createLineStream, createPaginatedResponse, createParamDecorator, createParamDecoratorWithoutParam, createRequestLogger, createSignedToken, createSuccessResponse, createTaskQueue, createTempDir, createTempFile, createThrottleStream, createUrlBuilder, dateDiff, daysInMonth, debounce, decrypt, deepFreeze, deepObjMerge, defaultSensitiveFields, deleteDirRecursive, deleteFileIfExists, difference, emptyDir, encrypt, endOf, ensureDir, ensureEmptyDir, ensureType, equalsIgnoreCase, errorHandler, extractFilterParams, extractPaginationParams, extractQueryParams, extractSortParams, fileExists, filterObject, findFilesByPattern, findInDir, findNewestFile, findOldestFile, flattenDeep, flattenObject, formatDate, formatRelativeTime, generateApiKey, generateRandomBytes, generateRandomBytesAsString, getAllPaths, getConfig, getDirSize, getDirStats, getDomain, getErrorMessage, getExtension, getFileSize, getFileStats, getFromContext, getLogger, getPaginationParams, getRedactCensor, getRequestId, getSubdirectories, getTypeOf, getValueByPath, groupBy, hasErrorShape, hasRequiredProps, hash, healthCheck, hmac, inject, intersect, isAlpha, isAlphanumeric, isArray, isArrayOf, isBase64, isBetween, isCreditCard, isDateInRange, isDirectory, isEmail, isEqual, isFile, isHexColor, isHttpError, isIPv4, isIPv6, isISODate, isLeapYear, isLengthBetween, isNumberBetween, isNumeric, isObjEmpty, isObject, isPhone, isPlainObject, isPort, isPrimitiveType, isStrongPassword, isURL, isUUID, isValidJSON, isValidUrl, joinPaths, listFiles, logError, logger, mapObject, mask, matchesPattern, md5, memoize, memoizeAsync, mergeSort, moveDir, moveFile, nanoId, normalizeUrl, omit, parseBooleanParam, parseDate, parseNumberParam, parseQueryString, parseTypedQueryParams, partition, pick, pluck, random, randomBase64, randomHex, randomInt, randomString, range, rateLimit, readDirectory, readFileBuffer, readJsonFile, readTextFile, redact, registerControllers, removeQueryParams, requestId, responseTime, retry, reverse, runInBatches, runInSeries, runWithConcurrency, safeCompare, safeReadJsonFile, sendResponse, setConfig, setRedactCensor, setSensitiveFields, setValueByPath, settleAll, setupRequestContext, sha1, sha256, sha256Hmac, shuffle, singletonAsync, sleep, slugify, startOf, streamFile, streamToBuffer, streamToString, stripHtml, take, takeWhile, throttle, timeAsync, timeSync, timed, timeout, toBool, toCamelCase, toKebabCase, toNum, toPascalCase, toSnakeCase, toStr, trackMemoryUsage, truncate, unique, uuid, validateAll, verifySignedToken, walkDir, watchDir, watchDirRecursive, waterfall, withErrorHandling, withTimeout, writeJsonFile, writeTextFile, zip };