@adaptic/backend-legacy 0.0.71 → 0.0.72
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/config/jwtConfig.cjs +52 -0
- package/config/jwtConfig.d.ts +16 -0
- package/config/jwtConfig.d.ts.map +1 -0
- package/config/jwtConfig.js.map +1 -0
- package/config/metrics.cjs +261 -0
- package/config/metrics.d.ts +88 -0
- package/config/metrics.d.ts.map +1 -0
- package/config/metrics.js.map +1 -0
- package/config/persisted-queries.cjs +122 -0
- package/config/persisted-queries.d.ts +40 -0
- package/config/persisted-queries.d.ts.map +1 -0
- package/config/persisted-queries.js.map +1 -0
- package/config/tracing.cjs +128 -0
- package/config/tracing.d.ts +24 -0
- package/config/tracing.d.ts.map +1 -0
- package/config/tracing.js.map +1 -0
- package/middleware/audit-logger.cjs +223 -0
- package/middleware/audit-logger.d.ts +85 -0
- package/middleware/audit-logger.d.ts.map +1 -0
- package/middleware/audit-logger.js.map +1 -0
- package/middleware/auth.cjs +44 -0
- package/middleware/auth.d.ts +6 -0
- package/middleware/auth.d.ts.map +1 -0
- package/middleware/auth.js.map +1 -0
- package/middleware/graphql-validation-plugin.cjs +164 -0
- package/middleware/graphql-validation-plugin.d.ts +37 -0
- package/middleware/graphql-validation-plugin.d.ts.map +1 -0
- package/middleware/graphql-validation-plugin.js.map +1 -0
- package/middleware/index.cjs +46 -0
- package/middleware/index.d.ts +13 -0
- package/middleware/index.d.ts.map +1 -0
- package/middleware/index.js.map +1 -0
- package/middleware/input-validator.cjs +220 -0
- package/middleware/input-validator.d.ts +63 -0
- package/middleware/input-validator.d.ts.map +1 -0
- package/middleware/input-validator.js.map +1 -0
- package/middleware/query-complexity.cjs +182 -0
- package/middleware/query-complexity.d.ts +56 -0
- package/middleware/query-complexity.d.ts.map +1 -0
- package/middleware/query-complexity.js.map +1 -0
- package/middleware/rate-limiter.cjs +112 -0
- package/middleware/rate-limiter.d.ts +16 -0
- package/middleware/rate-limiter.d.ts.map +1 -0
- package/middleware/rate-limiter.js.map +1 -0
- package/middleware/soft-delete.cjs +175 -0
- package/middleware/soft-delete.d.ts +146 -0
- package/middleware/soft-delete.d.ts.map +1 -0
- package/middleware/soft-delete.js.map +1 -0
- package/middleware/types.cjs +17 -0
- package/middleware/types.d.ts +87 -0
- package/middleware/types.d.ts.map +1 -0
- package/middleware/types.js.map +1 -0
- package/middleware/validation-examples.cjs +403 -0
- package/middleware/validation-examples.d.ts +76 -0
- package/middleware/validation-examples.d.ts.map +1 -0
- package/middleware/validation-examples.js.map +1 -0
- package/package.json +4 -1
- package/validators/allocation-validator.cjs +85 -0
- package/validators/allocation-validator.d.ts +32 -0
- package/validators/allocation-validator.d.ts.map +1 -0
- package/validators/allocation-validator.js.map +1 -0
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Centralized JWT_SECRET configuration with environment-aware validation.
|
|
4
|
+
*
|
|
5
|
+
* - In production (NODE_ENV=production): throws a startup error if JWT_SECRET
|
|
6
|
+
* is missing or shorter than 32 characters.
|
|
7
|
+
* - In development: logs a warning and falls back to a local-only default.
|
|
8
|
+
*
|
|
9
|
+
* This module is designed to be imported once at startup so that any
|
|
10
|
+
* misconfiguration is caught immediately rather than at the first request.
|
|
11
|
+
*/
|
|
12
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
13
|
+
exports.jwtSecret = void 0;
|
|
14
|
+
const logger_1 = require("../utils/logger.cjs");
|
|
15
|
+
const MINIMUM_SECRET_LENGTH = 32;
|
|
16
|
+
const DEV_FALLBACK_SECRET = 'development_secret_key_for_local_testing_only_do_not_use_in_production';
|
|
17
|
+
const isProduction = process.env.NODE_ENV === 'production';
|
|
18
|
+
function resolveJwtSecret() {
|
|
19
|
+
// Try JWT_SECRET first, then fall back to NEXTAUTH_SECRET for compatibility
|
|
20
|
+
const secret = process.env.JWT_SECRET || process.env.NEXTAUTH_SECRET;
|
|
21
|
+
if (!secret) {
|
|
22
|
+
if (isProduction) {
|
|
23
|
+
logger_1.logger.error('[SECURITY] FATAL: JWT_SECRET environment variable is not set. ' +
|
|
24
|
+
'The server cannot start in production without a valid JWT_SECRET. ' +
|
|
25
|
+
'Set JWT_SECRET to a cryptographically random string of at least ' +
|
|
26
|
+
`${MINIMUM_SECRET_LENGTH} characters.`);
|
|
27
|
+
throw new Error('JWT_SECRET is required in production. Set the JWT_SECRET environment variable.');
|
|
28
|
+
}
|
|
29
|
+
logger_1.logger.warn('[SECURITY] WARNING: JWT_SECRET is not set. Using an insecure development ' +
|
|
30
|
+
'fallback. This is acceptable for local development only. ' +
|
|
31
|
+
'Do NOT deploy to production without setting JWT_SECRET.');
|
|
32
|
+
return DEV_FALLBACK_SECRET;
|
|
33
|
+
}
|
|
34
|
+
if (secret.length < MINIMUM_SECRET_LENGTH) {
|
|
35
|
+
if (isProduction) {
|
|
36
|
+
logger_1.logger.error(`[SECURITY] FATAL: JWT_SECRET is too short (${secret.length} characters). ` +
|
|
37
|
+
`A minimum of ${MINIMUM_SECRET_LENGTH} characters is required in production.`);
|
|
38
|
+
throw new Error(`JWT_SECRET must be at least ${MINIMUM_SECRET_LENGTH} characters in production. ` +
|
|
39
|
+
`Current length: ${secret.length}.`);
|
|
40
|
+
}
|
|
41
|
+
logger_1.logger.warn(`[SECURITY] WARNING: JWT_SECRET is only ${secret.length} characters. ` +
|
|
42
|
+
`A minimum of ${MINIMUM_SECRET_LENGTH} characters is recommended. ` +
|
|
43
|
+
'This warning will become a fatal error in production.');
|
|
44
|
+
}
|
|
45
|
+
return secret;
|
|
46
|
+
}
|
|
47
|
+
/**
|
|
48
|
+
* The validated JWT secret for this environment.
|
|
49
|
+
* Resolved once at import time; will throw in production if invalid.
|
|
50
|
+
*/
|
|
51
|
+
exports.jwtSecret = resolveJwtSecret();
|
|
52
|
+
//# sourceMappingURL=jwtConfig.js.map
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Centralized JWT_SECRET configuration with environment-aware validation.
|
|
3
|
+
*
|
|
4
|
+
* - In production (NODE_ENV=production): throws a startup error if JWT_SECRET
|
|
5
|
+
* is missing or shorter than 32 characters.
|
|
6
|
+
* - In development: logs a warning and falls back to a local-only default.
|
|
7
|
+
*
|
|
8
|
+
* This module is designed to be imported once at startup so that any
|
|
9
|
+
* misconfiguration is caught immediately rather than at the first request.
|
|
10
|
+
*/
|
|
11
|
+
/**
|
|
12
|
+
* The validated JWT secret for this environment.
|
|
13
|
+
* Resolved once at import time; will throw in production if invalid.
|
|
14
|
+
*/
|
|
15
|
+
export declare const jwtSecret: string;
|
|
16
|
+
//# sourceMappingURL=jwtConfig.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"jwtConfig.d.ts","sourceRoot":"","sources":["../../src/config/jwtConfig.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAyDH;;;GAGG;AACH,eAAO,MAAM,SAAS,EAAE,MAA2B,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"jwtConfig.js","sourceRoot":"","sources":["../../src/config/jwtConfig.ts"],"names":[],"mappings":";AAAA;;;;;;;;;GASG;;;AAEH,4CAAyC;AAEzC,MAAM,qBAAqB,GAAG,EAAE,CAAC;AACjC,MAAM,mBAAmB,GACvB,wEAAwE,CAAC;AAE3E,MAAM,YAAY,GAAG,OAAO,CAAC,GAAG,CAAC,QAAQ,KAAK,YAAY,CAAC;AAE3D,SAAS,gBAAgB;IACvB,4EAA4E;IAC5E,MAAM,MAAM,GAAG,OAAO,CAAC,GAAG,CAAC,UAAU,IAAI,OAAO,CAAC,GAAG,CAAC,eAAe,CAAC;IAErE,IAAI,CAAC,MAAM,EAAE,CAAC;QACZ,IAAI,YAAY,EAAE,CAAC;YACjB,eAAM,CAAC,KAAK,CACV,gEAAgE;gBAC9D,oEAAoE;gBACpE,kEAAkE;gBAClE,GAAG,qBAAqB,cAAc,CACzC,CAAC;YACF,MAAM,IAAI,KAAK,CACb,gFAAgF,CACjF,CAAC;QACJ,CAAC;QAED,eAAM,CAAC,IAAI,CACT,2EAA2E;YACzE,2DAA2D;YAC3D,yDAAyD,CAC5D,CAAC;QACF,OAAO,mBAAmB,CAAC;IAC7B,CAAC;IAED,IAAI,MAAM,CAAC,MAAM,GAAG,qBAAqB,EAAE,CAAC;QAC1C,IAAI,YAAY,EAAE,CAAC;YACjB,eAAM,CAAC,KAAK,CACV,8CAA8C,MAAM,CAAC,MAAM,gBAAgB;gBACzE,gBAAgB,qBAAqB,wCAAwC,CAChF,CAAC;YACF,MAAM,IAAI,KAAK,CACb,+BAA+B,qBAAqB,6BAA6B;gBAC/E,mBAAmB,MAAM,CAAC,MAAM,GAAG,CACtC,CAAC;QACJ,CAAC;QAED,eAAM,CAAC,IAAI,CACT,0CAA0C,MAAM,CAAC,MAAM,eAAe;YACpE,gBAAgB,qBAAqB,8BAA8B;YACnE,uDAAuD,CAC1D,CAAC;IACJ,CAAC;IAED,OAAO,MAAM,CAAC;AAChB,CAAC;AAED;;;GAGG;AACU,QAAA,SAAS,GAAW,gBAAgB,EAAE,CAAC"}
|
|
@@ -0,0 +1,261 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.activeWebSocketConnections = exports.activeSubscriptions = exports.dbConnectionsActive = exports.dbQueryDuration = exports.graphqlErrorsTotal = exports.graphqlOperationDuration = exports.graphqlOperationsTotal = exports.httpRequestDuration = exports.httpRequestsTotal = exports.metricsRegistry = void 0;
|
|
4
|
+
exports.initMetrics = initMetrics;
|
|
5
|
+
exports.metricsMiddleware = metricsMiddleware;
|
|
6
|
+
exports.createMetricsPlugin = createMetricsPlugin;
|
|
7
|
+
exports.createMetricsRouter = createMetricsRouter;
|
|
8
|
+
const express_1 = require("express");
|
|
9
|
+
const prom_client_1 = require("prom-client");
|
|
10
|
+
const logger_1 = require("../utils/logger.cjs");
|
|
11
|
+
const SERVICE_NAME = 'backend-legacy';
|
|
12
|
+
/**
|
|
13
|
+
* Dedicated Prometheus registry for backend-legacy metrics.
|
|
14
|
+
* Using a dedicated registry avoids conflicts with default Node.js metrics
|
|
15
|
+
* that might be registered by other libraries.
|
|
16
|
+
*/
|
|
17
|
+
exports.metricsRegistry = new prom_client_1.Registry();
|
|
18
|
+
exports.metricsRegistry.setDefaultLabels({ service: SERVICE_NAME });
|
|
19
|
+
// ---------------------------------------------------------------------------
|
|
20
|
+
// HTTP / GraphQL request metrics
|
|
21
|
+
// ---------------------------------------------------------------------------
|
|
22
|
+
/** Counts total HTTP requests by method, route, and status code */
|
|
23
|
+
exports.httpRequestsTotal = new prom_client_1.Counter({
|
|
24
|
+
name: 'http_requests_total',
|
|
25
|
+
help: 'Total number of HTTP requests',
|
|
26
|
+
labelNames: ['method', 'route', 'status_code'],
|
|
27
|
+
registers: [exports.metricsRegistry],
|
|
28
|
+
});
|
|
29
|
+
/** Histogram of HTTP request durations in seconds */
|
|
30
|
+
exports.httpRequestDuration = new prom_client_1.Histogram({
|
|
31
|
+
name: 'http_request_duration_seconds',
|
|
32
|
+
help: 'Duration of HTTP requests in seconds',
|
|
33
|
+
labelNames: ['method', 'route', 'status_code'],
|
|
34
|
+
buckets: [0.005, 0.01, 0.025, 0.05, 0.1, 0.25, 0.5, 1, 2.5, 5, 10],
|
|
35
|
+
registers: [exports.metricsRegistry],
|
|
36
|
+
});
|
|
37
|
+
/** Counts total GraphQL operations by type and name */
|
|
38
|
+
exports.graphqlOperationsTotal = new prom_client_1.Counter({
|
|
39
|
+
name: 'graphql_operations_total',
|
|
40
|
+
help: 'Total number of GraphQL operations',
|
|
41
|
+
labelNames: ['operation_type', 'operation_name', 'status'],
|
|
42
|
+
registers: [exports.metricsRegistry],
|
|
43
|
+
});
|
|
44
|
+
/** Histogram of GraphQL operation durations in seconds */
|
|
45
|
+
exports.graphqlOperationDuration = new prom_client_1.Histogram({
|
|
46
|
+
name: 'graphql_operation_duration_seconds',
|
|
47
|
+
help: 'Duration of GraphQL operations in seconds',
|
|
48
|
+
labelNames: ['operation_type', 'operation_name'],
|
|
49
|
+
buckets: [0.01, 0.05, 0.1, 0.25, 0.5, 1, 2.5, 5, 10, 30],
|
|
50
|
+
registers: [exports.metricsRegistry],
|
|
51
|
+
});
|
|
52
|
+
/** Counts GraphQL errors by operation and error code */
|
|
53
|
+
exports.graphqlErrorsTotal = new prom_client_1.Counter({
|
|
54
|
+
name: 'graphql_errors_total',
|
|
55
|
+
help: 'Total number of GraphQL errors',
|
|
56
|
+
labelNames: ['operation_type', 'operation_name', 'error_code'],
|
|
57
|
+
registers: [exports.metricsRegistry],
|
|
58
|
+
});
|
|
59
|
+
// ---------------------------------------------------------------------------
|
|
60
|
+
// Database metrics
|
|
61
|
+
// ---------------------------------------------------------------------------
|
|
62
|
+
/** Histogram of Prisma query durations in seconds */
|
|
63
|
+
exports.dbQueryDuration = new prom_client_1.Histogram({
|
|
64
|
+
name: 'db_query_duration_seconds',
|
|
65
|
+
help: 'Duration of database queries in seconds',
|
|
66
|
+
labelNames: ['operation', 'model'],
|
|
67
|
+
buckets: [0.001, 0.005, 0.01, 0.025, 0.05, 0.1, 0.25, 0.5, 1, 5],
|
|
68
|
+
registers: [exports.metricsRegistry],
|
|
69
|
+
});
|
|
70
|
+
/** Gauge for active database connections */
|
|
71
|
+
exports.dbConnectionsActive = new prom_client_1.Gauge({
|
|
72
|
+
name: 'db_connections_active',
|
|
73
|
+
help: 'Number of active database connections (approximate)',
|
|
74
|
+
registers: [exports.metricsRegistry],
|
|
75
|
+
});
|
|
76
|
+
// ---------------------------------------------------------------------------
|
|
77
|
+
// WebSocket / Subscriptions metrics
|
|
78
|
+
// ---------------------------------------------------------------------------
|
|
79
|
+
/** Gauge for active GraphQL subscriptions */
|
|
80
|
+
exports.activeSubscriptions = new prom_client_1.Gauge({
|
|
81
|
+
name: 'graphql_active_subscriptions',
|
|
82
|
+
help: 'Number of active GraphQL subscriptions',
|
|
83
|
+
registers: [exports.metricsRegistry],
|
|
84
|
+
});
|
|
85
|
+
/** Gauge for active WebSocket connections */
|
|
86
|
+
exports.activeWebSocketConnections = new prom_client_1.Gauge({
|
|
87
|
+
name: 'websocket_active_connections',
|
|
88
|
+
help: 'Number of active WebSocket connections',
|
|
89
|
+
registers: [exports.metricsRegistry],
|
|
90
|
+
});
|
|
91
|
+
// ---------------------------------------------------------------------------
|
|
92
|
+
// Application metrics
|
|
93
|
+
// ---------------------------------------------------------------------------
|
|
94
|
+
/** Gauge for application uptime in seconds */
|
|
95
|
+
const uptimeGauge = new prom_client_1.Gauge({
|
|
96
|
+
name: 'app_uptime_seconds',
|
|
97
|
+
help: 'Application uptime in seconds',
|
|
98
|
+
registers: [exports.metricsRegistry],
|
|
99
|
+
});
|
|
100
|
+
const startedAt = Date.now();
|
|
101
|
+
// ---------------------------------------------------------------------------
|
|
102
|
+
// Initialization
|
|
103
|
+
// ---------------------------------------------------------------------------
|
|
104
|
+
/**
|
|
105
|
+
* Determines if metrics collection is enabled.
|
|
106
|
+
* Enabled by default in production/staging; can be explicitly controlled
|
|
107
|
+
* via PROMETHEUS_METRICS_ENABLED env var.
|
|
108
|
+
*/
|
|
109
|
+
function isMetricsEnabled() {
|
|
110
|
+
const explicitSetting = process.env.PROMETHEUS_METRICS_ENABLED;
|
|
111
|
+
if (explicitSetting !== undefined) {
|
|
112
|
+
return explicitSetting === 'true' || explicitSetting === '1';
|
|
113
|
+
}
|
|
114
|
+
const env = process.env.NODE_ENV || 'development';
|
|
115
|
+
return env === 'production' || env === 'staging';
|
|
116
|
+
}
|
|
117
|
+
/**
|
|
118
|
+
* Initializes Prometheus metrics collection.
|
|
119
|
+
*
|
|
120
|
+
* Registers default Node.js metrics (CPU, memory, event loop, GC) and
|
|
121
|
+
* application-specific metrics for HTTP, GraphQL, and database operations.
|
|
122
|
+
*
|
|
123
|
+
* Environment variables:
|
|
124
|
+
* - PROMETHEUS_METRICS_ENABLED: Explicit on/off ('true'/'false'). Defaults to on in production/staging.
|
|
125
|
+
*
|
|
126
|
+
* @returns true if metrics were initialized, false if disabled
|
|
127
|
+
*/
|
|
128
|
+
function initMetrics() {
|
|
129
|
+
if (!isMetricsEnabled()) {
|
|
130
|
+
logger_1.logger.info('Prometheus metrics collection is disabled', {
|
|
131
|
+
reason: 'PROMETHEUS_METRICS_ENABLED not set or environment is development',
|
|
132
|
+
});
|
|
133
|
+
return false;
|
|
134
|
+
}
|
|
135
|
+
// Register default Node.js metrics (memory, CPU, event loop lag, etc.)
|
|
136
|
+
(0, prom_client_1.collectDefaultMetrics)({ register: exports.metricsRegistry });
|
|
137
|
+
// Update uptime gauge periodically
|
|
138
|
+
const UPTIME_UPDATE_INTERVAL_MS = 15000;
|
|
139
|
+
setInterval(() => {
|
|
140
|
+
uptimeGauge.set((Date.now() - startedAt) / 1000);
|
|
141
|
+
}, UPTIME_UPDATE_INTERVAL_MS);
|
|
142
|
+
logger_1.logger.info('Prometheus metrics initialized');
|
|
143
|
+
return true;
|
|
144
|
+
}
|
|
145
|
+
// ---------------------------------------------------------------------------
|
|
146
|
+
// Express middleware
|
|
147
|
+
// ---------------------------------------------------------------------------
|
|
148
|
+
/**
|
|
149
|
+
* Express middleware that records HTTP request metrics.
|
|
150
|
+
* Tracks request count and duration for each method/route/status combination.
|
|
151
|
+
*
|
|
152
|
+
* Should be mounted early in the middleware chain to capture all requests.
|
|
153
|
+
*/
|
|
154
|
+
function metricsMiddleware(req, res, next) {
|
|
155
|
+
if (!isMetricsEnabled()) {
|
|
156
|
+
next();
|
|
157
|
+
return;
|
|
158
|
+
}
|
|
159
|
+
const start = process.hrtime.bigint();
|
|
160
|
+
res.on('finish', () => {
|
|
161
|
+
var _a;
|
|
162
|
+
const durationNs = Number(process.hrtime.bigint() - start);
|
|
163
|
+
const durationSeconds = durationNs / 1e9;
|
|
164
|
+
const route = ((_a = req.route) === null || _a === void 0 ? void 0 : _a.path) || req.path || 'unknown';
|
|
165
|
+
const method = req.method;
|
|
166
|
+
const statusCode = String(res.statusCode);
|
|
167
|
+
exports.httpRequestsTotal.inc({ method, route, status_code: statusCode });
|
|
168
|
+
exports.httpRequestDuration.observe({ method, route, status_code: statusCode }, durationSeconds);
|
|
169
|
+
});
|
|
170
|
+
next();
|
|
171
|
+
}
|
|
172
|
+
// ---------------------------------------------------------------------------
|
|
173
|
+
// Apollo Server plugin
|
|
174
|
+
// ---------------------------------------------------------------------------
|
|
175
|
+
/**
|
|
176
|
+
* Creates an Apollo Server plugin that records GraphQL operation metrics.
|
|
177
|
+
*
|
|
178
|
+
* Tracks:
|
|
179
|
+
* - Operation count by type (query/mutation/subscription) and name
|
|
180
|
+
* - Operation duration
|
|
181
|
+
* - Error count by operation and error code
|
|
182
|
+
*
|
|
183
|
+
* @returns Apollo Server plugin configuration
|
|
184
|
+
*/
|
|
185
|
+
function createMetricsPlugin() {
|
|
186
|
+
return {
|
|
187
|
+
async requestDidStart() {
|
|
188
|
+
const start = process.hrtime.bigint();
|
|
189
|
+
return {
|
|
190
|
+
async willSendResponse(requestContext) {
|
|
191
|
+
var _a, _b, _c, _d;
|
|
192
|
+
const durationNs = Number(process.hrtime.bigint() - start);
|
|
193
|
+
const durationSeconds = durationNs / 1e9;
|
|
194
|
+
const operationName = requestContext.operationName || 'anonymous';
|
|
195
|
+
const operationType = ((_a = requestContext.operation) === null || _a === void 0 ? void 0 : _a.operation) || 'unknown';
|
|
196
|
+
exports.graphqlOperationDuration.observe({ operation_type: operationType, operation_name: operationName }, durationSeconds);
|
|
197
|
+
const responseBody = requestContext.response.body;
|
|
198
|
+
const hasErrors = responseBody.kind === 'single' &&
|
|
199
|
+
((_b = responseBody.singleResult) === null || _b === void 0 ? void 0 : _b.errors) &&
|
|
200
|
+
responseBody.singleResult.errors.length > 0;
|
|
201
|
+
if (hasErrors &&
|
|
202
|
+
responseBody.kind === 'single' &&
|
|
203
|
+
((_c = responseBody.singleResult) === null || _c === void 0 ? void 0 : _c.errors)) {
|
|
204
|
+
for (const error of responseBody.singleResult.errors) {
|
|
205
|
+
const errorCode = ((_d = error.extensions) === null || _d === void 0 ? void 0 : _d.code) || 'INTERNAL_SERVER_ERROR';
|
|
206
|
+
exports.graphqlErrorsTotal.inc({
|
|
207
|
+
operation_type: operationType,
|
|
208
|
+
operation_name: operationName,
|
|
209
|
+
error_code: String(errorCode),
|
|
210
|
+
});
|
|
211
|
+
}
|
|
212
|
+
exports.graphqlOperationsTotal.inc({
|
|
213
|
+
operation_type: operationType,
|
|
214
|
+
operation_name: operationName,
|
|
215
|
+
status: 'error',
|
|
216
|
+
});
|
|
217
|
+
}
|
|
218
|
+
else {
|
|
219
|
+
exports.graphqlOperationsTotal.inc({
|
|
220
|
+
operation_type: operationType,
|
|
221
|
+
operation_name: operationName,
|
|
222
|
+
status: 'success',
|
|
223
|
+
});
|
|
224
|
+
}
|
|
225
|
+
},
|
|
226
|
+
};
|
|
227
|
+
},
|
|
228
|
+
};
|
|
229
|
+
}
|
|
230
|
+
// ---------------------------------------------------------------------------
|
|
231
|
+
// Metrics endpoint
|
|
232
|
+
// ---------------------------------------------------------------------------
|
|
233
|
+
/**
|
|
234
|
+
* Creates an Express router that exposes Prometheus metrics at GET /metrics.
|
|
235
|
+
*
|
|
236
|
+
* The endpoint returns metrics in Prometheus text exposition format.
|
|
237
|
+
* This should be scraped by a Prometheus server at regular intervals.
|
|
238
|
+
*
|
|
239
|
+
* Note: This endpoint should be protected in production (e.g., by firewall rules
|
|
240
|
+
* or by requiring a bearer token). It is excluded from rate limiting by default.
|
|
241
|
+
*/
|
|
242
|
+
function createMetricsRouter() {
|
|
243
|
+
const router = (0, express_1.Router)();
|
|
244
|
+
router.get('/metrics', async (_req, res) => {
|
|
245
|
+
try {
|
|
246
|
+
const metrics = await exports.metricsRegistry.metrics();
|
|
247
|
+
res.set('Content-Type', exports.metricsRegistry.contentType);
|
|
248
|
+
res.status(200).send(metrics);
|
|
249
|
+
}
|
|
250
|
+
catch (metricsError) {
|
|
251
|
+
logger_1.logger.error('Failed to generate metrics', {
|
|
252
|
+
error: metricsError instanceof Error
|
|
253
|
+
? metricsError.message
|
|
254
|
+
: String(metricsError),
|
|
255
|
+
});
|
|
256
|
+
res.status(500).send('Failed to generate metrics');
|
|
257
|
+
}
|
|
258
|
+
});
|
|
259
|
+
return router;
|
|
260
|
+
}
|
|
261
|
+
//# sourceMappingURL=metrics.js.map
|
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
import { Request, Response, Router } from 'express';
|
|
2
|
+
import { Registry, Counter, Histogram, Gauge } from 'prom-client';
|
|
3
|
+
/**
|
|
4
|
+
* Dedicated Prometheus registry for backend-legacy metrics.
|
|
5
|
+
* Using a dedicated registry avoids conflicts with default Node.js metrics
|
|
6
|
+
* that might be registered by other libraries.
|
|
7
|
+
*/
|
|
8
|
+
export declare const metricsRegistry: Registry<"text/plain; version=0.0.4; charset=utf-8">;
|
|
9
|
+
/** Counts total HTTP requests by method, route, and status code */
|
|
10
|
+
export declare const httpRequestsTotal: Counter<"route" | "method" | "status_code">;
|
|
11
|
+
/** Histogram of HTTP request durations in seconds */
|
|
12
|
+
export declare const httpRequestDuration: Histogram<"route" | "method" | "status_code">;
|
|
13
|
+
/** Counts total GraphQL operations by type and name */
|
|
14
|
+
export declare const graphqlOperationsTotal: Counter<"status" | "operation_type" | "operation_name">;
|
|
15
|
+
/** Histogram of GraphQL operation durations in seconds */
|
|
16
|
+
export declare const graphqlOperationDuration: Histogram<"operation_type" | "operation_name">;
|
|
17
|
+
/** Counts GraphQL errors by operation and error code */
|
|
18
|
+
export declare const graphqlErrorsTotal: Counter<"operation_type" | "operation_name" | "error_code">;
|
|
19
|
+
/** Histogram of Prisma query durations in seconds */
|
|
20
|
+
export declare const dbQueryDuration: Histogram<"operation" | "model">;
|
|
21
|
+
/** Gauge for active database connections */
|
|
22
|
+
export declare const dbConnectionsActive: Gauge<string>;
|
|
23
|
+
/** Gauge for active GraphQL subscriptions */
|
|
24
|
+
export declare const activeSubscriptions: Gauge<string>;
|
|
25
|
+
/** Gauge for active WebSocket connections */
|
|
26
|
+
export declare const activeWebSocketConnections: Gauge<string>;
|
|
27
|
+
/**
|
|
28
|
+
* Initializes Prometheus metrics collection.
|
|
29
|
+
*
|
|
30
|
+
* Registers default Node.js metrics (CPU, memory, event loop, GC) and
|
|
31
|
+
* application-specific metrics for HTTP, GraphQL, and database operations.
|
|
32
|
+
*
|
|
33
|
+
* Environment variables:
|
|
34
|
+
* - PROMETHEUS_METRICS_ENABLED: Explicit on/off ('true'/'false'). Defaults to on in production/staging.
|
|
35
|
+
*
|
|
36
|
+
* @returns true if metrics were initialized, false if disabled
|
|
37
|
+
*/
|
|
38
|
+
export declare function initMetrics(): boolean;
|
|
39
|
+
/**
|
|
40
|
+
* Express middleware that records HTTP request metrics.
|
|
41
|
+
* Tracks request count and duration for each method/route/status combination.
|
|
42
|
+
*
|
|
43
|
+
* Should be mounted early in the middleware chain to capture all requests.
|
|
44
|
+
*/
|
|
45
|
+
export declare function metricsMiddleware(req: Request, res: Response, next: () => void): void;
|
|
46
|
+
/**
|
|
47
|
+
* Creates an Apollo Server plugin that records GraphQL operation metrics.
|
|
48
|
+
*
|
|
49
|
+
* Tracks:
|
|
50
|
+
* - Operation count by type (query/mutation/subscription) and name
|
|
51
|
+
* - Operation duration
|
|
52
|
+
* - Error count by operation and error code
|
|
53
|
+
*
|
|
54
|
+
* @returns Apollo Server plugin configuration
|
|
55
|
+
*/
|
|
56
|
+
export declare function createMetricsPlugin(): {
|
|
57
|
+
requestDidStart: () => Promise<{
|
|
58
|
+
willSendResponse: (requestContext: {
|
|
59
|
+
operationName?: string | null;
|
|
60
|
+
operation?: {
|
|
61
|
+
operation: string;
|
|
62
|
+
} | null;
|
|
63
|
+
response: {
|
|
64
|
+
body: {
|
|
65
|
+
kind: string;
|
|
66
|
+
singleResult?: {
|
|
67
|
+
errors?: ReadonlyArray<{
|
|
68
|
+
extensions?: {
|
|
69
|
+
code?: string;
|
|
70
|
+
};
|
|
71
|
+
}>;
|
|
72
|
+
};
|
|
73
|
+
};
|
|
74
|
+
};
|
|
75
|
+
}) => Promise<void>;
|
|
76
|
+
}>;
|
|
77
|
+
};
|
|
78
|
+
/**
|
|
79
|
+
* Creates an Express router that exposes Prometheus metrics at GET /metrics.
|
|
80
|
+
*
|
|
81
|
+
* The endpoint returns metrics in Prometheus text exposition format.
|
|
82
|
+
* This should be scraped by a Prometheus server at regular intervals.
|
|
83
|
+
*
|
|
84
|
+
* Note: This endpoint should be protected in production (e.g., by firewall rules
|
|
85
|
+
* or by requiring a bearer token). It is excluded from rate limiting by default.
|
|
86
|
+
*/
|
|
87
|
+
export declare function createMetricsRouter(): Router;
|
|
88
|
+
//# sourceMappingURL=metrics.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"metrics.d.ts","sourceRoot":"","sources":["../../src/config/metrics.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,QAAQ,EAAE,MAAM,EAAE,MAAM,SAAS,CAAC;AACpD,OAAO,EACL,QAAQ,EACR,OAAO,EACP,SAAS,EACT,KAAK,EAEN,MAAM,aAAa,CAAC;AAKrB;;;;GAIG;AACH,eAAO,MAAM,eAAe,sDAAiB,CAAC;AAO9C,mEAAmE;AACnE,eAAO,MAAM,iBAAiB,6CAK5B,CAAC;AAEH,qDAAqD;AACrD,eAAO,MAAM,mBAAmB,+CAM9B,CAAC;AAEH,uDAAuD;AACvD,eAAO,MAAM,sBAAsB,yDAKjC,CAAC;AAEH,0DAA0D;AAC1D,eAAO,MAAM,wBAAwB,gDAMnC,CAAC;AAEH,wDAAwD;AACxD,eAAO,MAAM,kBAAkB,6DAK7B,CAAC;AAMH,qDAAqD;AACrD,eAAO,MAAM,eAAe,kCAM1B,CAAC;AAEH,4CAA4C;AAC5C,eAAO,MAAM,mBAAmB,eAI9B,CAAC;AAMH,6CAA6C;AAC7C,eAAO,MAAM,mBAAmB,eAI9B,CAAC;AAEH,6CAA6C;AAC7C,eAAO,MAAM,0BAA0B,eAIrC,CAAC;AAiCH;;;;;;;;;;GAUG;AACH,wBAAgB,WAAW,IAAI,OAAO,CAoBrC;AAMD;;;;;GAKG;AACH,wBAAgB,iBAAiB,CAC/B,GAAG,EAAE,OAAO,EACZ,GAAG,EAAE,QAAQ,EACb,IAAI,EAAE,MAAM,IAAI,GACf,IAAI,CAuBN;AAMD;;;;;;;;;GASG;AACH,wBAAgB,mBAAmB,IAAI;IACrC,eAAe,EAAE,MAAM,OAAO,CAAC;QAC7B,gBAAgB,EAAE,CAAC,cAAc,EAAE;YACjC,aAAa,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;YAC9B,SAAS,CAAC,EAAE;gBAAE,SAAS,EAAE,MAAM,CAAA;aAAE,GAAG,IAAI,CAAC;YACzC,QAAQ,EAAE;gBACR,IAAI,EAAE;oBACJ,IAAI,EAAE,MAAM,CAAC;oBACb,YAAY,CAAC,EAAE;wBACb,MAAM,CAAC,EAAE,aAAa,CAAC;4BAAE,UAAU,CAAC,EAAE;gCAAE,IAAI,CAAC,EAAE,MAAM,CAAA;6BAAE,CAAA;yBAAE,CAAC,CAAC;qBAC5D,CAAC;iBACH,CAAC;aACH,CAAC;SACH,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;KACrB,CAAC,CAAC;CACJ,CAuDA;AAMD;;;;;;;;GAQG;AACH,wBAAgB,mBAAmB,IAAI,MAAM,CAuB5C"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"metrics.js","sourceRoot":"","sources":["../../src/config/metrics.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,122 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.InMemoryAPQCache = void 0;
|
|
4
|
+
exports.isAPQEnabled = isAPQEnabled;
|
|
5
|
+
exports.createAPQCache = createAPQCache;
|
|
6
|
+
exports.getCacheControlPlugin = getCacheControlPlugin;
|
|
7
|
+
const disabled_1 = require("@apollo/server/plugin/disabled");
|
|
8
|
+
const logger_1 = require("../utils/logger.cjs");
|
|
9
|
+
/**
|
|
10
|
+
* Default cache TTL for persisted query hashes in seconds.
|
|
11
|
+
* Set to 0 to disable TTL (hashes persist indefinitely in memory).
|
|
12
|
+
*/
|
|
13
|
+
const DEFAULT_CACHE_TTL_SECONDS = 0;
|
|
14
|
+
/**
|
|
15
|
+
* Maximum size of the in-memory persisted query cache.
|
|
16
|
+
* Once exceeded, oldest entries are evicted (LRU).
|
|
17
|
+
*/
|
|
18
|
+
const DEFAULT_MAX_CACHE_SIZE = 1000;
|
|
19
|
+
/**
|
|
20
|
+
* Simple in-memory key-value cache implementing Apollo's KeyValueCache interface.
|
|
21
|
+
* Provides LRU eviction when the cache reaches maximum capacity.
|
|
22
|
+
*/
|
|
23
|
+
class InMemoryAPQCache {
|
|
24
|
+
constructor(maxSize) {
|
|
25
|
+
this.maxSize = maxSize || DEFAULT_MAX_CACHE_SIZE;
|
|
26
|
+
this.cache = new Map();
|
|
27
|
+
}
|
|
28
|
+
async get(key) {
|
|
29
|
+
const entry = this.cache.get(key);
|
|
30
|
+
if (!entry)
|
|
31
|
+
return undefined;
|
|
32
|
+
// Check TTL expiration
|
|
33
|
+
if (entry.expiresAt !== null && Date.now() > entry.expiresAt) {
|
|
34
|
+
this.cache.delete(key);
|
|
35
|
+
return undefined;
|
|
36
|
+
}
|
|
37
|
+
// Move to end for LRU ordering (Map preserves insertion order)
|
|
38
|
+
this.cache.delete(key);
|
|
39
|
+
this.cache.set(key, entry);
|
|
40
|
+
return entry.value;
|
|
41
|
+
}
|
|
42
|
+
async set(key, value, options) {
|
|
43
|
+
var _a;
|
|
44
|
+
// Evict oldest entry if at capacity
|
|
45
|
+
if (this.cache.size >= this.maxSize && !this.cache.has(key)) {
|
|
46
|
+
const oldestKey = this.cache.keys().next().value;
|
|
47
|
+
if (oldestKey !== undefined) {
|
|
48
|
+
this.cache.delete(oldestKey);
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
const ttlSeconds = (_a = options === null || options === void 0 ? void 0 : options.ttl) !== null && _a !== void 0 ? _a : DEFAULT_CACHE_TTL_SECONDS;
|
|
52
|
+
const expiresAt = ttlSeconds > 0 ? Date.now() + ttlSeconds * 1000 : null;
|
|
53
|
+
this.cache.set(key, { value, expiresAt });
|
|
54
|
+
}
|
|
55
|
+
async delete(key) {
|
|
56
|
+
return this.cache.delete(key);
|
|
57
|
+
}
|
|
58
|
+
/** Returns the current number of cached entries */
|
|
59
|
+
get size() {
|
|
60
|
+
return this.cache.size;
|
|
61
|
+
}
|
|
62
|
+
/** Clears all cached entries */
|
|
63
|
+
clear() {
|
|
64
|
+
this.cache.clear();
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
exports.InMemoryAPQCache = InMemoryAPQCache;
|
|
68
|
+
/**
|
|
69
|
+
* Determines if APQ (Automatic Persisted Queries) is enabled.
|
|
70
|
+
* Enabled by default. Disable via APQ_ENABLED=false.
|
|
71
|
+
*/
|
|
72
|
+
function isAPQEnabled() {
|
|
73
|
+
const setting = process.env.APQ_ENABLED;
|
|
74
|
+
if (setting !== undefined) {
|
|
75
|
+
return setting !== 'false' && setting !== '0';
|
|
76
|
+
}
|
|
77
|
+
return true;
|
|
78
|
+
}
|
|
79
|
+
/**
|
|
80
|
+
* Resolves the maximum APQ cache size from environment variables.
|
|
81
|
+
*/
|
|
82
|
+
function getMaxCacheSize() {
|
|
83
|
+
const envValue = process.env.APQ_MAX_CACHE_SIZE;
|
|
84
|
+
if (envValue) {
|
|
85
|
+
const parsed = parseInt(envValue, 10);
|
|
86
|
+
if (!isNaN(parsed) && parsed > 0)
|
|
87
|
+
return parsed;
|
|
88
|
+
}
|
|
89
|
+
return DEFAULT_MAX_CACHE_SIZE;
|
|
90
|
+
}
|
|
91
|
+
/**
|
|
92
|
+
* Creates and returns an APQ cache instance for use with Apollo Server.
|
|
93
|
+
*
|
|
94
|
+
* Apollo Server 5 enables APQ by default when a cache is available.
|
|
95
|
+
* To disable APQ entirely, set APQ_ENABLED=false.
|
|
96
|
+
*
|
|
97
|
+
* @returns The configured APQ cache, or undefined if APQ is disabled
|
|
98
|
+
*/
|
|
99
|
+
function createAPQCache() {
|
|
100
|
+
if (!isAPQEnabled()) {
|
|
101
|
+
logger_1.logger.info('Automatic Persisted Queries (APQ) disabled');
|
|
102
|
+
return undefined;
|
|
103
|
+
}
|
|
104
|
+
const maxSize = getMaxCacheSize();
|
|
105
|
+
const cache = new InMemoryAPQCache(maxSize);
|
|
106
|
+
logger_1.logger.info('Automatic Persisted Queries (APQ) enabled', {
|
|
107
|
+
maxCacheSize: maxSize,
|
|
108
|
+
});
|
|
109
|
+
return cache;
|
|
110
|
+
}
|
|
111
|
+
/**
|
|
112
|
+
* Returns the Apollo Server cache control plugin configuration.
|
|
113
|
+
* When APQ is disabled, this returns the cache control disabled plugin
|
|
114
|
+
* to explicitly disable caching behavior.
|
|
115
|
+
*/
|
|
116
|
+
function getCacheControlPlugin() {
|
|
117
|
+
if (!isAPQEnabled()) {
|
|
118
|
+
return (0, disabled_1.ApolloServerPluginCacheControlDisabled)();
|
|
119
|
+
}
|
|
120
|
+
return undefined;
|
|
121
|
+
}
|
|
122
|
+
//# sourceMappingURL=persisted-queries.js.map
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
import { ApolloServerPluginCacheControlDisabled } from '@apollo/server/plugin/disabled';
|
|
2
|
+
/**
|
|
3
|
+
* Simple in-memory key-value cache implementing Apollo's KeyValueCache interface.
|
|
4
|
+
* Provides LRU eviction when the cache reaches maximum capacity.
|
|
5
|
+
*/
|
|
6
|
+
export declare class InMemoryAPQCache {
|
|
7
|
+
private cache;
|
|
8
|
+
private readonly maxSize;
|
|
9
|
+
constructor(maxSize?: number);
|
|
10
|
+
get(key: string): Promise<string | undefined>;
|
|
11
|
+
set(key: string, value: string, options?: {
|
|
12
|
+
ttl?: number | null;
|
|
13
|
+
}): Promise<void>;
|
|
14
|
+
delete(key: string): Promise<boolean>;
|
|
15
|
+
/** Returns the current number of cached entries */
|
|
16
|
+
get size(): number;
|
|
17
|
+
/** Clears all cached entries */
|
|
18
|
+
clear(): void;
|
|
19
|
+
}
|
|
20
|
+
/**
|
|
21
|
+
* Determines if APQ (Automatic Persisted Queries) is enabled.
|
|
22
|
+
* Enabled by default. Disable via APQ_ENABLED=false.
|
|
23
|
+
*/
|
|
24
|
+
export declare function isAPQEnabled(): boolean;
|
|
25
|
+
/**
|
|
26
|
+
* Creates and returns an APQ cache instance for use with Apollo Server.
|
|
27
|
+
*
|
|
28
|
+
* Apollo Server 5 enables APQ by default when a cache is available.
|
|
29
|
+
* To disable APQ entirely, set APQ_ENABLED=false.
|
|
30
|
+
*
|
|
31
|
+
* @returns The configured APQ cache, or undefined if APQ is disabled
|
|
32
|
+
*/
|
|
33
|
+
export declare function createAPQCache(): InMemoryAPQCache | undefined;
|
|
34
|
+
/**
|
|
35
|
+
* Returns the Apollo Server cache control plugin configuration.
|
|
36
|
+
* When APQ is disabled, this returns the cache control disabled plugin
|
|
37
|
+
* to explicitly disable caching behavior.
|
|
38
|
+
*/
|
|
39
|
+
export declare function getCacheControlPlugin(): ReturnType<typeof ApolloServerPluginCacheControlDisabled> | undefined;
|
|
40
|
+
//# sourceMappingURL=persisted-queries.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"persisted-queries.d.ts","sourceRoot":"","sources":["../../src/config/persisted-queries.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,sCAAsC,EAAE,MAAM,gCAAgC,CAAC;AAwCxF;;;GAGG;AACH,qBAAa,gBAAgB;IAC3B,OAAO,CAAC,KAAK,CAA0B;IACvC,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAS;gBAErB,OAAO,CAAC,EAAE,MAAM;IAKtB,GAAG,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,GAAG,SAAS,CAAC;IAgB7C,GAAG,CACP,GAAG,EAAE,MAAM,EACX,KAAK,EAAE,MAAM,EACb,OAAO,CAAC,EAAE;QAAE,GAAG,CAAC,EAAE,MAAM,GAAG,IAAI,CAAA;KAAE,GAChC,OAAO,CAAC,IAAI,CAAC;IAcV,MAAM,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC;IAI3C,mDAAmD;IACnD,IAAI,IAAI,IAAI,MAAM,CAEjB;IAED,gCAAgC;IAChC,KAAK,IAAI,IAAI;CAGd;AAED;;;GAGG;AACH,wBAAgB,YAAY,IAAI,OAAO,CAMtC;AAcD;;;;;;;GAOG;AACH,wBAAgB,cAAc,IAAI,gBAAgB,GAAG,SAAS,CAa7D;AAED;;;;GAIG;AACH,wBAAgB,qBAAqB,IACjC,UAAU,CAAC,OAAO,sCAAsC,CAAC,GACzD,SAAS,CAKZ"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"persisted-queries.js","sourceRoot":"","sources":["../../src/config/persisted-queries.ts"],"names":[],"mappings":"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"}
|