@exyconn/common 2.3.3 → 2.3.5

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/dist/index.js CHANGED
@@ -2,10 +2,11 @@
2
2
 
3
3
  var winston = require('winston');
4
4
  var DailyRotateFile = require('winston-daily-rotate-file');
5
- var path = require('path');
5
+ var path2 = require('path');
6
6
  var mongoose = require('mongoose');
7
7
  var jwt = require('jsonwebtoken');
8
8
  var fs = require('fs');
9
+ var os = require('os');
9
10
  var rateLimit = require('express-rate-limit');
10
11
  var axios = require('axios');
11
12
  var react = require('react');
@@ -37,9 +38,11 @@ function _interopNamespace(e) {
37
38
 
38
39
  var winston__default = /*#__PURE__*/_interopDefault(winston);
39
40
  var DailyRotateFile__default = /*#__PURE__*/_interopDefault(DailyRotateFile);
40
- var path__default = /*#__PURE__*/_interopDefault(path);
41
+ var path2__default = /*#__PURE__*/_interopDefault(path2);
41
42
  var mongoose__default = /*#__PURE__*/_interopDefault(mongoose);
42
43
  var jwt__default = /*#__PURE__*/_interopDefault(jwt);
44
+ var fs__default = /*#__PURE__*/_interopDefault(fs);
45
+ var os__default = /*#__PURE__*/_interopDefault(os);
43
46
  var rateLimit__default = /*#__PURE__*/_interopDefault(rateLimit);
44
47
  var axios__default = /*#__PURE__*/_interopDefault(axios);
45
48
  var Yup__namespace = /*#__PURE__*/_interopNamespace(Yup);
@@ -89,12 +92,14 @@ __export(server_exports, {
89
92
  createCorsOptions: () => createCorsOptions,
90
93
  createCrudControllers: () => createCrudControllers,
91
94
  createDdosRateLimiter: () => createDdosRateLimiter,
95
+ createHealthHandler: () => createHealthHandler,
92
96
  createLogger: () => createLogger,
93
97
  createMorganStream: () => createMorganStream,
94
98
  createMultiBrandCorsOptions: () => createMultiBrandCorsOptions,
95
99
  createPaginationMiddleware: () => createPaginationMiddleware,
96
100
  createPrefixedKeyGenerator: () => createPrefixedKeyGenerator,
97
101
  createRateLimiter: () => createRateLimiter,
102
+ createRootHandler: () => createRootHandler,
98
103
  createStandardRateLimiter: () => createStandardRateLimiter,
99
104
  createStrictRateLimiter: () => createStrictRateLimiter,
100
105
  createUserKeyGenerator: () => createUserKeyGenerator,
@@ -108,6 +113,7 @@ __export(server_exports, {
108
113
  extractSchemaMeta: () => extractSchemaMeta,
109
114
  forbiddenResponse: () => forbiddenResponse,
110
115
  formatPackageCheckResult: () => formatPackageCheckResult,
116
+ generateHealthResponse: () => generateHealthResponse,
111
117
  generateNcuCommand: () => generateNcuCommand,
112
118
  getConnectionStatus: () => getConnectionStatus,
113
119
  getDatabaseOptions: () => getDatabaseOptions,
@@ -352,7 +358,7 @@ var createLogger = (config = {}) => {
352
358
  }),
353
359
  // Combined logs (all levels)
354
360
  new DailyRotateFile__default.default({
355
- filename: path__default.default.join(finalConfig.logsDir, "combined-%DATE%.log"),
361
+ filename: path2__default.default.join(finalConfig.logsDir, "combined-%DATE%.log"),
356
362
  datePattern: "YYYY-MM-DD",
357
363
  maxSize: finalConfig.maxSize,
358
364
  maxFiles: finalConfig.maxFiles,
@@ -360,7 +366,7 @@ var createLogger = (config = {}) => {
360
366
  }),
361
367
  // Error logs only
362
368
  new DailyRotateFile__default.default({
363
- filename: path__default.default.join(finalConfig.logsDir, "error-%DATE%.log"),
369
+ filename: path2__default.default.join(finalConfig.logsDir, "error-%DATE%.log"),
364
370
  datePattern: "YYYY-MM-DD",
365
371
  level: "error",
366
372
  maxSize: finalConfig.maxSize,
@@ -1315,7 +1321,7 @@ async function loadPackageJson(source) {
1315
1321
  }
1316
1322
  return response.json();
1317
1323
  }
1318
- const filePath = path.resolve(source);
1324
+ const filePath = path2.resolve(source);
1319
1325
  if (!fs.existsSync(filePath)) {
1320
1326
  throw new Error(`File not found: ${filePath}`);
1321
1327
  }
@@ -1469,6 +1475,150 @@ var packageCheckServer = {
1469
1475
  generateNcuCommand,
1470
1476
  print: printPackageCheckSummary
1471
1477
  };
1478
+ var serverStartTime = Date.now();
1479
+ function getTimezoneOffset() {
1480
+ const offset = (/* @__PURE__ */ new Date()).getTimezoneOffset();
1481
+ const hours = Math.floor(Math.abs(offset) / 60);
1482
+ const minutes = Math.abs(offset) % 60;
1483
+ const sign = offset <= 0 ? "+" : "-";
1484
+ return `${sign}${hours.toString().padStart(2, "0")}:${minutes.toString().padStart(2, "0")}`;
1485
+ }
1486
+ function getTimezoneName() {
1487
+ try {
1488
+ return Intl.DateTimeFormat().resolvedOptions().timeZone;
1489
+ } catch {
1490
+ return "UTC";
1491
+ }
1492
+ }
1493
+ function getPackageInfo(criticalPackages = []) {
1494
+ try {
1495
+ const possiblePaths = [
1496
+ path2__default.default.join(process.cwd(), "package.json"),
1497
+ path2__default.default.join(__dirname, "..", "..", "..", "..", "package.json"),
1498
+ path2__default.default.join(__dirname, "..", "..", "package.json")
1499
+ ];
1500
+ for (const pkgPath of possiblePaths) {
1501
+ if (fs__default.default.existsSync(pkgPath)) {
1502
+ const pkg = JSON.parse(fs__default.default.readFileSync(pkgPath, "utf-8"));
1503
+ const deps = pkg.dependencies || {};
1504
+ const devDeps = pkg.devDependencies || {};
1505
+ const total = Object.keys(deps).length + Object.keys(devDeps).length;
1506
+ const critical = {};
1507
+ for (const pkgName of criticalPackages) {
1508
+ if (deps[pkgName]) {
1509
+ critical[pkgName] = deps[pkgName].replace("^", "").replace("~", "");
1510
+ }
1511
+ }
1512
+ return { total, critical };
1513
+ }
1514
+ }
1515
+ } catch {
1516
+ }
1517
+ return { total: 0, critical: {} };
1518
+ }
1519
+ async function generateHealthResponse(config) {
1520
+ const startTime = Date.now();
1521
+ const now = /* @__PURE__ */ new Date();
1522
+ let dependencies = {};
1523
+ if (config.checkDependencies) {
1524
+ try {
1525
+ dependencies = await config.checkDependencies();
1526
+ } catch {
1527
+ dependencies = { error: "DOWN" };
1528
+ }
1529
+ }
1530
+ const hasDownDep = Object.values(dependencies).includes("DOWN");
1531
+ const status = hasDownDep ? "DEGRADED" : "UP";
1532
+ const defaultCriticalPackages = ["express", "mongoose", "cors", "dotenv"];
1533
+ const packageInfo = getPackageInfo(config.criticalPackages || defaultCriticalPackages);
1534
+ const totalMem = os__default.default.totalmem();
1535
+ const freeMem = os__default.default.freemem();
1536
+ const usedMem = totalMem - freeMem;
1537
+ const isProduction2 = process.env.NODE_ENV === "production";
1538
+ const serverUrl = isProduction2 ? `https://${config.domain}` : `http://localhost:${config.port}`;
1539
+ const response = {
1540
+ status,
1541
+ app: config.name,
1542
+ env: process.env.NODE_ENV || "development",
1543
+ version: config.version,
1544
+ urls: {
1545
+ ...config.uiUrl && { ui: config.uiUrl },
1546
+ server: config.serverUrl || serverUrl,
1547
+ health: `${config.serverUrl || serverUrl}/health`
1548
+ },
1549
+ time: {
1550
+ serverTime: now.toISOString(),
1551
+ timezone: getTimezoneName(),
1552
+ offset: getTimezoneOffset(),
1553
+ epoch: Math.floor(now.getTime() / 1e3)
1554
+ },
1555
+ uptimeSec: Math.floor((Date.now() - serverStartTime) / 1e3),
1556
+ node: {
1557
+ version: process.version,
1558
+ platform: os__default.default.platform(),
1559
+ arch: os__default.default.arch()
1560
+ },
1561
+ system: {
1562
+ hostname: os__default.default.hostname(),
1563
+ memoryUsedMB: Math.round(usedMem / 1024 / 1024),
1564
+ memoryTotalMB: Math.round(totalMem / 1024 / 1024),
1565
+ memoryFreePercent: Math.round(freeMem / totalMem * 100),
1566
+ cpuLoad: os__default.default.loadavg().map((l) => Math.round(l * 100) / 100),
1567
+ cpuCount: os__default.default.cpus().length
1568
+ },
1569
+ packages: {
1570
+ appVersion: config.version,
1571
+ totalDependencies: packageInfo.total,
1572
+ critical: packageInfo.critical
1573
+ },
1574
+ dependencies,
1575
+ ...config.infra && { infra: config.infra },
1576
+ responseTimeMs: Date.now() - startTime
1577
+ };
1578
+ return response;
1579
+ }
1580
+ function createHealthHandler(config) {
1581
+ return async (_req, res) => {
1582
+ try {
1583
+ const health = await generateHealthResponse(config);
1584
+ const statusCode2 = health.status === "UP" ? 200 : health.status === "DEGRADED" ? 200 : 503;
1585
+ res.status(statusCode2).json(health);
1586
+ } catch (error) {
1587
+ res.status(503).json({
1588
+ status: "DOWN",
1589
+ app: config.name,
1590
+ env: process.env.NODE_ENV || "development",
1591
+ version: config.version,
1592
+ error: error instanceof Error ? error.message : "Unknown error",
1593
+ time: {
1594
+ serverTime: (/* @__PURE__ */ new Date()).toISOString(),
1595
+ timezone: getTimezoneName(),
1596
+ offset: getTimezoneOffset(),
1597
+ epoch: Math.floor(Date.now() / 1e3)
1598
+ }
1599
+ });
1600
+ }
1601
+ };
1602
+ }
1603
+ function createRootHandler(config) {
1604
+ return async (_req, res) => {
1605
+ try {
1606
+ const health = await generateHealthResponse(config);
1607
+ res.json({
1608
+ message: `Welcome to ${config.name}`,
1609
+ description: config.description || `${config.name} API Server`,
1610
+ ...config.endpoints && { endpoints: config.endpoints },
1611
+ ...health
1612
+ });
1613
+ } catch (error) {
1614
+ res.status(503).json({
1615
+ status: "DOWN",
1616
+ app: config.name,
1617
+ error: error instanceof Error ? error.message : "Unknown error"
1618
+ });
1619
+ }
1620
+ };
1621
+ }
1472
1622
 
1473
1623
  // src/server/configs/cors.config.ts
1474
1624
  var DEFAULT_CORS_CONFIG = {
@@ -2153,7 +2303,9 @@ __export(client_exports, {
2153
2303
  camelToKebab: () => camelToKebab,
2154
2304
  capitalize: () => capitalize,
2155
2305
  capitalizeWords: () => capitalizeWords,
2306
+ clearCustomHeaders: () => clearCustomHeaders,
2156
2307
  clientLogger: () => clientLogger,
2308
+ configureHttp: () => configureHttp,
2157
2309
  contactFormSchema: () => contactFormSchema,
2158
2310
  copyToClipboard: () => copyToClipboard,
2159
2311
  createClientLogger: () => createClientLogger,
@@ -2188,8 +2340,12 @@ __export(client_exports, {
2188
2340
  generateSlug: () => generateSlug,
2189
2341
  generateSnakeSlug: () => generateSnakeSlug,
2190
2342
  generateUrlSlug: () => generateUrlSlug,
2343
+ getApiBaseUrl: () => getApiBaseUrl,
2344
+ getApiPrefix: () => getApiPrefix,
2191
2345
  getContrastColor: () => getContrastColor,
2346
+ getCustomHeaders: () => getCustomHeaders,
2192
2347
  getErrorMessage: () => getErrorMessage,
2348
+ getHttpConfig: () => getHttpConfig,
2193
2349
  getNextPage: () => getNextPage,
2194
2350
  getPrevPage: () => getPrevPage,
2195
2351
  getRequest: () => getRequest,
@@ -2224,9 +2380,15 @@ __export(client_exports, {
2224
2380
  putRequest: () => putRequest,
2225
2381
  registerFormSchema: () => registerFormSchema,
2226
2382
  removeCssVars: () => removeCssVars,
2383
+ removeCustomHeader: () => removeCustomHeader,
2384
+ resetHttpConfig: () => resetHttpConfig,
2227
2385
  resolveThemeMode: () => resolveThemeMode,
2228
2386
  safeJsonParse: () => safeJsonParse,
2229
2387
  saveThemeMode: () => saveThemeMode,
2388
+ setApiBaseUrl: () => setApiBaseUrl,
2389
+ setApiPrefix: () => setApiPrefix,
2390
+ setCustomHeader: () => setCustomHeader,
2391
+ setCustomHeaders: () => setCustomHeaders,
2230
2392
  simpleMetaParseResponse: () => simpleMetaParseResponse,
2231
2393
  simpleParseDualDataResponse: () => simpleParseDualDataResponse,
2232
2394
  simpleParseResponse: () => simpleParseResponse,
@@ -2515,9 +2677,9 @@ var parsePaginatedResponse = (response) => {
2515
2677
  return { items: [], total: 0, page: 1, limit: 10 };
2516
2678
  }
2517
2679
  };
2518
- var extractNestedData = (response, path2, fallback = null) => {
2680
+ var extractNestedData = (response, path3, fallback = null) => {
2519
2681
  try {
2520
- const keys = path2.split(".");
2682
+ const keys = path3.split(".");
2521
2683
  let current = response;
2522
2684
  for (const key of keys) {
2523
2685
  if (current && typeof current === "object" && key in current) {
@@ -2639,17 +2801,97 @@ var simpleParseDualDataResponse = (response) => {
2639
2801
  };
2640
2802
 
2641
2803
  // src/client/http/http.ts
2642
- var isDevelopment2 = typeof window !== "undefined" && window.location.hostname === "localhost";
2643
- var API_BASE_URL = isDevelopment2 ? "http://localhost:4002" : "https://service-api.exyconn.com";
2644
- var API_PREFIX = "/v1/api";
2645
- var axiosInstance = axios__default.default.create({
2646
- baseURL: API_BASE_URL,
2804
+ var defaultConfig2 = {
2805
+ baseUrl: typeof window !== "undefined" && window.location.hostname === "localhost" ? "http://localhost:4002" : "https://service-api.exyconn.com",
2806
+ apiPrefix: "/v1/api",
2647
2807
  timeout: 3e4,
2648
- // 30 seconds
2808
+ defaultHeaders: {}
2809
+ };
2810
+ var currentConfig = { ...defaultConfig2 };
2811
+ var axiosInstance = axios__default.default.create({
2812
+ baseURL: defaultConfig2.baseUrl,
2813
+ timeout: defaultConfig2.timeout,
2649
2814
  headers: {
2650
2815
  "Content-Type": "application/json"
2651
2816
  }
2652
2817
  });
2818
+ var getApiBaseUrl = () => {
2819
+ return currentConfig.baseUrl || defaultConfig2.baseUrl;
2820
+ };
2821
+ var setApiBaseUrl = (baseUrl) => {
2822
+ currentConfig.baseUrl = baseUrl;
2823
+ axiosInstance.defaults.baseURL = baseUrl;
2824
+ logger2.info(`API Base URL updated to: ${baseUrl}`);
2825
+ };
2826
+ var getApiPrefix = () => {
2827
+ return currentConfig.apiPrefix || defaultConfig2.apiPrefix;
2828
+ };
2829
+ var setApiPrefix = (prefix) => {
2830
+ currentConfig.apiPrefix = prefix;
2831
+ logger2.info(`API Prefix updated to: ${prefix}`);
2832
+ };
2833
+ var getCustomHeaders = () => {
2834
+ return { ...currentConfig.defaultHeaders };
2835
+ };
2836
+ var setCustomHeader = (key, value) => {
2837
+ if (!currentConfig.defaultHeaders) {
2838
+ currentConfig.defaultHeaders = {};
2839
+ }
2840
+ currentConfig.defaultHeaders[key] = value;
2841
+ axiosInstance.defaults.headers.common[key] = value;
2842
+ logger2.info(`Custom header added: ${key}`);
2843
+ };
2844
+ var removeCustomHeader = (key) => {
2845
+ if (currentConfig.defaultHeaders) {
2846
+ delete currentConfig.defaultHeaders[key];
2847
+ }
2848
+ delete axiosInstance.defaults.headers.common[key];
2849
+ logger2.info(`Custom header removed: ${key}`);
2850
+ };
2851
+ var setCustomHeaders = (headers) => {
2852
+ currentConfig.defaultHeaders = { ...currentConfig.defaultHeaders, ...headers };
2853
+ Object.entries(headers).forEach(([key, value]) => {
2854
+ axiosInstance.defaults.headers.common[key] = value;
2855
+ });
2856
+ logger2.info(`Multiple custom headers added: ${Object.keys(headers).join(", ")}`);
2857
+ };
2858
+ var clearCustomHeaders = () => {
2859
+ if (currentConfig.defaultHeaders) {
2860
+ Object.keys(currentConfig.defaultHeaders).forEach((key) => {
2861
+ delete axiosInstance.defaults.headers.common[key];
2862
+ });
2863
+ }
2864
+ currentConfig.defaultHeaders = {};
2865
+ logger2.info("All custom headers cleared");
2866
+ };
2867
+ var configureHttp = (config) => {
2868
+ if (config.baseUrl) {
2869
+ setApiBaseUrl(config.baseUrl);
2870
+ }
2871
+ if (config.apiPrefix) {
2872
+ setApiPrefix(config.apiPrefix);
2873
+ }
2874
+ if (config.timeout !== void 0) {
2875
+ currentConfig.timeout = config.timeout;
2876
+ axiosInstance.defaults.timeout = config.timeout;
2877
+ }
2878
+ if (config.defaultHeaders) {
2879
+ setCustomHeaders(config.defaultHeaders);
2880
+ }
2881
+ logger2.info("HTTP client configured successfully");
2882
+ };
2883
+ var getHttpConfig = () => {
2884
+ return { ...currentConfig };
2885
+ };
2886
+ var resetHttpConfig = () => {
2887
+ currentConfig = { ...defaultConfig2 };
2888
+ axiosInstance.defaults.baseURL = defaultConfig2.baseUrl;
2889
+ axiosInstance.defaults.timeout = defaultConfig2.timeout;
2890
+ clearCustomHeaders();
2891
+ logger2.info("HTTP configuration reset to defaults");
2892
+ };
2893
+ var API_BASE_URL = getApiBaseUrl();
2894
+ var API_PREFIX = getApiPrefix();
2653
2895
  axiosInstance.interceptors.request.use(
2654
2896
  (config) => {
2655
2897
  try {
@@ -2682,7 +2924,10 @@ axiosInstance.interceptors.response.use(
2682
2924
  var buildHeaders = (customHeaders) => {
2683
2925
  const headers = {
2684
2926
  "Content-Type": "application/json",
2927
+ ...currentConfig.defaultHeaders,
2928
+ // Add global custom headers
2685
2929
  ...customHeaders
2930
+ // Request-specific headers override global ones
2686
2931
  };
2687
2932
  return headers;
2688
2933
  };
@@ -6568,11 +6813,11 @@ function getContrastColor(hex) {
6568
6813
  }
6569
6814
  function flattenToCssVars(obj, prefix = "--ec") {
6570
6815
  const result = {};
6571
- function flatten(current, path2 = []) {
6816
+ function flatten(current, path3 = []) {
6572
6817
  for (const key in current) {
6573
6818
  if (Object.prototype.hasOwnProperty.call(current, key)) {
6574
6819
  const value = current[key];
6575
- const newPath = [...path2, key];
6820
+ const newPath = [...path3, key];
6576
6821
  const varName = `${prefix}-${newPath.join("-")}`;
6577
6822
  if (value && typeof value === "object" && !Array.isArray(value)) {
6578
6823
  flatten(value, newPath);
@@ -6830,8 +7075,8 @@ function ThemeProvider({
6830
7075
  );
6831
7076
  return /* @__PURE__ */ jsxRuntime.jsx(ThemeContext.Provider, { value: contextValue, children });
6832
7077
  }
6833
- function cssVar(path2, prefix = "--ec") {
6834
- return `var(${prefix}-${path2.replace(/\./g, "-")})`;
7078
+ function cssVar(path3, prefix = "--ec") {
7079
+ return `var(${prefix}-${path3.replace(/\./g, "-")})`;
6835
7080
  }
6836
7081
  function useThemeValue(selector) {
6837
7082
  const { theme } = useTheme();