@lucaapp/service-utils 5.9.0 → 5.10.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.
@@ -1,20 +1,10 @@
1
1
  import { Api } from '../../api/api';
2
2
  import { PgBossService } from '../service';
3
+ import type { Middleware } from '../../api/types/middleware';
3
4
  /**
4
- * Mounts pg-boss dashboard API routes onto an Api instance.
5
- *
6
- * Endpoints:
7
- * - GET /queues — list queues with stats
8
- * - GET /queues/:name/jobs — list jobs in a queue
9
- * - GET /queues/:queue/jobs/:id — job detail
10
- * - POST /queues/:queue/jobs/:id/retry — retry a job
11
- * - POST /queues/:queue/jobs/:id/cancel — cancel a job
12
- * - DELETE /queues/:queue/jobs/:id — delete a job
13
- * - GET /schedules — list cron schedules
14
- * - POST /schedules — create a schedule
15
- * - PUT /schedules/:name — update a schedule
16
- * - DELETE /schedules/:name — delete a schedule
17
- * - POST /queues/:name/jobs — enqueue a new job
18
- * - GET /warnings — recent warnings
5
+ * Express path prefix for every pg-boss admin route. `Api.child()` only
6
+ * affects OpenAPI documentation, not the underlying express router, so the
7
+ * prefix MUST live on each path string to make routing work end-to-end.
19
8
  */
20
- export declare const mountPgBossApiRoutes: (api: Api, service: PgBossService) => void;
9
+ export declare const PGBOSS_API_PATH_PREFIX = "/support/pgboss";
10
+ export declare const mountPgBossApiRoutes: (api: Api, service: PgBossService, middlewares?: Middleware<any, any, any, any, any, any>[]) => void;
@@ -1,37 +1,30 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.mountPgBossApiRoutes = void 0;
3
+ exports.mountPgBossApiRoutes = exports.PGBOSS_API_PATH_PREFIX = void 0;
4
4
  const send_1 = require("../../api/send");
5
5
  const response_1 = require("../../api/response");
6
6
  const routes_schema_1 = require("./routes.schema");
7
7
  /**
8
- * Mounts pg-boss dashboard API routes onto an Api instance.
9
- *
10
- * Endpoints:
11
- * - GET /queues — list queues with stats
12
- * - GET /queues/:name/jobs — list jobs in a queue
13
- * - GET /queues/:queue/jobs/:id — job detail
14
- * - POST /queues/:queue/jobs/:id/retry — retry a job
15
- * - POST /queues/:queue/jobs/:id/cancel — cancel a job
16
- * - DELETE /queues/:queue/jobs/:id — delete a job
17
- * - GET /schedules — list cron schedules
18
- * - POST /schedules — create a schedule
19
- * - PUT /schedules/:name — update a schedule
20
- * - DELETE /schedules/:name — delete a schedule
21
- * - POST /queues/:name/jobs — enqueue a new job
22
- * - GET /warnings — recent warnings
8
+ * Express path prefix for every pg-boss admin route. `Api.child()` only
9
+ * affects OpenAPI documentation, not the underlying express router, so the
10
+ * prefix MUST live on each path string to make routing work end-to-end.
23
11
  */
