@catbee/utils 2.0.3 → 2.0.4

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/server/index.mjs CHANGED
@@ -298,42 +298,6 @@ var ServerConfigBuilder = class {
298
298
  return this.setEnabled("requestLogging", false);
299
299
  }
300
300
  /**
301
- * Configures server metrics collection and endpoints.
302
- *
303
- * @param opts - Metrics configuration options
304
- * @returns The builder instance for chaining
305
- * @default - { enable: false, path: '/metrics', withGlobalPrefix: false }
306
- *
307
- * @example
308
- * ```typescript
309
- * builder.withMetrics({
310
- * enable: true,
311
- * path: '/metrics'
312
- * })
313
- * ```
314
- */
315
- withMetrics(opts) {
316
- this.mergeConfig("metrics", opts);
317
- return this;
318
- }
319
- /**
320
- * Enables Prometheus metrics collection and endpoint
321
- *
322
- * @param opts - Optional metrics configuration
323
- * @returns The builder instance for chaining
324
- */
325
- enableMetrics(opts = {}) {
326
- return this.setEnabled("metrics", true, opts);
327
- }
328
- /**
329
- * Disables Prometheus metrics
330
- *
331
- * @returns The builder instance for chaining
332
- */
333
- disableMetrics() {
334
- return this.setEnabled("metrics", false);
335
- }
336
- /**
337
301
  * Configures server health check endpoint.
338
302
  *
339
303
  * @param opts - Health check configuration options
@@ -353,6 +317,19 @@ var ServerConfigBuilder = class {
353
317
  return this;
354
318
  }
355
319
  /**
320
+ * Enables health check endpoint with default or custom settings
321
+ * @param opts - Optional health check configuration
322
+ * @returns The builder instance for chaining
323
+ *
324
+ * @example
325
+ * ```typescript
326
+ * builder.disableHealthCheck()
327
+ * ```
328
+ */
329
+ disableHealthCheck() {
330
+ return this.setEnabled("healthCheck", false);
331
+ }
332
+ /**
356
333
  * Configures OpenAPI/Swagger documentation for the API.
357
334
  *
358
335
  * @param opts - OpenAPI configuration options
@@ -363,7 +340,7 @@ var ServerConfigBuilder = class {
363
340
  * ```typescript
364
341
  * builder.withOpenApi({
365
342
  * enable: true,
366
- * path: '/api-docs',
343
+ * mountPath: '/api-docs',
367
344
  * filePath: './openapi.yaml'
368
345
  * })
369
346
  * ```
@@ -703,15 +680,12 @@ var DependencyErrors = {
703
680
  compression: getDependencyErrorMessage("compression"),
704
681
  "express-rate-limit": getDependencyErrorMessage("express-rate-limit"),
705
682
  "cookie-parser": getDependencyErrorMessage("cookie-parser"),
706
- "@scalar/express-api-reference": getDependencyErrorMessage("@scalar/express-api-reference"),
707
- "prom-client": getDependencyErrorMessage("prom-client")
683
+ "@scalar/express-api-reference": getDependencyErrorMessage("@scalar/express-api-reference")
708
684
  };
709
685
  var ExpressServer = class {
710
686
  static {
711
687
  __name(this, "ExpressServer");
712
688
  }
713
- /** Prometheus client registry for metrics collection */
714
- register = null;
715
689
  /** HTTP server instance (null when not running) */
716
690
  server = null;
717
691
  /** Merged configuration with defaults applied */