24
- const mountPgBossApiRoutes = (api, service) => {
12
+ exports.PGBOSS_API_PATH_PREFIX = '/support/pgboss';
13
+ const mountPgBossApiRoutes = (api, service,
14
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
15
+ middlewares) => {
25
16
  const pgBossApi = api.child({ tags: ['PgBoss'] });
26
- // GET /queues list queues with stats
27
- pgBossApi.get('/queues', 'List all queues with stats', {
17
+ const p = (path) => `${exports.PGBOSS_API_PATH_PREFIX}${path}`;
18
+ const mw = middlewares?.length ? { middlewares } : {};
19
+ pgBossApi.get(p('/queues'), 'List all queues with stats', {
20
+ ...mw,
28
21
  responses: [(0, response_1.okResponse)(routes_schema_1.queueStatsArraySchema)],
29
22
  }, async (_request, _context, respond) => {
30
23
  const stats = await service.getQueueStats();
31
24
  return respond((0, send_1.ok)(stats));
32
25
  });
33
- // GET /queues/:name/jobs list jobs in a queue
34
- pgBossApi.get('/queues/:name/jobs', 'List jobs in a queue', {
26
+ pgBossApi.get(p('/queues/:name/jobs'), 'List jobs in a queue', {
27
+ ...mw,
35
28
  responses: [(0, response_1.okResponse)(routes_schema_1.jobArraySchema)],
36
29
  schemas: {
37
30
  params: routes_schema_1.queueNameParamsSchema,
@@ -40,8 +33,8 @@ const mountPgBossApiRoutes = (api, service) => {
40
33
  const jobs = await service.listJobs(request.params.name);
41
34
  return respond((0, send_1.ok)(jobs));
42
35
  });
43
- // GET /queues/:queue/jobs/:id job detail
44
- pgBossApi.get('/queues/:queue/jobs/:id', 'Get job details', {
36
+ pgBossApi.get(p('/queues/:queue/jobs/:id'), 'Get job details', {
37
+ ...mw,
45
38
  responses: [(0, response_1.okResponse)(routes_schema_1.jobDetailSchema)],
46
39
  schemas: {
47
40
  params: routes_schema_1.queueJobParamsSchema,
@@ -54,8 +47,8 @@ const mountPgBossApiRoutes = (api, service) => {
54
47
  }
55
48
  return respond((0, send_1.ok)(job));
56
49
  });
57
- // POST /queues/:queue/jobs/:id/retry retry a failed job
58
- pgBossApi.post('/queues/:queue/jobs/:id/retry', 'Retry a failed job', {
50
+ pgBossApi.post(p('/queues/:queue/jobs/:id/retry'), 'Retry a failed job', {
51
+ ...mw,
59
52
  responses: [(0, response_1.okResponse)(routes_schema_1.successResponseSchema)],
60
53
  schemas: {
61
54
  params: routes_schema_1.queueJobParamsSchema,
@@ -65,8 +58,8 @@ const mountPgBossApiRoutes = (api, service) => {
65
58
  await service.retryJob(queue, id);
66
59
  return respond((0, send_1.ok)({ success: true, jobId: id }));
67
60
  });
68
- // POST /queues/:queue/jobs/:id/cancel cancel a job
69
- pgBossApi.post('/queues/:queue/jobs/:id/cancel', 'Cancel a job', {
61
+ pgBossApi.post(p('/queues/:queue/jobs/:id/cancel'), 'Cancel a job', {
62
+ ...mw,
70
63
  responses: [(0, response_1.okResponse)(routes_schema_1.successResponseSchema)],
71
64
  schemas: {
72
65
  params: routes_schema_1.queueJobParamsSchema,
@@ -76,8 +69,8 @@ const mountPgBossApiRoutes = (api, service) => {
76
69
  await service.cancelJob(queue, id);
77
70
  return respond((0, send_1.ok)({ success: true, jobId: id }));
78
71
  });
79
- // DELETE /queues/:queue/jobs/:id delete a job
80
- pgBossApi.delete('/queues/:queue/jobs/:id', 'Delete a job', {
72
+ pgBossApi.delete(p('/queues/:queue/jobs/:id'), 'Delete a job', {
73
+ ...mw,
81
74
  responses: [(0, response_1.okResponse)(routes_schema_1.successResponseSchema)],
82
75
  schemas: {
83
76
  params: routes_schema_1.queueJobParamsSchema,
@@ -87,15 +80,15 @@ const mountPgBossApiRoutes = (api, service) => {
87
80
  await service.deleteJob(queue, id);
88
81
  return respond((0, send_1.ok)({ success: true, deleted: id }));
89
82
  });
90
- // GET /schedules list cron schedules
91
- pgBossApi.get('/schedules', 'List all cron schedules', {
83
+ pgBossApi.get(p('/schedules'), 'List all cron schedules', {
84
+ ...mw,
92
85
  responses: [(0, response_1.okResponse)(routes_schema_1.scheduleArraySchema)],
93
86
  }, async (_request, _context, respond) => {
94
87
  const schedules = await service.getSchedules();
95
88
  return respond((0, send_1.ok)(schedules));
96
89
  });
97
- // POST /schedules create a cron schedule
98
- pgBossApi.post('/schedules', 'Create a cron schedule', {
90
+ pgBossApi.post(p('/schedules'), 'Create a cron schedule', {
91
+ ...mw,
99
92
  responses: [(0, response_1.createdResponse)(routes_schema_1.successResponseSchema)],
100
93
  schemas: {
101
94
  body: routes_schema_1.scheduleBodySchema,
@@ -105,8 +98,8 @@ const mountPgBossApiRoutes = (api, service) => {
105
98
  await service.createSchedule(name, cron, data, options);
106
99
  return respond((0, send_1.created)({ success: true, name }));
107
100
  });
108
- // PUT /schedules/:name update a cron schedule
109
- pgBossApi.put('/schedules/:name', 'Update a cron schedule', {
101
+ pgBossApi.put(p('/schedules/:name'), 'Update a cron schedule', {
102
+ ...mw,
110
103
  responses: [(0, response_1.okResponse)(routes_schema_1.successResponseSchema)],
111
104
  schemas: {
112
105
  params: routes_schema_1.scheduleNameParamsSchema,
@@ -117,8 +110,8 @@ const mountPgBossApiRoutes = (api, service) => {
117
110
  await service.updateSchedule(request.params.name, cron, data, options);
118
111
  return respond((0, send_1.ok)({ success: true, name: request.params.name }));
119
112
  });
120
- // DELETE /schedules/:name delete a cron schedule
121
- pgBossApi.delete('/schedules/:name', 'Delete a cron schedule', {
113
+ pgBossApi.delete(p('/schedules/:name'), 'Delete a cron schedule', {
114
+ ...mw,
122
115
  responses: [(0, response_1.okResponse)(routes_schema_1.successResponseSchema)],
123
116
  schemas: {
124
117
  params: routes_schema_1.scheduleNameParamsSchema,
@@ -127,8 +120,8 @@ const mountPgBossApiRoutes = (api, service) => {
127
120
  await service.deleteSchedule(request.params.name);
128
121
  return respond((0, send_1.ok)({ success: true, deleted: request.params.name }));
129
122
  });
130
- // POST /queues/:name/jobs enqueue a new job
131
- pgBossApi.post('/queues/:name/jobs', 'Enqueue a new job', {
123
+ pgBossApi.post(p('/queues/:name/jobs'), 'Enqueue a new job', {
124
+ ...mw,
132
125
  responses: [(0, response_1.createdResponse)(routes_schema_1.successResponseSchema)],
133
126
  schemas: {
134
127
  params: routes_schema_1.queueNameParamsSchema,
@@ -139,8 +132,8 @@ const mountPgBossApiRoutes = (api, service) => {
139
132
  const jobId = await service.enqueueJob(request.params.name, data, options);
140
133
  return respond((0, send_1.created)({ success: true, jobId: jobId ?? undefined }));
141
134
  });
142
- // GET /warnings recent warnings
143
- pgBossApi.get('/warnings', 'List recent warnings', {
135
+ pgBossApi.get(p('/warnings'), 'List recent warnings', {
136
+ ...mw,
144
137
  responses: [(0, response_1.okResponse)(routes_schema_1.warningArraySchema)],
145
138
  schemas: {
146
139
  query: routes_schema_1.warningsQuerySchema,
@@ -1,5 +1,5 @@
1
1
  import { PgBoss } from 'pg-boss';
2
- import type { SendOptions } from 'pg-boss';
2
+ import type { Job, SendOptions } from 'pg-boss';
3
3
  import type { Logger } from 'pino';
4
4
  import type { Sequelize, Transaction } from 'sequelize';
5
5
  /**
@@ -13,3 +13,11 @@ export declare const enqueueJob: (boss: PgBoss, queueName: string, data: object,
13
13
  * instead of calling internal SQL functions directly.
14
14
  */
15
15
  export declare const enqueueInTransaction: (boss: PgBoss, queueName: string, data: object, options: SendOptions, transaction: Transaction, sequelize: Sequelize) => Promise<string | null>;
16
+ /**
17
+ * Wrap a pg-boss worker handler so that, when the final retry attempt fails,
18
+ * a Mattermost DLQ alert is fired before the error is re-thrown.
19
+ *
20
+ * Requires the worker to be registered with `{ includeMetadata: true }` so
21
+ * `retryCount` and `retryLimit` are populated on each job.
22
+ */
23
+ export declare const withDlqAlerting: <T = object>(queueName: string, handler: (jobs: Job<T>[]) => Promise<void>, logger: Logger, mattermostWebhookUrl?: string) => ((jobs: Job<T>[]) => Promise<void>);
@@ -1,6 +1,7 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.enqueueInTransaction = exports.enqueueJob = void 0;
3
+ exports.withDlqAlerting = exports.enqueueInTransaction = exports.enqueueJob = void 0;
4
+ const metrics_1 = require("./metrics");
4
5
  /**
5
6
  * Enqueue a job via pg-boss with logging.
6
7
  */
@@ -42,3 +43,29 @@ const enqueueInTransaction = async (boss, queueName, data, options, transaction,
42
43
  return boss.send(queueName, data, { ...options, db });
43
44
  };
44
45
  exports.enqueueInTransaction = enqueueInTransaction;
46
+ /**
47
+ * Wrap a pg-boss worker handler so that, when the final retry attempt fails,
48
+ * a Mattermost DLQ alert is fired before the error is re-thrown.
49
+ *
50
+ * Requires the worker to be registered with `{ includeMetadata: true }` so
51
+ * `retryCount` and `retryLimit` are populated on each job.
52
+ */
53
+ const withDlqAlerting = (queueName, handler, logger, mattermostWebhookUrl) => {
54
+ return async (jobs) => {
55
+ try {
56
+ await handler(jobs);
57
+ }
58
+ catch (error) {
59
+ const job = jobs[0];
60
+ const retryCount = job?.retryCount ?? 0;
61
+ const retryLimit = job?.retryLimit ?? 0;
62
+ const isFinalFailure = retryLimit > 0 && retryCount >= retryLimit;
63
+ if (isFinalFailure && mattermostWebhookUrl && job) {
64
+ const message = error instanceof Error ? error.message : String(error);
65
+ await (0, metrics_1.sendDlqAlert)(mattermostWebhookUrl, queueName, job.id, message, logger);
66
+ }
67
+ throw error;
68
+ }
69
+ };
70
+ };
71
+ exports.withDlqAlerting = withDlqAlerting;
@@ -2,28 +2,41 @@ import { PgBoss } from 'pg-boss';
2
2
  import type { Logger } from 'pino';
3
3
  import type { PgBossConfig } from './types';
4
4
  export { PgBoss };
5
+ export type { Job, SendOptions } from 'pg-boss';
5
6
  export type { PgBossConfig, QueueDefinition, WorkerRegistration, PgBossInstance, } from './types';
6
7
  export { PG_BOSS_DEFAULTS, buildPgBossDefaults } from './config';
7
8
  export { mountPgBossApiRoutes } from './controller/routes';
8
9
  export { PgBossService } from './service';
9
10
  export { registerPgBossMetrics } from './metrics';
10
- export { enqueueJob, enqueueInTransaction } from './helpers';
11
+ export { enqueueJob, enqueueInTransaction, withDlqAlerting } from './helpers';
11
12
  export { sendDlqAlert } from './metrics';
12
13
  export interface PgBossContext {
13
14
  boss: PgBoss;
14
15
  logger: Logger;
15
16
  config: Required<PgBossConfig>;
17
+ serviceName: string;
18
+ metricsInterval?: NodeJS.Timeout;
16
19
  }
17
20
  /**
18
21
  * Creates a pg-boss instance with error recovery (auto-restart on connection loss).
19
22
  * Issue #510 mitigation: on error, waits 5s then restarts.
20
23
  */
21
- export declare const createPgBoss: (config: PgBossConfig, logger: Logger) => PgBossContext;
24
+ export declare const createPgBoss: (config: PgBossConfig, logger: Logger, serviceName?: string) => PgBossContext;
22
25
  /**
23
- * Starts the pg-boss instance. Call after database is connected.
26
+ * Starts the pg-boss instance and registers Prometheus metrics polling.
27
+ * Call after database is connected.
24
28
  */
25
29
  export declare const startBoss: (ctx: PgBossContext) => Promise<void>;
26
30
  /**
27
- * Gracefully stops the pg-boss instance. Suitable as a shutdown handler.
31
+ * Gracefully stops the pg-boss instance and clears metrics polling.
32
+ * Suitable as a shutdown handler.
28
33
  */
29
34
  export declare const stopBoss: (ctx: PgBossContext) => Promise<void>;
35
+ /**
36
+ * Maps the legacy `deleteAfterDays` setting to pg-boss v12's
37
+ * per-queue `deleteAfterSeconds` option. Use this when calling
38
+ * `boss.createQueue(name, { ...defaultRetention(ctx), policy: 'singleton' })`.
39
+ */
40
+ export declare const defaultRetention: (ctx: PgBossContext) => {
41
+ deleteAfterSeconds: number;
42
+ };
@@ -1,9 +1,10 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.stopBoss = exports.startBoss = exports.createPgBoss = exports.sendDlqAlert = exports.enqueueInTransaction = exports.enqueueJob = exports.registerPgBossMetrics = exports.PgBossService = exports.mountPgBossApiRoutes = exports.buildPgBossDefaults = exports.PG_BOSS_DEFAULTS = exports.PgBoss = void 0;
3
+ exports.defaultRetention = exports.stopBoss = exports.startBoss = exports.createPgBoss = exports.sendDlqAlert = exports.withDlqAlerting = exports.enqueueInTransaction = exports.enqueueJob = exports.registerPgBossMetrics = exports.PgBossService = exports.mountPgBossApiRoutes = exports.buildPgBossDefaults = exports.PG_BOSS_DEFAULTS = exports.PgBoss = void 0;
4
4
  const pg_boss_1 = require("pg-boss");
5
5
  Object.defineProperty(exports, "PgBoss", { enumerable: true, get: function () { return pg_boss_1.PgBoss; } });
6
6
  const config_1 = require("./config");
7
+ const metrics_1 = require("./metrics");
7
8
  var config_2 = require("./config");
8
9
  Object.defineProperty(exports, "PG_BOSS_DEFAULTS", { enumerable: true, get: function () { return config_2.PG_BOSS_DEFAULTS; } });
9
10
  Object.defineProperty(exports, "buildPgBossDefaults", { enumerable: true, get: function () { return config_2.buildPgBossDefaults; } });
@@ -11,24 +12,27 @@ var routes_1 = require("./controller/routes");
11
12
  Object.defineProperty(exports, "mountPgBossApiRoutes", { enumerable: true, get: function () { return routes_1.mountPgBossApiRoutes; } });
12
13
  var service_1 = require("./service");
13
14
  Object.defineProperty(exports, "PgBossService", { enumerable: true, get: function () { return service_1.PgBossService; } });
14
- var metrics_1 = require("./metrics");
15
- Object.defineProperty(exports, "registerPgBossMetrics", { enumerable: true, get: function () { return metrics_1.registerPgBossMetrics; } });
15
+ var metrics_2 = require("./metrics");
16
+ Object.defineProperty(exports, "registerPgBossMetrics", { enumerable: true, get: function () { return metrics_2.registerPgBossMetrics; } });
16
17
  var helpers_1 = require("./helpers");
17
18
  Object.defineProperty(exports, "enqueueJob", { enumerable: true, get: function () { return helpers_1.enqueueJob; } });
18
19
  Object.defineProperty(exports, "enqueueInTransaction", { enumerable: true, get: function () { return helpers_1.enqueueInTransaction; } });
19
- var metrics_2 = require("./metrics");
20
- Object.defineProperty(exports, "sendDlqAlert", { enumerable: true, get: function () { return metrics_2.sendDlqAlert; } });
20
+ Object.defineProperty(exports, "withDlqAlerting", { enumerable: true, get: function () { return helpers_1.withDlqAlerting; } });
21
+ var metrics_3 = require("./metrics");
22
+ Object.defineProperty(exports, "sendDlqAlert", { enumerable: true, get: function () { return metrics_3.sendDlqAlert; } });
21
23
  const RESTART_DELAY_MS = 5000;
24
+ const SECONDS_PER_DAY = 86_400;
22
25
  /**
23
26
  * Creates a pg-boss instance with error recovery (auto-restart on connection loss).
24
27
  * Issue #510 mitigation: on error, waits 5s then restarts.
25
28
  */
26
- const createPgBoss = (config, logger) => {
29
+ const createPgBoss = (config, logger, serviceName = config.schema) => {
27
30
  const resolvedConfig = (0, config_1.buildPgBossDefaults)(config);
28
31
  const boss = new pg_boss_1.PgBoss({
29
32
  connectionString: resolvedConfig.connectionString,
30
33
  schema: resolvedConfig.schema,
31
34
  application_name: resolvedConfig.applicationName,
35
+ max: resolvedConfig.maxConnectionPoolSize,
32
36
  migrate: true,
33
37
  });
34
38
  boss.on('error', (error) => {
@@ -38,27 +42,43 @@ const createPgBoss = (config, logger) => {
38
42
  boss.on('warning', warning => {
39
43
  logger.warn({ warning }, 'pg-boss warning');
40
44
  });
41
- return { boss, logger, config: resolvedConfig };
45
+ return { boss, logger, config: resolvedConfig, serviceName };
42
46
  };
43
47
  exports.createPgBoss = createPgBoss;
44
48
  /**
45
- * Starts the pg-boss instance. Call after database is connected.
49
+ * Starts the pg-boss instance and registers Prometheus metrics polling.
50
+ * Call after database is connected.
46
51
  */
47
52
  const startBoss = async (ctx) => {
48
53
  ctx.logger.info({ schema: ctx.config.schema }, 'Starting pg-boss');
49
54
  await ctx.boss.start();
55
+ ctx.metricsInterval = (0, metrics_1.registerPgBossMetrics)(ctx.boss, ctx.serviceName, ctx.logger, ctx.config.mattermostWebhookUrl || undefined);
50
56
  ctx.logger.info({ schema: ctx.config.schema }, 'pg-boss started successfully');
51
57
  };
52
58
  exports.startBoss = startBoss;
53
59
  /**
54
- * Gracefully stops the pg-boss instance. Suitable as a shutdown handler.
60
+ * Gracefully stops the pg-boss instance and clears metrics polling.
61
+ * Suitable as a shutdown handler.
55
62
  */
56
63
  const stopBoss = async (ctx) => {
57
64
  ctx.logger.info({ schema: ctx.config.schema }, 'Stopping pg-boss');
65
+ if (ctx.metricsInterval) {
66
+ clearInterval(ctx.metricsInterval);
67
+ ctx.metricsInterval = undefined;
68
+ }
58
69
  await ctx.boss.stop({ graceful: true, timeout: 30_000 });
59
70
  ctx.logger.info({ schema: ctx.config.schema }, 'pg-boss stopped');
60
71
  };
61
72
  exports.stopBoss = stopBoss;
73
+ /**
74
+ * Maps the legacy `deleteAfterDays` setting to pg-boss v12's
75
+ * per-queue `deleteAfterSeconds` option. Use this when calling
76
+ * `boss.createQueue(name, { ...defaultRetention(ctx), policy: 'singleton' })`.
77
+ */
78
+ const defaultRetention = (ctx) => ({
79
+ deleteAfterSeconds: ctx.config.deleteAfterDays * SECONDS_PER_DAY,
80
+ });
81
+ exports.defaultRetention = defaultRetention;
62
82
  const scheduleRestart = (boss, logger) => {
63
83
  setTimeout(async () => {
64
84
  try {
@@ -4,7 +4,7 @@ exports.manageJob = void 0;
4
4
  const manageJob = async (boss, logger, action, queueName, jobId) => {
5
5
  switch (action) {
6
6
  case 'retry':
7
- await boss.resume(queueName, jobId);
7
+ await boss.retry(queueName, jobId);
8
8
  break;
9
9
  case 'cancel':
10
10
  await boss.cancel(queueName, jobId);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@lucaapp/service-utils",
3
- "version": "5.9.0",
3
+ "version": "5.10.1",
4
4
  "main": "dist/index.js",
5
5
  "types": "dist/index.d.ts",
6
6
  "files": [
@@ -31,7 +31,7 @@
31
31
  "@types/response-time": "^2.3.9",
32
32
  "@types/swagger-ui-express": "4.1.8",
33
33
  "@types/validator": "13.7.1",
34
- "axios": "^1.15.2",
34
+ "axios": "1.16.0",
35
35
  "axios-rate-limit": "^1.4.0",
36
36
  "axios-retry": "^4.5.0",
37
37
  "body-parser": "1.20.4",
@@ -97,7 +97,8 @@
97
97
  "node-forge": "1.4.0",
98
98
  "uuid": "^14.0.0",
99
99
  "follow-redirects": "^1.16.0",
100
- "axios": "^1.15.2",
101
- "path-to-regexp": "0.1.13"
100
+ "axios": "1.16.0",
101
+ "path-to-regexp": "0.1.13",
102
+ "ip-address": "10.1.1"
102
103
  }
103
104
  }