@@ -730,16 +704,13 @@ var ExpressServer = class {
730
704
  connections = /* @__PURE__ */ new Set();
731
705
  /** Flag indicating if the server is shutting down */
732
706
  isShuttingDown = false;
707
+ /** Flag indicating if graceful shutdown handlers are registered */
708
+ gracefulShutdownRegistered = false;
733
709
  /**
734
710
  * Collection of registered health check functions.
735
711
  * These are executed when the health check endpoint is accessed.
736
712
  */
737
713
  healthChecks = [];
738
- /** Prometheus metrics for monitoring */
739
- requestCounter;
740
- routeTimings;
741
- requestSizes;
742
- clientIPs;
743
714
  /** Promise that resolves when initialization (middleware + routes) is complete */
744
715
  initPromise;
745
716
  /**
@@ -755,7 +726,6 @@ var ExpressServer = class {
755
726
  *
756
727
  * Default Monitoring:
757
728
  * - Request/Response logging
758
- * - Prometheus metrics
759
729
  * - Health checks
760
730
  * - Request tracing
761
731
  */
@@ -773,82 +743,6 @@ var ExpressServer = class {
773
743
  getLogger().error(msg);
774
744
  throw new Error(msg);
775
745
  }
776
- const safeAppName = (this.config.appName || "express_app").toLowerCase().replace(/[^a-z0-9_]/g, "_");
777
- if (this.config.metrics?.enable) {
778
- const client = optionalRequire("prom-client");
779
- if (!client) {
780
- this.throwDependancyError("prom-client");
781
- }
782
- this.register = new client.Registry();
783
- this.requestCounter = new client.Counter({
784
- name: `${safeAppName}_http_requests_total`,
785
- help: "Total HTTP requests",
786
- labelNames: [
787
- "method",
788
- "route",
789
- "status"
790
- ],
791
- registers: [
792
- this.register
793
- ]
794
- });
795
- this.routeTimings = new client.Histogram({
796
- name: `${safeAppName}_http_request_duration_seconds`,
797
- help: "Duration of HTTP requests by route",
798
- labelNames: [
799
- "method",
800
- "route",
801
- "status"
802
- ],
803
- buckets: [
804
- 0.1,
805
- 0.3,
806
- 0.5,
807
- 0.7,
808
- 1,
809
- 3,
810
- 5,
811
- 7,
812
- 10
813
- ],
814
- registers: [
815
- this.register
816
- ]
817
- });
818
- this.requestSizes = new client.Histogram({
819
- name: `${safeAppName}_http_request_size_bytes`,
820
- help: "Size of HTTP request bodies",
821
- labelNames: [
822
- "method",
823
- "route"
824
- ],
825
- buckets: [
826
- 100,
827
- 1e3,
828
- 1e4,
829
- 1e5,
830
- 1e6
831
- ],
832
- registers: [
833
- this.register
834
- ]
835
- });
836
- this.clientIPs = new client.Counter({
837
- name: `${safeAppName}_http_client_ip_total`,
838
- help: "Client IP request counter",
839
- labelNames: [
840
- "ip",
841
- "method"
842
- ],
843
- registers: [
844
- this.register
845
- ]
846
- });
847
- client.collectDefaultMetrics({
848
- register: this.register,
849
- prefix: `${safeAppName}_`
850
- });
851
- }
852
746
  if (config?.healthCheck?.checks) {
853
747
  this.healthChecks.push(...config.healthCheck.checks);
854
748
  }
@@ -921,7 +815,6 @@ var ExpressServer = class {
921
815
  this.setupBodyParsingMiddleware();
922
816
  this.setupCookieParsingMiddleware();
923
817
  await this.setupOpenApiMiddleware();
924
- this.setupMetricsMiddleware();
925
818
  }
926
819
  /**
927
820
  * Set up basic middleware (trust proxy, request ID, context).
@@ -944,6 +837,7 @@ var ExpressServer = class {
944
837
  if (this.isShuttingDown) {
945
838
  res.setHeader("Connection", "close");
946
839
  res.status(HttpStatusCodes.SERVICE_UNAVAILABLE).json(new ServiceUnavailableException("Server is shutting down"));
840
+ return;
947
841
  }
948
842
  next();
949
843
  });
@@ -955,7 +849,7 @@ var ExpressServer = class {
955
849
  if (this.config.helmet) {
956
850
  const helmet = optionalRequire("helmet");
957
851
  if (!helmet) {
958
- this.throwDependancyError("helmet");
852
+ this.throwDependencyError("helmet");
959
853
  }
960
854
  if (typeof this.config.helmet === "object") {
961
855
  this.app.use(helmet(this.config.helmet));
@@ -966,7 +860,7 @@ var ExpressServer = class {
966
860
  if (this.config.cors) {
967
861
  const cors = optionalRequire("cors");
968
862
  if (!cors) {
969
- this.throwDependancyError("cors");
863
+ this.throwDependencyError("cors");
970
864
  }
971
865
  this.app.use(cors(this.config.cors === true ? {} : this.config.cors));
972
866
  }
@@ -1018,7 +912,7 @@ var ExpressServer = class {
1018
912
  if (this.config.rateLimit?.enable) {
1019
913
  const rateLimit = optionalRequire("express-rate-limit");
1020
914
  if (!rateLimit) {
1021
- this.throwDependancyError("express-rate-limit");
915
+ this.throwDependencyError("express-rate-limit");
1022
916
  }
1023
917
  this.app.use(rateLimit({
1024
918
  windowMs: this.config.rateLimit.windowMs ?? 15 * 60 * 1e3,
@@ -1067,7 +961,7 @@ var ExpressServer = class {
1067
961
  if (this.config.compression) {
1068
962
  const compression = optionalRequire("compression");
1069
963
  if (!compression) {
1070
- this.throwDependancyError("compression");
964
+ this.throwDependencyError("compression");
1071
965
  }
1072
966
  if (typeof this.config.compression === "object") {
1073
967
  this.app.use(compression(this.config.compression));
@@ -1123,7 +1017,7 @@ var ExpressServer = class {
1123
1017
  if (this.config.cookieParser) {
1124
1018
  const cookieParser = optionalRequire("cookie-parser");
1125
1019
  if (!cookieParser) {
1126
- this.throwDependancyError("cookie-parser");
1020
+ this.throwDependencyError("cookie-parser");
1127
1021
  }
1128
1022
  if (typeof this.config.cookieParser === "object") {
1129
1023
  this.app.use(cookieParser(void 0, this.config.cookieParser));
@@ -1157,7 +1051,7 @@ var ExpressServer = class {
1157
1051
  }
1158
1052
  const apiReference = optionalRequire("@scalar/express-api-reference")?.apiReference;
1159
1053
  if (!apiReference) {
1160
- this.throwDependancyError("@scalar/express-api-reference", getDependencyErrorMessage("@scalar/express-api-reference", "OpenAPI docs"));
1054
+ this.throwDependencyError("@scalar/express-api-reference", getDependencyErrorMessage("@scalar/express-api-reference", "OpenAPI docs"));
1161
1055
  }
1162
1056
  this.app.use(openApiMountPath, apiReference({
1163
1057
  spec: {
@@ -1178,50 +1072,10 @@ var ExpressServer = class {
1178
1072
  }
1179
1073
  }
1180
1074
  /**
1181
- * Set up metrics tracking middleware.
1182
- */
1183
- setupMetricsMiddleware() {
1184
- if (this.config.metrics?.enable) {
1185
- this.app.use((req, res, next) => {
1186
- const start = process.hrtime();
1187
- this.clientIPs?.inc({
1188
- ip: req.ip,
1189
- method: req.method
1190
- });
1191
- const cl = req.headers["content-length"];
1192
- if (cl) {
1193
- const size = Number(cl);
1194
- if (!Number.isNaN(size) && size >= 0) {
1195
- const route = this.normalizeRouteForMetrics(req, res);
1196
- this.requestSizes?.observe({
1197
- method: req.method,
1198
- route
1199
- }, size);
1200
- }
1201
- }
1202
- res.once("finish", () => {
1203
- const [seconds, nanoseconds] = process.hrtime(start);
1204
- const finalRoute = this.normalizeRouteForMetrics(req, res);
1205
- this.requestCounter?.inc({
1206
- method: req.method,
1207
- route: finalRoute,
1208
- status: res.statusCode.toString()
1209
- });
1210
- this.routeTimings?.observe({
1211
- method: req.method,
1212
- route: finalRoute,
1213
- status: res.statusCode.toString()
1214
- }, seconds + nanoseconds / 1e9);
1215
- });
1216
- next();
1217
- });
1218
- }
1219
- }
1220
- /**
1221
1075
  * Configure server routes and error handling.
1222
1076
  * Sets up in following order:
1223
1077
  *
1224
- * 1. Built-in routes (health, metrics)
1078
+ * 1. Built-in routes (health)
1225
1079
  * 2. Application routes
1226
1080
  * 3. 404 handler
1227
1081
  * 4. Error handler
@@ -1231,13 +1085,6 @@ var ExpressServer = class {
1231
1085
  this.app.get(healthCheckPath, async (_req, res) => {
1232
1086
  return this.handleHealthCheckRequest(res);
1233
1087
  });
1234
- if (this.config.metrics?.enable) {
1235
- const metricsPath = this.normalizePath(this.config.metrics.path ?? "/metrics", this.config.metrics?.withGlobalPrefix);
1236
- this.app.get(metricsPath, async (_req, res) => {
1237
- res.set("Content-Type", this.register.contentType);
1238
- res.end(await this.register.metrics());
1239
- });
1240
- }
1241
1088
  const routerToUse = this.externalRouter || this.rootRouter;
1242
1089
  this.app.use(this.globalPrefix, routerToUse);
1243
1090
  await this.runHook("afterRoutes", this.app);
@@ -1384,6 +1231,10 @@ var ExpressServer = class {
1384
1231
  * @throws Error if server fails to start or port is already in use
1385
1232
  */
1386
1233
  async start() {
1234
+ if (this.server) {
1235
+ getLogger().warn("Server is already running, returning existing instance");
1236
+ return this.server;
1237
+ }
1387
1238
  await this.initPromise;
1388
1239
  await this.runHook("beforeStart", this.app);
1389
1240
  return new Promise((resolve, reject) => {
@@ -1456,12 +1307,9 @@ var ExpressServer = class {
1456
1307
  const host = this.formatHostForUrl(this.config.host || "localhost");
1457
1308
  const url = `${protocol}://${host}:${port}`;
1458
1309
  getLogger().info(`Server running on ${url}`);
1459
- if (this.config.healthCheck?.path) {
1310
+ if (this.config.healthCheck && this.config.healthCheck?.path) {
1460
1311
  getLogger().info(`Health check available at ${url}${this.normalizePath(this.config.healthCheck.path, this.config.healthCheck.withGlobalPrefix)}`);
1461
1312
  }
1462
- if (this.config.metrics?.enable && this.config.metrics.path) {
1463
- getLogger().info(`Metrics available at ${url}${this.normalizePath(this.config.metrics.path, this.config.metrics.withGlobalPrefix)}`);
1464
- }
1465
1313
  if (this.config.openApi?.enable) {
1466
1314
  getLogger().info(`API docs available at ${url}${this.normalizePath(this.config.openApi.mountPath, this.config.openApi.withGlobalPrefix)}`);
1467
1315
  }
@@ -1488,50 +1336,70 @@ var ExpressServer = class {
1488
1336
  return;
1489
1337
  }
1490
1338
  if (this.isShuttingDown) {
1491
- getLogger().warn("Stop called while shutdown is already in progress");
1339
+ getLogger().warn("Shutdown already in progress");
1492
1340
  return;
1493
1341
  }
1494
1342
  this.isShuttingDown = true;
1495
1343
  await this.runHook("beforeStop", this.server);
1496
1344
  try {
1497
- await this.gracefulShutdown();
1498
- } catch (err) {
1499
- getLogger().error({
1500
- err
1501
- }, "Graceful shutdown timed out");
1502
- if (force) {
1503
- getLogger().warn("Forcing connection destroy due to shutdown timeout");
1504
- }
1345
+ await this.gracefulShutdown(force);
1505
1346
  } finally {
1506
- await this.destroyConnections();
1347
+ this.isShuttingDown = false;
1507
1348
  }
1508
1349
  }
1509
1350
  /**
1510
1351
  * Perform graceful server shutdown with timeout.
1511
1352
  */
1512
- async gracefulShutdown() {
1353
+ async gracefulShutdown(force = false) {
1513
1354
  const shutdownTimeout = 1e4;
1355
+ const server = this.server;
1356
+ let timer;
1357
+ let afterStopCalled = false;
1358
+ const runAfterStop = /* @__PURE__ */ __name(async () => {
1359
+ if (afterStopCalled) return;
1360
+ afterStopCalled = true;
1361
+ await this.runHook("afterStop");
1362
+ }, "runAfterStop");
1514
1363
  const serverClosePromise = new Promise((resolve, reject) => {
1515
- this.server.close(async (err) => {
1364
+ server.close(async (err) => {
1365
+ if (timer) clearTimeout(timer);
1516
1366
  if (err) {
1517
1367
  getLogger().error({
1518
1368
  err
1519
- }, "Error while closing server");
1369
+ }, "Error during server shutdown");
1520
1370
  reject(err);
1521
1371
  return;
1522
1372
  }
1523
1373
  this.server = null;
1524
- this.isShuttingDown = false;
1525
1374
  getLogger().info("Server stopped gracefully");
1526
- await this.runHook("afterStop");
1375
+ await runAfterStop();
1527
1376
  resolve();
1528
1377
  });
1529
1378
  });
1530
- const timeoutPromise = new Promise((_, reject) => setTimeout(() => reject(new Error("Shutdown timeout")), shutdownTimeout));
1531
- await Promise.race([
1532
- serverClosePromise,
1533
- timeoutPromise
1534
- ]);
1379
+ const timeoutPromise = new Promise((_, reject) => {
1380
+ timer = setTimeout(() => reject(new Error("Shutdown timeout")), shutdownTimeout);
1381
+ });
1382
+ try {
1383
+ await Promise.race([
1384
+ serverClosePromise,
1385
+ timeoutPromise
1386
+ ]);
1387
+ } catch (err) {
1388
+ if (timer) clearTimeout(timer);
1389
+ getLogger().warn({
1390
+ err
1391
+ }, "Graceful shutdown timed out");
1392
+ if (!force) {
1393
+ throw err;
1394
+ }
1395
+ getLogger().warn("Escalating to forced shutdown");
1396
+ server.closeIdleConnections?.();
1397
+ server.closeAllConnections?.();
1398
+ await this.destroyConnections();
1399
+ this.server = null;
1400
+ getLogger().info("Forced shutdown completed");
1401
+ await runAfterStop();
1402
+ }
1535
1403
  }
1536
1404
  /**
1537
1405
  * Enable graceful shutdown on OS signals for production deployment.
@@ -1548,31 +1416,64 @@ var ExpressServer = class {
1548
1416
  "SIGINT",
1549
1417
  "SIGTERM"
1550
1418
  ]) {
1419
+ if (this.gracefulShutdownRegistered) {
1420
+ getLogger().warn("Graceful shutdown handlers are already registered");
1421
+ return this;
1422
+ }
1423
+ let signalHandled = false;
1551
1424
  signals.forEach((signal) => {
1552
1425
  process.on(signal, async () => {
1426
+ if (signalHandled) {
1427
+ getLogger().warn(`Ignoring duplicate ${signal}`);
1428
+ return;
1429
+ }
1430
+ signalHandled = true;
1553
1431
  getLogger().info(`Received ${signal}, initiating graceful shutdown...`);
1554
1432
  try {
1555
- await this.stop();
1433
+ await this.stop(true);
1556
1434
  process.exit(0);
1557
1435
  } catch (err) {
1558
- getLogger().error({
1436
+ getLogger().fatal({
1559
1437
  err
1560
- }, "Error during graceful shutdown, forcing stop...");
1561
- try {
1562
- await this.stop(true);
1563
- process.exit(1);
1564
- } catch (forceError) {
1565
- getLogger().fatal({
1566
- forceError
1567
- }, "Forced shutdown failed, exiting hard");
1568
- process.exit(1);
1569
- }
1438
+ }, "Shutdown failed");
1439
+ process.exit(1);
1570
1440
  }
1571
1441
  });
1572
1442
  });
1443
+ this.gracefulShutdownRegistered = true;
1573
1444
  return this;
1574
1445
  }
1575
1446
  /**
1447
+ * Destroy all active connections (gracefully if possible).
1448
+ * If a connection does not close cleanly, it will be force-destroyed.
1449
+ */
1450
+ async destroyConnections() {
1451
+ if (!this.connections.size) {
1452
+ return;
1453
+ }
1454
+ const sockets = [
1455
+ ...this.connections
1456
+ ];
1457
+ await Promise.allSettled(sockets.map((socket) => new Promise((resolve) => {
1458
+ socket.end();
1459
+ const timer = setTimeout(() => {
1460
+ socket.destroy();
1461
+ resolve();
1462
+ }, 1e3);
1463
+ socket.once("close", () => {
1464
+ clearTimeout(timer);
1465
+ resolve();
1466
+ });
1467
+ socket.once("error", () => {
1468
+ clearTimeout(timer);
1469
+ socket.destroy();
1470
+ resolve();
1471
+ });
1472
+ })));
1473
+ this.connections.clear();
1474
+ getLogger().info(`Closed ${sockets.length} active connection(s)`);
1475
+ }
1476
+ /**
1576
1477
  * Set an externally created base router.
1577
1478
  * This will override the internal rootRouter.
1578
1479
  */
@@ -1600,14 +1501,15 @@ var ExpressServer = class {
1600
1501
  */
1601
1502
  registerRoute(methods, path, ...handlers) {
1602
1503
  const fullPath = this.normalizePath(path, true);
1504
+ const routerToUse = this.externalRouter || this.rootRouter;
1603
1505
  const methodMap = {
1604
- get: this.app.get.bind(this.app),
1605
- post: this.app.post.bind(this.app),
1606
- put: this.app.put.bind(this.app),
1607
- delete: this.app.delete.bind(this.app),
1608
- patch: this.app.patch.bind(this.app),
1609
- options: this.app.options.bind(this.app),
1610
- head: this.app.head.bind(this.app)
1506
+ get: routerToUse.get.bind(routerToUse),
1507
+ post: routerToUse.post.bind(routerToUse),
1508
+ put: routerToUse.put.bind(routerToUse),
1509
+ delete: routerToUse.delete.bind(routerToUse),
1510
+ patch: routerToUse.patch.bind(routerToUse),
1511
+ options: routerToUse.options.bind(routerToUse),
1512
+ head: routerToUse.head.bind(routerToUse)
1611
1513
  };
1612
1514
  methods.forEach((m) => {
1613
1515
  const fn = methodMap[m];
@@ -1633,15 +1535,16 @@ var ExpressServer = class {
1633
1535
  * @returns This instance for method chaining
1634
1536
  */
1635
1537
  registerMiddleware(path, middleware) {
1538
+ const routerToUse = this.externalRouter || this.rootRouter;
1636
1539
  if (typeof path === "string") {
1637
1540
  const normalizedPath = this.normalizePath(path);
1638
1541
  if (normalizedPath) {
1639
- this.app.use(normalizedPath, middleware);
1542
+ routerToUse.use(normalizedPath, middleware);
1640
1543
  } else {
1641
- this.app.use(middleware);
1544
+ routerToUse.use(middleware);
1642
1545
  }
1643
1546
  } else {
1644
- this.app.use(path);
1547
+ routerToUse.use(path);
1645
1548
  }
1646
1549
  return this;
1647
1550
  }
@@ -1655,22 +1558,11 @@ var ExpressServer = class {
1655
1558
  */
1656
1559
  useMiddleware(...middlewares) {
1657
1560
  middlewares.forEach((middleware) => {
1658
- this.app.use(middleware);
1561
+ (this.externalRouter || this.rootRouter).use(middleware);
1659
1562
  });
1660
1563
  return this;
1661
1564
  }
1662
1565
  /**
1663
- * Get Prometheus registry (to add custom counters/histograms)
1664
- *
1665
- * @return {*} {client.Registry}
1666
- */
1667
- getMetricsRegistry() {
1668
- if (!this.config.metrics?.enable) {
1669
- getLogger().warn("Metrics are not enabled in the server configuration \nPlease enable metrics to use this feature.");
1670
- }
1671
- return this.register;
1672
- }
1673
- /**
1674
1566
  * Get server configuration
1675
1567
  *
1676
1568
  * @return {*} {CatbeeServerConfig}
@@ -1819,41 +1711,6 @@ var ExpressServer = class {
1819
1711
  }
1820
1712
  return sanitize(prefix + "/" + path);
1821
1713
  }
1822
- normalizeRouteForMetrics(req, res) {
1823
- if (req?.route?.path) {
1824
- return req.route.path;
1825
- }
1826
- if (res.statusCode === 404) return "/404";
1827
- const path = (req.path || "unknown").split("?")[0];
1828
- return path.replace(/\/[0-9]+/g, "/:id").replace(/\/[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}/g, "/:uuid");
1829
- }
1830
- /**
1831
- * Destroy all active connections (gracefully if possible).
1832
- * If a connection does not close cleanly, it will be force-destroyed.
1833
- */
1834
- async destroyConnections() {
1835
- const total = this.connections.size;
1836
- if (total === 0) {
1837
- getLogger().debug("No active connections to close");
1838
- return;
1839
- }
1840
- const timeoutMs = 5e3;
1841
- await Promise.race([
1842
- Promise.all(Array.from(this.connections).map((conn) => new Promise((resolve) => {
1843
- conn.end(() => {
1844
- if (!conn.destroyed) conn.destroy();
1845
- resolve();
1846
- });
1847
- conn.on("error", () => {
1848
- conn.destroy();
1849
- resolve();
1850
- });
1851
- }))),
1852
- new Promise((resolve) => setTimeout(resolve, timeoutMs))
1853
- ]);
1854
- this.connections.clear();
1855
- getLogger().info(`Closed ${total} active connections`);
1856
- }
1857
1714
  async validateHttpsFiles() {
1858
1715
  if (!await fileExists(this.config.https.key)) {
1859
1716
  const msg = `HTTPS key file not found: ${this.config.https.key}`;
@@ -1877,7 +1734,7 @@ var ExpressServer = class {
1877
1734
  }
1878
1735
  return false;
1879
1736
  }
1880
- throwDependancyError(packageName, msg) {
1737
+ throwDependencyError(packageName, msg) {
1881
1738
  getLogger().error({
1882
1739
  command: `npm install ${packageName}`
1883
1740
  }, msg || DependencyErrors[packageName]);
package/types/index.d.ts CHANGED
@@ -484,28 +484,6 @@ interface CatbeeServerConfig {
484
484
  */
485
485
  withGlobalPrefix?: boolean;
486
486
  };
487
- /** Prometheus metrics config
488
- * - **enable**: `false` - **env**: `SERVER_METRICS_ENABLE`
489
- * - **path**: `'/metrics'` - **env**: `SERVER_METRICS_PATH`
490
- * - **withGlobalPrefix**: `false` - **env**: `SERVER_METRICS_WITH_GLOBAL_PREFIX`
491
- */
492
- metrics?: {
493
- /** Enable metrics endpoint
494
- * - **default**: `false`
495
- * - **env**: `SERVER_METRICS_ENABLE`
496
- */
497
- enable: boolean;
498
- /** Metrics endpoint path
499
- * - **default**: `'/metrics'`
500
- * - **env**: `SERVER_METRICS_PATH`
501
- */
502
- path?: string;
503
- /** Apply global prefix
504
- * - **default**: `false`
505
- * - **env**: `SERVER_METRICS_WITH_GLOBAL_PREFIX`
506
- */
507
- withGlobalPrefix?: boolean;
508
- };
509
487
  /** Service version header config
510
488
  * - **enable**: `false` - **env**: `SERVER_SERVICE_VERSION_ENABLE`
511
489
  * - **headerName**: `'x-service-version'` - **env**: `SERVER_SERVICE_VERSION_HEADER_NAME`