apitally 0.17.4 → 0.18.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.
- package/README.md +2 -5
- package/dist/fastify/index.cjs +54 -28
- package/dist/fastify/index.cjs.map +1 -1
- package/dist/fastify/index.js +54 -28
- package/dist/fastify/index.js.map +1 -1
- package/dist/fastify/plugin.cjs +56 -28
- package/dist/fastify/plugin.cjs.map +1 -1
- package/dist/fastify/plugin.d.cts +3 -1
- package/dist/fastify/plugin.d.ts +3 -1
- package/dist/fastify/plugin.js +55 -28
- package/dist/fastify/plugin.js.map +1 -1
- package/dist/nestjs/index.cjs +1517 -1137
- package/dist/nestjs/index.cjs.map +1 -1
- package/dist/nestjs/index.d.cts +4 -6
- package/dist/nestjs/index.d.ts +4 -6
- package/dist/nestjs/index.js +1501 -1119
- package/dist/nestjs/index.js.map +1 -1
- package/package.json +9 -4
package/dist/nestjs/index.cjs
CHANGED
|
@@ -7,6 +7,9 @@ var __getProtoOf = Object.getPrototypeOf;
|
|
|
7
7
|
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
8
8
|
var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
|
|
9
9
|
var __name = (target, value) => __defProp(target, "name", { value, configurable: true });
|
|
10
|
+
var __esm = (fn, res) => function __init() {
|
|
11
|
+
return fn && (res = (0, fn[__getOwnPropNames(fn)[0]])(fn = 0)), res;
|
|
12
|
+
};
|
|
10
13
|
var __commonJS = (cb, mod) => function __require() {
|
|
11
14
|
return mod || (0, cb[__getOwnPropNames(cb)[0]])((mod = { exports: {} }).exports, mod), mod.exports;
|
|
12
15
|
};
|
|
@@ -11020,272 +11023,217 @@ var require_cjs = __commonJS({
|
|
|
11020
11023
|
}
|
|
11021
11024
|
});
|
|
11022
11025
|
|
|
11023
|
-
// src/nestjs/index.ts
|
|
11024
|
-
var nestjs_exports = {};
|
|
11025
|
-
__export(nestjs_exports, {
|
|
11026
|
-
setConsumer: () => setConsumer,
|
|
11027
|
-
useApitally: () => useApitally2
|
|
11028
|
-
});
|
|
11029
|
-
module.exports = __toCommonJS(nestjs_exports);
|
|
11030
|
-
var import_common = require("@nestjs/common");
|
|
11031
|
-
var import_rxjs = __toESM(require_cjs(), 1);
|
|
11032
|
-
|
|
11033
|
-
// src/express/middleware.ts
|
|
11034
|
-
var import_perf_hooks = require("perf_hooks");
|
|
11035
|
-
|
|
11036
|
-
// src/common/client.ts
|
|
11037
|
-
var import_crypto5 = require("crypto");
|
|
11038
|
-
var import_fetch_retry = __toESM(require("fetch-retry"), 1);
|
|
11039
|
-
|
|
11040
11026
|
// src/common/consumerRegistry.ts
|
|
11041
|
-
var consumerFromStringOrObject
|
|
11042
|
-
|
|
11043
|
-
|
|
11044
|
-
|
|
11045
|
-
|
|
11046
|
-
|
|
11047
|
-
|
|
11048
|
-
|
|
11049
|
-
|
|
11050
|
-
|
|
11051
|
-
|
|
11052
|
-
|
|
11053
|
-
|
|
11054
|
-
|
|
11055
|
-
|
|
11056
|
-
|
|
11057
|
-
|
|
11058
|
-
|
|
11059
|
-
|
|
11060
|
-
|
|
11061
|
-
|
|
11062
|
-
|
|
11063
|
-
|
|
11064
|
-
|
|
11065
|
-
|
|
11066
|
-
|
|
11067
|
-
|
|
11068
|
-
|
|
11069
|
-
|
|
11070
|
-
|
|
11071
|
-
|
|
11072
|
-
|
|
11073
|
-
|
|
11074
|
-
|
|
11075
|
-
|
|
11076
|
-
|
|
11077
|
-
|
|
11027
|
+
var consumerFromStringOrObject, _ConsumerRegistry, ConsumerRegistry;
|
|
11028
|
+
var init_consumerRegistry = __esm({
|
|
11029
|
+
"src/common/consumerRegistry.ts"() {
|
|
11030
|
+
"use strict";
|
|
11031
|
+
consumerFromStringOrObject = /* @__PURE__ */ __name((consumer) => {
|
|
11032
|
+
var _a3, _b;
|
|
11033
|
+
if (typeof consumer === "string") {
|
|
11034
|
+
consumer = String(consumer).trim().substring(0, 128);
|
|
11035
|
+
return consumer ? {
|
|
11036
|
+
identifier: consumer
|
|
11037
|
+
} : null;
|
|
11038
|
+
} else {
|
|
11039
|
+
consumer.identifier = String(consumer.identifier).trim().substring(0, 128);
|
|
11040
|
+
consumer.name = (_a3 = consumer.name) == null ? void 0 : _a3.trim().substring(0, 64);
|
|
11041
|
+
consumer.group = (_b = consumer.group) == null ? void 0 : _b.trim().substring(0, 64);
|
|
11042
|
+
return consumer.identifier ? consumer : null;
|
|
11043
|
+
}
|
|
11044
|
+
}, "consumerFromStringOrObject");
|
|
11045
|
+
_ConsumerRegistry = class _ConsumerRegistry {
|
|
11046
|
+
consumers;
|
|
11047
|
+
updated;
|
|
11048
|
+
constructor() {
|
|
11049
|
+
this.consumers = /* @__PURE__ */ new Map();
|
|
11050
|
+
this.updated = /* @__PURE__ */ new Set();
|
|
11051
|
+
}
|
|
11052
|
+
addOrUpdateConsumer(consumer) {
|
|
11053
|
+
if (!consumer || !consumer.name && !consumer.group) {
|
|
11054
|
+
return;
|
|
11055
|
+
}
|
|
11056
|
+
const existing = this.consumers.get(consumer.identifier);
|
|
11057
|
+
if (!existing) {
|
|
11058
|
+
this.consumers.set(consumer.identifier, consumer);
|
|
11059
|
+
this.updated.add(consumer.identifier);
|
|
11060
|
+
} else {
|
|
11061
|
+
if (consumer.name && consumer.name !== existing.name) {
|
|
11062
|
+
existing.name = consumer.name;
|
|
11063
|
+
this.updated.add(consumer.identifier);
|
|
11064
|
+
}
|
|
11065
|
+
if (consumer.group && consumer.group !== existing.group) {
|
|
11066
|
+
existing.group = consumer.group;
|
|
11067
|
+
this.updated.add(consumer.identifier);
|
|
11068
|
+
}
|
|
11069
|
+
}
|
|
11078
11070
|
}
|
|
11079
|
-
|
|
11080
|
-
|
|
11081
|
-
|
|
11082
|
-
|
|
11083
|
-
|
|
11084
|
-
|
|
11085
|
-
|
|
11086
|
-
|
|
11071
|
+
getAndResetUpdatedConsumers() {
|
|
11072
|
+
const data = [];
|
|
11073
|
+
this.updated.forEach((identifier) => {
|
|
11074
|
+
const consumer = this.consumers.get(identifier);
|
|
11075
|
+
if (consumer) {
|
|
11076
|
+
data.push(consumer);
|
|
11077
|
+
}
|
|
11078
|
+
});
|
|
11079
|
+
this.updated.clear();
|
|
11080
|
+
return data;
|
|
11087
11081
|
}
|
|
11088
|
-
}
|
|
11089
|
-
|
|
11090
|
-
|
|
11082
|
+
};
|
|
11083
|
+
__name(_ConsumerRegistry, "ConsumerRegistry");
|
|
11084
|
+
ConsumerRegistry = _ConsumerRegistry;
|
|
11091
11085
|
}
|
|
11092
|
-
};
|
|
11093
|
-
__name(_ConsumerRegistry, "ConsumerRegistry");
|
|
11094
|
-
var ConsumerRegistry = _ConsumerRegistry;
|
|
11086
|
+
});
|
|
11095
11087
|
|
|
11096
11088
|
// src/common/logging.ts
|
|
11097
|
-
var import_winston
|
|
11098
|
-
var
|
|
11099
|
-
|
|
11100
|
-
|
|
11101
|
-
|
|
11102
|
-
|
|
11103
|
-
|
|
11104
|
-
|
|
11105
|
-
|
|
11106
|
-
|
|
11089
|
+
var import_winston, getLogger;
|
|
11090
|
+
var init_logging = __esm({
|
|
11091
|
+
"src/common/logging.ts"() {
|
|
11092
|
+
"use strict";
|
|
11093
|
+
import_winston = require("winston");
|
|
11094
|
+
getLogger = /* @__PURE__ */ __name(() => {
|
|
11095
|
+
return (0, import_winston.createLogger)({
|
|
11096
|
+
level: process.env.APITALLY_DEBUG ? "debug" : "warn",
|
|
11097
|
+
format: import_winston.format.combine(import_winston.format.colorize(), import_winston.format.timestamp(), import_winston.format.printf((info) => `${info.timestamp} ${info.level}: ${info.message}`)),
|
|
11098
|
+
transports: [
|
|
11099
|
+
new import_winston.transports.Console()
|
|
11100
|
+
]
|
|
11101
|
+
});
|
|
11102
|
+
}, "getLogger");
|
|
11103
|
+
}
|
|
11104
|
+
});
|
|
11107
11105
|
|
|
11108
11106
|
// src/common/paramValidation.ts
|
|
11109
11107
|
function isValidClientId(clientId) {
|
|
11110
11108
|
const regexExp = /^[0-9a-f]{8}-[0-9a-f]{4}-[4][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i;
|
|
11111
11109
|
return regexExp.test(clientId);
|
|
11112
11110
|
}
|
|
11113
|
-
__name(isValidClientId, "isValidClientId");
|
|
11114
11111
|
function isValidEnv(env) {
|
|
11115
11112
|
const regexExp = /^[\w-]{1,32}$/;
|
|
11116
11113
|
return regexExp.test(env);
|
|
11117
11114
|
}
|
|
11118
|
-
|
|
11115
|
+
var init_paramValidation = __esm({
|
|
11116
|
+
"src/common/paramValidation.ts"() {
|
|
11117
|
+
"use strict";
|
|
11118
|
+
__name(isValidClientId, "isValidClientId");
|
|
11119
|
+
__name(isValidEnv, "isValidEnv");
|
|
11120
|
+
}
|
|
11121
|
+
});
|
|
11119
11122
|
|
|
11120
11123
|
// src/common/requestCounter.ts
|
|
11121
|
-
var _RequestCounter
|
|
11122
|
-
|
|
11123
|
-
|
|
11124
|
-
|
|
11125
|
-
|
|
11126
|
-
|
|
11127
|
-
|
|
11128
|
-
|
|
11129
|
-
|
|
11130
|
-
|
|
11131
|
-
|
|
11132
|
-
|
|
11133
|
-
|
|
11134
|
-
|
|
11135
|
-
|
|
11136
|
-
|
|
11137
|
-
|
|
11138
|
-
|
|
11139
|
-
|
|
11140
|
-
requestInfo
|
|
11141
|
-
|
|
11142
|
-
|
|
11143
|
-
|
|
11144
|
-
|
|
11145
|
-
|
|
11146
|
-
|
|
11147
|
-
|
|
11148
|
-
|
|
11149
|
-
|
|
11150
|
-
|
|
11151
|
-
|
|
11152
|
-
|
|
11153
|
-
|
|
11154
|
-
|
|
11155
|
-
|
|
11156
|
-
|
|
11157
|
-
|
|
11158
|
-
|
|
11159
|
-
|
|
11160
|
-
|
|
11161
|
-
|
|
11162
|
-
|
|
11163
|
-
|
|
11164
|
-
|
|
11165
|
-
|
|
11166
|
-
|
|
11167
|
-
|
|
11168
|
-
|
|
11169
|
-
|
|
11170
|
-
|
|
11171
|
-
|
|
11172
|
-
|
|
11173
|
-
|
|
11174
|
-
|
|
11175
|
-
|
|
11176
|
-
|
|
11177
|
-
|
|
11178
|
-
|
|
11179
|
-
|
|
11180
|
-
|
|
11181
|
-
|
|
11182
|
-
|
|
11183
|
-
|
|
11184
|
-
|
|
11185
|
-
|
|
11186
|
-
|
|
11187
|
-
|
|
11188
|
-
|
|
11189
|
-
|
|
11190
|
-
|
|
11191
|
-
|
|
11192
|
-
|
|
11193
|
-
|
|
11194
|
-
|
|
11195
|
-
|
|
11196
|
-
|
|
11197
|
-
|
|
11198
|
-
|
|
11199
|
-
|
|
11200
|
-
|
|
11124
|
+
var _RequestCounter, RequestCounter;
|
|
11125
|
+
var init_requestCounter = __esm({
|
|
11126
|
+
"src/common/requestCounter.ts"() {
|
|
11127
|
+
"use strict";
|
|
11128
|
+
_RequestCounter = class _RequestCounter {
|
|
11129
|
+
requestCounts;
|
|
11130
|
+
requestSizeSums;
|
|
11131
|
+
responseSizeSums;
|
|
11132
|
+
responseTimes;
|
|
11133
|
+
requestSizes;
|
|
11134
|
+
responseSizes;
|
|
11135
|
+
constructor() {
|
|
11136
|
+
this.requestCounts = /* @__PURE__ */ new Map();
|
|
11137
|
+
this.requestSizeSums = /* @__PURE__ */ new Map();
|
|
11138
|
+
this.responseSizeSums = /* @__PURE__ */ new Map();
|
|
11139
|
+
this.responseTimes = /* @__PURE__ */ new Map();
|
|
11140
|
+
this.requestSizes = /* @__PURE__ */ new Map();
|
|
11141
|
+
this.responseSizes = /* @__PURE__ */ new Map();
|
|
11142
|
+
}
|
|
11143
|
+
getKey(requestInfo) {
|
|
11144
|
+
return [
|
|
11145
|
+
requestInfo.consumer || "",
|
|
11146
|
+
requestInfo.method.toUpperCase(),
|
|
11147
|
+
requestInfo.path,
|
|
11148
|
+
requestInfo.statusCode
|
|
11149
|
+
].join("|");
|
|
11150
|
+
}
|
|
11151
|
+
addRequest(requestInfo) {
|
|
11152
|
+
const key = this.getKey(requestInfo);
|
|
11153
|
+
this.requestCounts.set(key, (this.requestCounts.get(key) || 0) + 1);
|
|
11154
|
+
if (!this.responseTimes.has(key)) {
|
|
11155
|
+
this.responseTimes.set(key, /* @__PURE__ */ new Map());
|
|
11156
|
+
}
|
|
11157
|
+
const responseTimeMap = this.responseTimes.get(key);
|
|
11158
|
+
const responseTimeMsBin = Math.floor(requestInfo.responseTime / 10) * 10;
|
|
11159
|
+
responseTimeMap.set(responseTimeMsBin, (responseTimeMap.get(responseTimeMsBin) || 0) + 1);
|
|
11160
|
+
if (requestInfo.requestSize !== void 0) {
|
|
11161
|
+
requestInfo.requestSize = Number(requestInfo.requestSize);
|
|
11162
|
+
this.requestSizeSums.set(key, (this.requestSizeSums.get(key) || 0) + requestInfo.requestSize);
|
|
11163
|
+
if (!this.requestSizes.has(key)) {
|
|
11164
|
+
this.requestSizes.set(key, /* @__PURE__ */ new Map());
|
|
11165
|
+
}
|
|
11166
|
+
const requestSizeMap = this.requestSizes.get(key);
|
|
11167
|
+
const requestSizeKbBin = Math.floor(requestInfo.requestSize / 1e3);
|
|
11168
|
+
requestSizeMap.set(requestSizeKbBin, (requestSizeMap.get(requestSizeKbBin) || 0) + 1);
|
|
11169
|
+
}
|
|
11170
|
+
if (requestInfo.responseSize !== void 0) {
|
|
11171
|
+
requestInfo.responseSize = Number(requestInfo.responseSize);
|
|
11172
|
+
this.responseSizeSums.set(key, (this.responseSizeSums.get(key) || 0) + requestInfo.responseSize);
|
|
11173
|
+
if (!this.responseSizes.has(key)) {
|
|
11174
|
+
this.responseSizes.set(key, /* @__PURE__ */ new Map());
|
|
11175
|
+
}
|
|
11176
|
+
const responseSizeMap = this.responseSizes.get(key);
|
|
11177
|
+
const responseSizeKbBin = Math.floor(requestInfo.responseSize / 1e3);
|
|
11178
|
+
responseSizeMap.set(responseSizeKbBin, (responseSizeMap.get(responseSizeKbBin) || 0) + 1);
|
|
11179
|
+
}
|
|
11180
|
+
}
|
|
11181
|
+
getAndResetRequests() {
|
|
11182
|
+
const data = [];
|
|
11183
|
+
this.requestCounts.forEach((count, key) => {
|
|
11184
|
+
const [consumer, method, path, statusCodeStr] = key.split("|");
|
|
11185
|
+
const responseTimes = this.responseTimes.get(key) || /* @__PURE__ */ new Map();
|
|
11186
|
+
const requestSizes = this.requestSizes.get(key) || /* @__PURE__ */ new Map();
|
|
11187
|
+
const responseSizes = this.responseSizes.get(key) || /* @__PURE__ */ new Map();
|
|
11188
|
+
data.push({
|
|
11189
|
+
consumer: consumer || null,
|
|
11190
|
+
method,
|
|
11191
|
+
path,
|
|
11192
|
+
status_code: parseInt(statusCodeStr),
|
|
11193
|
+
request_count: count,
|
|
11194
|
+
request_size_sum: this.requestSizeSums.get(key) || 0,
|
|
11195
|
+
response_size_sum: this.responseSizeSums.get(key) || 0,
|
|
11196
|
+
response_times: Object.fromEntries(responseTimes),
|
|
11197
|
+
request_sizes: Object.fromEntries(requestSizes),
|
|
11198
|
+
response_sizes: Object.fromEntries(responseSizes)
|
|
11199
|
+
});
|
|
11200
|
+
});
|
|
11201
|
+
this.requestCounts.clear();
|
|
11202
|
+
this.requestSizeSums.clear();
|
|
11203
|
+
this.responseSizeSums.clear();
|
|
11204
|
+
this.responseTimes.clear();
|
|
11205
|
+
this.requestSizes.clear();
|
|
11206
|
+
this.responseSizes.clear();
|
|
11207
|
+
return data;
|
|
11208
|
+
}
|
|
11209
|
+
};
|
|
11210
|
+
__name(_RequestCounter, "RequestCounter");
|
|
11211
|
+
RequestCounter = _RequestCounter;
|
|
11201
11212
|
}
|
|
11202
|
-
};
|
|
11203
|
-
__name(_RequestCounter, "RequestCounter");
|
|
11204
|
-
var RequestCounter = _RequestCounter;
|
|
11205
|
-
|
|
11206
|
-
// src/common/requestLogger.ts
|
|
11207
|
-
var import_async_lock = __toESM(require("async-lock"), 1);
|
|
11208
|
-
var import_buffer2 = require("buffer");
|
|
11209
|
-
var import_crypto3 = require("crypto");
|
|
11210
|
-
var import_fs2 = require("fs");
|
|
11211
|
-
var import_os2 = require("os");
|
|
11212
|
-
var import_path2 = require("path");
|
|
11213
|
+
});
|
|
11213
11214
|
|
|
11214
11215
|
// src/common/sentry.ts
|
|
11215
|
-
var sentry;
|
|
11216
|
-
(async () => {
|
|
11217
|
-
try {
|
|
11218
|
-
sentry = await import("@sentry/node");
|
|
11219
|
-
} catch (e) {
|
|
11220
|
-
}
|
|
11221
|
-
})();
|
|
11222
11216
|
function getSentryEventId() {
|
|
11223
11217
|
if (sentry && sentry.lastEventId) {
|
|
11224
11218
|
return sentry.lastEventId();
|
|
11225
11219
|
}
|
|
11226
11220
|
return void 0;
|
|
11227
11221
|
}
|
|
11228
|
-
|
|
11229
|
-
|
|
11230
|
-
|
|
11231
|
-
|
|
11232
|
-
|
|
11233
|
-
|
|
11234
|
-
|
|
11235
|
-
|
|
11236
|
-
errorDetails;
|
|
11237
|
-
sentryEventIds;
|
|
11238
|
-
constructor() {
|
|
11239
|
-
this.errorCounts = /* @__PURE__ */ new Map();
|
|
11240
|
-
this.errorDetails = /* @__PURE__ */ new Map();
|
|
11241
|
-
this.sentryEventIds = /* @__PURE__ */ new Map();
|
|
11242
|
-
}
|
|
11243
|
-
addServerError(serverError) {
|
|
11244
|
-
const key = this.getKey(serverError);
|
|
11245
|
-
if (!this.errorDetails.has(key)) {
|
|
11246
|
-
this.errorDetails.set(key, serverError);
|
|
11247
|
-
}
|
|
11248
|
-
this.errorCounts.set(key, (this.errorCounts.get(key) || 0) + 1);
|
|
11249
|
-
const sentryEventId = getSentryEventId();
|
|
11250
|
-
if (sentryEventId) {
|
|
11251
|
-
this.sentryEventIds.set(key, sentryEventId);
|
|
11252
|
-
}
|
|
11253
|
-
}
|
|
11254
|
-
getAndResetServerErrors() {
|
|
11255
|
-
const data = [];
|
|
11256
|
-
this.errorCounts.forEach((count, key) => {
|
|
11257
|
-
const serverError = this.errorDetails.get(key);
|
|
11258
|
-
if (serverError) {
|
|
11259
|
-
data.push({
|
|
11260
|
-
consumer: serverError.consumer || null,
|
|
11261
|
-
method: serverError.method,
|
|
11262
|
-
path: serverError.path,
|
|
11263
|
-
type: serverError.type,
|
|
11264
|
-
msg: truncateExceptionMessage(serverError.msg),
|
|
11265
|
-
traceback: truncateExceptionStackTrace(serverError.traceback),
|
|
11266
|
-
sentry_event_id: this.sentryEventIds.get(key) || null,
|
|
11267
|
-
error_count: count
|
|
11268
|
-
});
|
|
11222
|
+
var sentry;
|
|
11223
|
+
var init_sentry = __esm({
|
|
11224
|
+
"src/common/sentry.ts"() {
|
|
11225
|
+
"use strict";
|
|
11226
|
+
(async () => {
|
|
11227
|
+
try {
|
|
11228
|
+
sentry = await import("@sentry/node");
|
|
11229
|
+
} catch (e) {
|
|
11269
11230
|
}
|
|
11270
|
-
});
|
|
11271
|
-
|
|
11272
|
-
this.errorDetails.clear();
|
|
11273
|
-
return data;
|
|
11231
|
+
})();
|
|
11232
|
+
__name(getSentryEventId, "getSentryEventId");
|
|
11274
11233
|
}
|
|
11275
|
-
|
|
11276
|
-
|
|
11277
|
-
|
|
11278
|
-
serverError.method.toUpperCase(),
|
|
11279
|
-
serverError.path,
|
|
11280
|
-
serverError.type,
|
|
11281
|
-
serverError.msg.trim(),
|
|
11282
|
-
serverError.traceback.trim()
|
|
11283
|
-
].join("|");
|
|
11284
|
-
return (0, import_crypto.createHash)("md5").update(hashInput).digest("hex");
|
|
11285
|
-
}
|
|
11286
|
-
};
|
|
11287
|
-
__name(_ServerErrorCounter, "ServerErrorCounter");
|
|
11288
|
-
var ServerErrorCounter = _ServerErrorCounter;
|
|
11234
|
+
});
|
|
11235
|
+
|
|
11236
|
+
// src/common/serverErrorCounter.ts
|
|
11289
11237
|
function truncateExceptionMessage(msg) {
|
|
11290
11238
|
if (msg.length <= MAX_MSG_LENGTH) {
|
|
11291
11239
|
return msg;
|
|
@@ -11294,7 +11242,6 @@ function truncateExceptionMessage(msg) {
|
|
|
11294
11242
|
const cutoff = MAX_MSG_LENGTH - suffix.length;
|
|
11295
11243
|
return msg.substring(0, cutoff) + suffix;
|
|
11296
11244
|
}
|
|
11297
|
-
__name(truncateExceptionMessage, "truncateExceptionMessage");
|
|
11298
11245
|
function truncateExceptionStackTrace(stack) {
|
|
11299
11246
|
const suffix = "... (truncated) ...";
|
|
11300
11247
|
const cutoff = MAX_STACKTRACE_LENGTH - suffix.length;
|
|
@@ -11311,413 +11258,155 @@ function truncateExceptionStackTrace(stack) {
|
|
|
11311
11258
|
}
|
|
11312
11259
|
return truncatedLines.join("\n");
|
|
11313
11260
|
}
|
|
11314
|
-
|
|
11315
|
-
|
|
11316
|
-
|
|
11317
|
-
|
|
11318
|
-
|
|
11319
|
-
|
|
11320
|
-
|
|
11321
|
-
|
|
11322
|
-
|
|
11323
|
-
|
|
11324
|
-
|
|
11325
|
-
|
|
11326
|
-
|
|
11327
|
-
|
|
11328
|
-
|
|
11329
|
-
|
|
11330
|
-
|
|
11331
|
-
|
|
11332
|
-
|
|
11333
|
-
|
|
11334
|
-
|
|
11335
|
-
|
|
11336
|
-
|
|
11337
|
-
|
|
11338
|
-
|
|
11339
|
-
|
|
11340
|
-
|
|
11341
|
-
|
|
11342
|
-
|
|
11343
|
-
|
|
11344
|
-
|
|
11345
|
-
|
|
11346
|
-
|
|
11347
|
-
|
|
11348
|
-
|
|
11349
|
-
|
|
11350
|
-
|
|
11351
|
-
|
|
11352
|
-
|
|
11353
|
-
|
|
11354
|
-
|
|
11355
|
-
|
|
11356
|
-
|
|
11357
|
-
|
|
11358
|
-
|
|
11359
|
-
|
|
11360
|
-
|
|
11361
|
-
|
|
11362
|
-
|
|
11363
|
-
|
|
11364
|
-
|
|
11365
|
-
|
|
11366
|
-
|
|
11367
|
-
|
|
11368
|
-
|
|
11369
|
-
|
|
11370
|
-
|
|
11371
|
-
|
|
11372
|
-
|
|
11373
|
-
}
|
|
11374
|
-
async close() {
|
|
11375
|
-
await new Promise((resolve) => {
|
|
11376
|
-
this.gzip.end(() => {
|
|
11377
|
-
resolve();
|
|
11378
|
-
});
|
|
11379
|
-
});
|
|
11380
|
-
await this.closedPromise;
|
|
11381
|
-
}
|
|
11382
|
-
async delete() {
|
|
11383
|
-
await this.close();
|
|
11384
|
-
(0, import_fs.unlinkSync)(this.filePath);
|
|
11385
|
-
}
|
|
11386
|
-
};
|
|
11387
|
-
__name(_TempGzipFile, "TempGzipFile");
|
|
11388
|
-
var TempGzipFile = _TempGzipFile;
|
|
11389
|
-
|
|
11390
|
-
// src/common/requestLogger.ts
|
|
11391
|
-
var MAX_BODY_SIZE = 5e4;
|
|
11392
|
-
var MAX_FILE_SIZE = 1e6;
|
|
11393
|
-
var MAX_FILES = 50;
|
|
11394
|
-
var MAX_PENDING_WRITES = 100;
|
|
11395
|
-
var BODY_TOO_LARGE = import_buffer2.Buffer.from("<body too large>");
|
|
11396
|
-
var BODY_MASKED = import_buffer2.Buffer.from("<masked>");
|
|
11397
|
-
var MASKED = "******";
|
|
11398
|
-
var ALLOWED_CONTENT_TYPES = [
|
|
11399
|
-
"application/json",
|
|
11400
|
-
"application/problem+json",
|
|
11401
|
-
"application/vnd.api+json",
|
|
11402
|
-
"text/plain"
|
|
11403
|
-
];
|
|
11404
|
-
var EXCLUDE_PATH_PATTERNS = [
|
|
11405
|
-
/\/_?healthz?$/i,
|
|
11406
|
-
/\/_?health[_-]?checks?$/i,
|
|
11407
|
-
/\/_?heart[_-]?beats?$/i,
|
|
11408
|
-
/\/ping$/i,
|
|
11409
|
-
/\/ready$/i,
|
|
11410
|
-
/\/live$/i
|
|
11411
|
-
];
|
|
11412
|
-
var EXCLUDE_USER_AGENT_PATTERNS = [
|
|
11413
|
-
/health[-_ ]?check/i,
|
|
11414
|
-
/microsoft-azure-application-lb/i,
|
|
11415
|
-
/googlehc/i,
|
|
11416
|
-
/kube-probe/i
|
|
11417
|
-
];
|
|
11418
|
-
var MASK_QUERY_PARAM_PATTERNS = [
|
|
11419
|
-
/auth/i,
|
|
11420
|
-
/api-?key/i,
|
|
11421
|
-
/secret/i,
|
|
11422
|
-
/token/i,
|
|
11423
|
-
/password/i,
|
|
11424
|
-
/pwd/i
|
|
11425
|
-
];
|
|
11426
|
-
var MASK_HEADER_PATTERNS = [
|
|
11427
|
-
/auth/i,
|
|
11428
|
-
/api-?key/i,
|
|
11429
|
-
/secret/i,
|
|
11430
|
-
/token/i,
|
|
11431
|
-
/cookie/i
|
|
11432
|
-
];
|
|
11433
|
-
var MASK_BODY_FIELD_PATTERNS = [
|
|
11434
|
-
/password/i,
|
|
11435
|
-
/pwd/i,
|
|
11436
|
-
/token/i,
|
|
11437
|
-
/secret/i,
|
|
11438
|
-
/auth/i,
|
|
11439
|
-
/card[-_ ]?number/i,
|
|
11440
|
-
/ccv/i,
|
|
11441
|
-
/ssn/i
|
|
11442
|
-
];
|
|
11443
|
-
var DEFAULT_CONFIG = {
|
|
11444
|
-
enabled: false,
|
|
11445
|
-
logQueryParams: true,
|
|
11446
|
-
logRequestHeaders: false,
|
|
11447
|
-
logRequestBody: false,
|
|
11448
|
-
logResponseHeaders: true,
|
|
11449
|
-
logResponseBody: false,
|
|
11450
|
-
logException: true,
|
|
11451
|
-
maskQueryParams: [],
|
|
11452
|
-
maskHeaders: [],
|
|
11453
|
-
maskBodyFields: [],
|
|
11454
|
-
excludePaths: []
|
|
11455
|
-
};
|
|
11456
|
-
var _RequestLogger = class _RequestLogger {
|
|
11457
|
-
config;
|
|
11458
|
-
enabled;
|
|
11459
|
-
suspendUntil = null;
|
|
11460
|
-
pendingWrites = [];
|
|
11461
|
-
currentFile = null;
|
|
11462
|
-
files = [];
|
|
11463
|
-
maintainIntervalId;
|
|
11464
|
-
lock = new import_async_lock.default();
|
|
11465
|
-
constructor(config) {
|
|
11466
|
-
this.config = {
|
|
11467
|
-
...DEFAULT_CONFIG,
|
|
11468
|
-
...config
|
|
11469
|
-
};
|
|
11470
|
-
this.enabled = this.config.enabled && checkWritableFs();
|
|
11471
|
-
if (this.enabled) {
|
|
11472
|
-
this.maintainIntervalId = setInterval(() => {
|
|
11473
|
-
this.maintain();
|
|
11474
|
-
}, 1e3);
|
|
11475
|
-
}
|
|
11476
|
-
}
|
|
11477
|
-
get maxBodySize() {
|
|
11478
|
-
return MAX_BODY_SIZE;
|
|
11479
|
-
}
|
|
11480
|
-
shouldExcludePath(urlPath) {
|
|
11481
|
-
const patterns = [
|
|
11482
|
-
...this.config.excludePaths,
|
|
11483
|
-
...EXCLUDE_PATH_PATTERNS
|
|
11484
|
-
];
|
|
11485
|
-
return matchPatterns(urlPath, patterns);
|
|
11486
|
-
}
|
|
11487
|
-
shouldExcludeUserAgent(userAgent) {
|
|
11488
|
-
return userAgent ? matchPatterns(userAgent, EXCLUDE_USER_AGENT_PATTERNS) : false;
|
|
11489
|
-
}
|
|
11490
|
-
shouldMaskQueryParam(name) {
|
|
11491
|
-
const patterns = [
|
|
11492
|
-
...this.config.maskQueryParams,
|
|
11493
|
-
...MASK_QUERY_PARAM_PATTERNS
|
|
11494
|
-
];
|
|
11495
|
-
return matchPatterns(name, patterns);
|
|
11496
|
-
}
|
|
11497
|
-
shouldMaskHeader(name) {
|
|
11498
|
-
const patterns = [
|
|
11499
|
-
...this.config.maskHeaders,
|
|
11500
|
-
...MASK_HEADER_PATTERNS
|
|
11501
|
-
];
|
|
11502
|
-
return matchPatterns(name, patterns);
|
|
11503
|
-
}
|
|
11504
|
-
shouldMaskBodyField(name) {
|
|
11505
|
-
const patterns = [
|
|
11506
|
-
...this.config.maskBodyFields,
|
|
11507
|
-
...MASK_BODY_FIELD_PATTERNS
|
|
11508
|
-
];
|
|
11509
|
-
return matchPatterns(name, patterns);
|
|
11510
|
-
}
|
|
11511
|
-
hasSupportedContentType(headers) {
|
|
11512
|
-
var _a3;
|
|
11513
|
-
const contentType = (_a3 = headers.find(([k]) => k.toLowerCase() === "content-type")) == null ? void 0 : _a3[1];
|
|
11514
|
-
return this.isSupportedContentType(contentType);
|
|
11515
|
-
}
|
|
11516
|
-
hasJsonContentType(headers) {
|
|
11517
|
-
var _a3;
|
|
11518
|
-
const contentType = (_a3 = headers.find(([k]) => k.toLowerCase() === "content-type")) == null ? void 0 : _a3[1];
|
|
11519
|
-
return contentType ? /\bjson\b/i.test(contentType) : null;
|
|
11520
|
-
}
|
|
11521
|
-
isSupportedContentType(contentType) {
|
|
11522
|
-
return typeof contentType === "string" && ALLOWED_CONTENT_TYPES.some((t) => contentType.startsWith(t));
|
|
11523
|
-
}
|
|
11524
|
-
maskQueryParams(search) {
|
|
11525
|
-
const params = new URLSearchParams(search);
|
|
11526
|
-
for (const [key] of params) {
|
|
11527
|
-
if (this.shouldMaskQueryParam(key)) {
|
|
11528
|
-
params.set(key, MASKED);
|
|
11529
|
-
}
|
|
11530
|
-
}
|
|
11531
|
-
return params.toString();
|
|
11532
|
-
}
|
|
11533
|
-
maskHeaders(headers) {
|
|
11534
|
-
return headers.map(([k, v]) => [
|
|
11535
|
-
k,
|
|
11536
|
-
this.shouldMaskHeader(k) ? MASKED : v
|
|
11537
|
-
]);
|
|
11538
|
-
}
|
|
11539
|
-
maskBody(data) {
|
|
11540
|
-
if (typeof data === "object" && data !== null && !Array.isArray(data)) {
|
|
11541
|
-
const result = {};
|
|
11542
|
-
for (const [key, value] of Object.entries(data)) {
|
|
11543
|
-
if (typeof value === "string" && this.shouldMaskBodyField(key)) {
|
|
11544
|
-
result[key] = MASKED;
|
|
11545
|
-
} else {
|
|
11546
|
-
result[key] = this.maskBody(value);
|
|
11547
|
-
}
|
|
11548
|
-
}
|
|
11549
|
-
return result;
|
|
11550
|
-
}
|
|
11551
|
-
if (Array.isArray(data)) {
|
|
11552
|
-
return data.map((item) => this.maskBody(item));
|
|
11553
|
-
}
|
|
11554
|
-
return data;
|
|
11555
|
-
}
|
|
11556
|
-
applyMasking(item) {
|
|
11557
|
-
if (this.config.maskRequestBodyCallback && item.request.body && item.request.body !== BODY_TOO_LARGE) {
|
|
11558
|
-
try {
|
|
11559
|
-
const maskedBody = this.config.maskRequestBodyCallback(item.request);
|
|
11560
|
-
item.request.body = maskedBody ?? BODY_MASKED;
|
|
11561
|
-
} catch {
|
|
11562
|
-
item.request.body = void 0;
|
|
11563
|
-
}
|
|
11564
|
-
}
|
|
11565
|
-
if (this.config.maskResponseBodyCallback && item.response.body && item.response.body !== BODY_TOO_LARGE) {
|
|
11566
|
-
try {
|
|
11567
|
-
const maskedBody = this.config.maskResponseBodyCallback(item.request, item.response);
|
|
11568
|
-
item.response.body = maskedBody ?? BODY_MASKED;
|
|
11569
|
-
} catch {
|
|
11570
|
-
item.response.body = void 0;
|
|
11571
|
-
}
|
|
11572
|
-
}
|
|
11573
|
-
if (item.request.body && item.request.body.length > MAX_BODY_SIZE) {
|
|
11574
|
-
item.request.body = BODY_TOO_LARGE;
|
|
11575
|
-
}
|
|
11576
|
-
if (item.response.body && item.response.body.length > MAX_BODY_SIZE) {
|
|
11577
|
-
item.response.body = BODY_TOO_LARGE;
|
|
11578
|
-
}
|
|
11579
|
-
for (const key of [
|
|
11580
|
-
"request",
|
|
11581
|
-
"response"
|
|
11582
|
-
]) {
|
|
11583
|
-
const bodyData = item[key].body;
|
|
11584
|
-
if (!bodyData || bodyData === BODY_TOO_LARGE || bodyData === BODY_MASKED) {
|
|
11585
|
-
continue;
|
|
11261
|
+
var import_crypto, MAX_MSG_LENGTH, MAX_STACKTRACE_LENGTH, _ServerErrorCounter, ServerErrorCounter;
|
|
11262
|
+
var init_serverErrorCounter = __esm({
|
|
11263
|
+
"src/common/serverErrorCounter.ts"() {
|
|
11264
|
+
"use strict";
|
|
11265
|
+
import_crypto = require("crypto");
|
|
11266
|
+
init_sentry();
|
|
11267
|
+
MAX_MSG_LENGTH = 2048;
|
|
11268
|
+
MAX_STACKTRACE_LENGTH = 65536;
|
|
11269
|
+
_ServerErrorCounter = class _ServerErrorCounter {
|
|
11270
|
+
errorCounts;
|
|
11271
|
+
errorDetails;
|
|
11272
|
+
sentryEventIds;
|
|
11273
|
+
constructor() {
|
|
11274
|
+
this.errorCounts = /* @__PURE__ */ new Map();
|
|
11275
|
+
this.errorDetails = /* @__PURE__ */ new Map();
|
|
11276
|
+
this.sentryEventIds = /* @__PURE__ */ new Map();
|
|
11277
|
+
}
|
|
11278
|
+
addServerError(serverError) {
|
|
11279
|
+
const key = this.getKey(serverError);
|
|
11280
|
+
if (!this.errorDetails.has(key)) {
|
|
11281
|
+
this.errorDetails.set(key, serverError);
|
|
11282
|
+
}
|
|
11283
|
+
this.errorCounts.set(key, (this.errorCounts.get(key) || 0) + 1);
|
|
11284
|
+
const sentryEventId = getSentryEventId();
|
|
11285
|
+
if (sentryEventId) {
|
|
11286
|
+
this.sentryEventIds.set(key, sentryEventId);
|
|
11287
|
+
}
|
|
11288
|
+
}
|
|
11289
|
+
getAndResetServerErrors() {
|
|
11290
|
+
const data = [];
|
|
11291
|
+
this.errorCounts.forEach((count, key) => {
|
|
11292
|
+
const serverError = this.errorDetails.get(key);
|
|
11293
|
+
if (serverError) {
|
|
11294
|
+
data.push({
|
|
11295
|
+
consumer: serverError.consumer || null,
|
|
11296
|
+
method: serverError.method,
|
|
11297
|
+
path: serverError.path,
|
|
11298
|
+
type: serverError.type,
|
|
11299
|
+
msg: truncateExceptionMessage(serverError.msg),
|
|
11300
|
+
traceback: truncateExceptionStackTrace(serverError.traceback),
|
|
11301
|
+
sentry_event_id: this.sentryEventIds.get(key) || null,
|
|
11302
|
+
error_count: count
|
|
11303
|
+
});
|
|
11304
|
+
}
|
|
11305
|
+
});
|
|
11306
|
+
this.errorCounts.clear();
|
|
11307
|
+
this.errorDetails.clear();
|
|
11308
|
+
return data;
|
|
11309
|
+
}
|
|
11310
|
+
getKey(serverError) {
|
|
11311
|
+
const hashInput = [
|
|
11312
|
+
serverError.consumer || "",
|
|
11313
|
+
serverError.method.toUpperCase(),
|
|
11314
|
+
serverError.path,
|
|
11315
|
+
serverError.type,
|
|
11316
|
+
serverError.msg.trim(),
|
|
11317
|
+
serverError.traceback.trim()
|
|
11318
|
+
].join("|");
|
|
11319
|
+
return (0, import_crypto.createHash)("md5").update(hashInput).digest("hex");
|
|
11586
11320
|
}
|
|
11587
|
-
const headers = item[key].headers;
|
|
11588
|
-
const hasJsonContent = this.hasJsonContentType(headers);
|
|
11589
|
-
if (hasJsonContent === null || hasJsonContent) {
|
|
11590
|
-
try {
|
|
11591
|
-
const parsedBody = JSON.parse(bodyData.toString());
|
|
11592
|
-
const maskedBody = this.maskBody(parsedBody);
|
|
11593
|
-
item[key].body = import_buffer2.Buffer.from(JSON.stringify(maskedBody));
|
|
11594
|
-
} catch {
|
|
11595
|
-
}
|
|
11596
|
-
}
|
|
11597
|
-
}
|
|
11598
|
-
item.request.headers = this.config.logRequestHeaders ? this.maskHeaders(item.request.headers) : [];
|
|
11599
|
-
item.response.headers = this.config.logResponseHeaders ? this.maskHeaders(item.response.headers) : [];
|
|
11600
|
-
const url = new URL(item.request.url);
|
|
11601
|
-
url.search = this.config.logQueryParams ? this.maskQueryParams(url.search) : "";
|
|
11602
|
-
item.request.url = url.toString();
|
|
11603
|
-
return item;
|
|
11604
|
-
}
|
|
11605
|
-
logRequest(request, response, error) {
|
|
11606
|
-
var _a3, _b, _c;
|
|
11607
|
-
if (!this.enabled || this.suspendUntil !== null) return;
|
|
11608
|
-
const url = new URL(request.url);
|
|
11609
|
-
const path = request.path ?? url.pathname;
|
|
11610
|
-
const userAgent = (_a3 = request.headers.find(([k]) => k.toLowerCase() === "user-agent")) == null ? void 0 : _a3[1];
|
|
11611
|
-
if (this.shouldExcludePath(path) || this.shouldExcludeUserAgent(userAgent) || (((_c = (_b = this.config).excludeCallback) == null ? void 0 : _c.call(_b, request, response)) ?? false)) {
|
|
11612
|
-
return;
|
|
11613
|
-
}
|
|
11614
|
-
if (!this.config.logRequestBody || !this.hasSupportedContentType(request.headers)) {
|
|
11615
|
-
request.body = void 0;
|
|
11616
|
-
}
|
|
11617
|
-
if (!this.config.logResponseBody || !this.hasSupportedContentType(response.headers)) {
|
|
11618
|
-
response.body = void 0;
|
|
11619
|
-
}
|
|
11620
|
-
if (request.size !== void 0 && request.size < 0) {
|
|
11621
|
-
request.size = void 0;
|
|
11622
|
-
}
|
|
11623
|
-
if (response.size !== void 0 && response.size < 0) {
|
|
11624
|
-
response.size = void 0;
|
|
11625
|
-
}
|
|
11626
|
-
const item = {
|
|
11627
|
-
uuid: (0, import_crypto3.randomUUID)(),
|
|
11628
|
-
request,
|
|
11629
|
-
response,
|
|
11630
|
-
exception: error && this.config.logException ? {
|
|
11631
|
-
type: error.name,
|
|
11632
|
-
message: truncateExceptionMessage(error.message),
|
|
11633
|
-
stacktrace: truncateExceptionStackTrace(error.stack || ""),
|
|
11634
|
-
sentryEventId: getSentryEventId()
|
|
11635
|
-
} : void 0
|
|
11636
11321
|
};
|
|
11637
|
-
|
|
11638
|
-
|
|
11639
|
-
|
|
11640
|
-
|
|
11322
|
+
__name(_ServerErrorCounter, "ServerErrorCounter");
|
|
11323
|
+
ServerErrorCounter = _ServerErrorCounter;
|
|
11324
|
+
__name(truncateExceptionMessage, "truncateExceptionMessage");
|
|
11325
|
+
__name(truncateExceptionStackTrace, "truncateExceptionStackTrace");
|
|
11641
11326
|
}
|
|
11642
|
-
|
|
11643
|
-
|
|
11644
|
-
|
|
11645
|
-
|
|
11646
|
-
|
|
11647
|
-
|
|
11648
|
-
|
|
11649
|
-
|
|
11650
|
-
|
|
11651
|
-
|
|
11652
|
-
|
|
11653
|
-
|
|
11654
|
-
|
|
11655
|
-
|
|
11656
|
-
|
|
11657
|
-
|
|
11658
|
-
|
|
11659
|
-
|
|
11660
|
-
|
|
11661
|
-
|
|
11662
|
-
|
|
11663
|
-
|
|
11664
|
-
|
|
11665
|
-
|
|
11666
|
-
|
|
11667
|
-
|
|
11327
|
+
});
|
|
11328
|
+
|
|
11329
|
+
// src/common/tempGzipFile.ts
|
|
11330
|
+
var import_buffer, import_crypto2, import_fs, import_os, import_path, import_zlib, _TempGzipFile, TempGzipFile;
|
|
11331
|
+
var init_tempGzipFile = __esm({
|
|
11332
|
+
"src/common/tempGzipFile.ts"() {
|
|
11333
|
+
"use strict";
|
|
11334
|
+
import_buffer = require("buffer");
|
|
11335
|
+
import_crypto2 = require("crypto");
|
|
11336
|
+
import_fs = require("fs");
|
|
11337
|
+
import_os = require("os");
|
|
11338
|
+
import_path = require("path");
|
|
11339
|
+
import_zlib = require("zlib");
|
|
11340
|
+
_TempGzipFile = class _TempGzipFile {
|
|
11341
|
+
uuid;
|
|
11342
|
+
filePath;
|
|
11343
|
+
gzip;
|
|
11344
|
+
writeStream;
|
|
11345
|
+
readyPromise;
|
|
11346
|
+
closedPromise;
|
|
11347
|
+
constructor() {
|
|
11348
|
+
this.uuid = (0, import_crypto2.randomUUID)();
|
|
11349
|
+
this.filePath = (0, import_path.join)((0, import_os.tmpdir)(), `apitally-${this.uuid}.gz`);
|
|
11350
|
+
this.writeStream = (0, import_fs.createWriteStream)(this.filePath);
|
|
11351
|
+
this.readyPromise = new Promise((resolve, reject) => {
|
|
11352
|
+
this.writeStream.once("ready", resolve);
|
|
11353
|
+
this.writeStream.once("error", reject);
|
|
11354
|
+
});
|
|
11355
|
+
this.closedPromise = new Promise((resolve, reject) => {
|
|
11356
|
+
this.writeStream.once("close", resolve);
|
|
11357
|
+
this.writeStream.once("error", reject);
|
|
11358
|
+
});
|
|
11359
|
+
this.gzip = (0, import_zlib.createGzip)();
|
|
11360
|
+
this.gzip.pipe(this.writeStream);
|
|
11361
|
+
}
|
|
11362
|
+
get size() {
|
|
11363
|
+
return this.writeStream.bytesWritten;
|
|
11364
|
+
}
|
|
11365
|
+
async writeLine(data) {
|
|
11366
|
+
await this.readyPromise;
|
|
11367
|
+
return new Promise((resolve, reject) => {
|
|
11368
|
+
this.gzip.write(import_buffer.Buffer.concat([
|
|
11369
|
+
data,
|
|
11370
|
+
import_buffer.Buffer.from("\n")
|
|
11371
|
+
]), (error) => {
|
|
11372
|
+
if (error) {
|
|
11373
|
+
reject(error);
|
|
11374
|
+
} else {
|
|
11375
|
+
resolve();
|
|
11668
11376
|
}
|
|
11669
11377
|
});
|
|
11670
|
-
|
|
11671
|
-
}
|
|
11378
|
+
});
|
|
11672
11379
|
}
|
|
11673
|
-
|
|
11674
|
-
|
|
11675
|
-
|
|
11676
|
-
|
|
11677
|
-
|
|
11678
|
-
|
|
11679
|
-
|
|
11680
|
-
|
|
11681
|
-
|
|
11682
|
-
|
|
11683
|
-
if (this.currentFile) {
|
|
11684
|
-
await this.currentFile.close();
|
|
11685
|
-
this.files.push(this.currentFile);
|
|
11686
|
-
this.currentFile = null;
|
|
11380
|
+
async getContent() {
|
|
11381
|
+
return new Promise((resolve, reject) => {
|
|
11382
|
+
(0, import_fs.readFile)(this.filePath, (error, data) => {
|
|
11383
|
+
if (error) {
|
|
11384
|
+
reject(error);
|
|
11385
|
+
} else {
|
|
11386
|
+
resolve(data);
|
|
11387
|
+
}
|
|
11388
|
+
});
|
|
11389
|
+
});
|
|
11687
11390
|
}
|
|
11688
|
-
|
|
11689
|
-
|
|
11690
|
-
|
|
11691
|
-
|
|
11692
|
-
|
|
11693
|
-
|
|
11694
|
-
|
|
11695
|
-
|
|
11696
|
-
|
|
11697
|
-
|
|
11698
|
-
|
|
11699
|
-
|
|
11700
|
-
|
|
11701
|
-
|
|
11702
|
-
|
|
11703
|
-
async clear() {
|
|
11704
|
-
this.pendingWrites = [];
|
|
11705
|
-
await this.rotateFile();
|
|
11706
|
-
this.files.forEach((file) => {
|
|
11707
|
-
file.delete();
|
|
11708
|
-
});
|
|
11709
|
-
this.files = [];
|
|
11710
|
-
}
|
|
11711
|
-
async close() {
|
|
11712
|
-
this.enabled = false;
|
|
11713
|
-
await this.clear();
|
|
11714
|
-
if (this.maintainIntervalId) {
|
|
11715
|
-
clearInterval(this.maintainIntervalId);
|
|
11716
|
-
}
|
|
11391
|
+
async close() {
|
|
11392
|
+
await new Promise((resolve) => {
|
|
11393
|
+
this.gzip.end(() => {
|
|
11394
|
+
resolve();
|
|
11395
|
+
});
|
|
11396
|
+
});
|
|
11397
|
+
await this.closedPromise;
|
|
11398
|
+
}
|
|
11399
|
+
async delete() {
|
|
11400
|
+
await this.close();
|
|
11401
|
+
(0, import_fs.unlinkSync)(this.filePath);
|
|
11402
|
+
}
|
|
11403
|
+
};
|
|
11404
|
+
__name(_TempGzipFile, "TempGzipFile");
|
|
11405
|
+
TempGzipFile = _TempGzipFile;
|
|
11717
11406
|
}
|
|
11718
|
-
};
|
|
11719
|
-
|
|
11720
|
-
|
|
11407
|
+
});
|
|
11408
|
+
|
|
11409
|
+
// src/common/requestLogger.ts
|
|
11721
11410
|
function convertHeaders(headers) {
|
|
11722
11411
|
if (headers instanceof Headers) {
|
|
11723
11412
|
return Array.from(headers.entries());
|
|
@@ -11740,7 +11429,6 @@ function convertHeaders(headers) {
|
|
|
11740
11429
|
];
|
|
11741
11430
|
});
|
|
11742
11431
|
}
|
|
11743
|
-
__name(convertHeaders, "convertHeaders");
|
|
11744
11432
|
function convertBody(body, contentType) {
|
|
11745
11433
|
if (!body || !contentType) {
|
|
11746
11434
|
return;
|
|
@@ -11760,7 +11448,6 @@ function convertBody(body, contentType) {
|
|
|
11760
11448
|
return;
|
|
11761
11449
|
}
|
|
11762
11450
|
}
|
|
11763
|
-
__name(convertBody, "convertBody");
|
|
11764
11451
|
function isValidJsonString(body) {
|
|
11765
11452
|
if (typeof body !== "string") {
|
|
11766
11453
|
return false;
|
|
@@ -11772,13 +11459,11 @@ function isValidJsonString(body) {
|
|
|
11772
11459
|
return false;
|
|
11773
11460
|
}
|
|
11774
11461
|
}
|
|
11775
|
-
__name(isValidJsonString, "isValidJsonString");
|
|
11776
11462
|
function matchPatterns(value, patterns) {
|
|
11777
11463
|
return patterns.some((pattern) => {
|
|
11778
11464
|
return pattern.test(value);
|
|
11779
11465
|
});
|
|
11780
11466
|
}
|
|
11781
|
-
__name(matchPatterns, "matchPatterns");
|
|
11782
11467
|
function skipEmptyValues(data) {
|
|
11783
11468
|
return Object.fromEntries(Object.entries(data).filter(([_, v]) => {
|
|
11784
11469
|
if (v == null || Number.isNaN(v)) return false;
|
|
@@ -11788,7 +11473,6 @@ function skipEmptyValues(data) {
|
|
|
11788
11473
|
return true;
|
|
11789
11474
|
}));
|
|
11790
11475
|
}
|
|
11791
|
-
__name(skipEmptyValues, "skipEmptyValues");
|
|
11792
11476
|
function checkWritableFs() {
|
|
11793
11477
|
try {
|
|
11794
11478
|
const testPath = (0, import_path2.join)((0, import_os2.tmpdir)(), `apitally-${(0, import_crypto3.randomUUID)()}`);
|
|
@@ -11799,333 +11483,703 @@ function checkWritableFs() {
|
|
|
11799
11483
|
return false;
|
|
11800
11484
|
}
|
|
11801
11485
|
}
|
|
11802
|
-
|
|
11803
|
-
|
|
11804
|
-
|
|
11805
|
-
|
|
11806
|
-
|
|
11807
|
-
|
|
11808
|
-
|
|
11809
|
-
|
|
11810
|
-
|
|
11811
|
-
|
|
11812
|
-
|
|
11813
|
-
|
|
11814
|
-
|
|
11815
|
-
|
|
11816
|
-
|
|
11817
|
-
|
|
11818
|
-
|
|
11819
|
-
|
|
11820
|
-
|
|
11821
|
-
|
|
11822
|
-
|
|
11823
|
-
|
|
11824
|
-
|
|
11825
|
-
|
|
11826
|
-
|
|
11827
|
-
|
|
11828
|
-
|
|
11829
|
-
|
|
11830
|
-
|
|
11831
|
-
|
|
11832
|
-
|
|
11833
|
-
|
|
11486
|
+
var import_async_lock, import_buffer2, import_crypto3, import_fs2, import_os2, import_path2, MAX_BODY_SIZE, MAX_FILE_SIZE, MAX_FILES, MAX_PENDING_WRITES, BODY_TOO_LARGE, BODY_MASKED, MASKED, ALLOWED_CONTENT_TYPES, EXCLUDE_PATH_PATTERNS, EXCLUDE_USER_AGENT_PATTERNS, MASK_QUERY_PARAM_PATTERNS, MASK_HEADER_PATTERNS, MASK_BODY_FIELD_PATTERNS, DEFAULT_CONFIG, _RequestLogger, RequestLogger;
|
|
11487
|
+
var init_requestLogger = __esm({
|
|
11488
|
+
"src/common/requestLogger.ts"() {
|
|
11489
|
+
"use strict";
|
|
11490
|
+
import_async_lock = __toESM(require("async-lock"), 1);
|
|
11491
|
+
import_buffer2 = require("buffer");
|
|
11492
|
+
import_crypto3 = require("crypto");
|
|
11493
|
+
import_fs2 = require("fs");
|
|
11494
|
+
import_os2 = require("os");
|
|
11495
|
+
import_path2 = require("path");
|
|
11496
|
+
init_sentry();
|
|
11497
|
+
init_serverErrorCounter();
|
|
11498
|
+
init_tempGzipFile();
|
|
11499
|
+
MAX_BODY_SIZE = 5e4;
|
|
11500
|
+
MAX_FILE_SIZE = 1e6;
|
|
11501
|
+
MAX_FILES = 50;
|
|
11502
|
+
MAX_PENDING_WRITES = 100;
|
|
11503
|
+
BODY_TOO_LARGE = import_buffer2.Buffer.from("<body too large>");
|
|
11504
|
+
BODY_MASKED = import_buffer2.Buffer.from("<masked>");
|
|
11505
|
+
MASKED = "******";
|
|
11506
|
+
ALLOWED_CONTENT_TYPES = [
|
|
11507
|
+
"application/json",
|
|
11508
|
+
"application/problem+json",
|
|
11509
|
+
"application/vnd.api+json",
|
|
11510
|
+
"text/plain"
|
|
11511
|
+
];
|
|
11512
|
+
EXCLUDE_PATH_PATTERNS = [
|
|
11513
|
+
/\/_?healthz?$/i,
|
|
11514
|
+
/\/_?health[_-]?checks?$/i,
|
|
11515
|
+
/\/_?heart[_-]?beats?$/i,
|
|
11516
|
+
/\/ping$/i,
|
|
11517
|
+
/\/ready$/i,
|
|
11518
|
+
/\/live$/i
|
|
11519
|
+
];
|
|
11520
|
+
EXCLUDE_USER_AGENT_PATTERNS = [
|
|
11521
|
+
/health[-_ ]?check/i,
|
|
11522
|
+
/microsoft-azure-application-lb/i,
|
|
11523
|
+
/googlehc/i,
|
|
11524
|
+
/kube-probe/i
|
|
11525
|
+
];
|
|
11526
|
+
MASK_QUERY_PARAM_PATTERNS = [
|
|
11527
|
+
/auth/i,
|
|
11528
|
+
/api-?key/i,
|
|
11529
|
+
/secret/i,
|
|
11530
|
+
/token/i,
|
|
11531
|
+
/password/i,
|
|
11532
|
+
/pwd/i
|
|
11533
|
+
];
|
|
11534
|
+
MASK_HEADER_PATTERNS = [
|
|
11535
|
+
/auth/i,
|
|
11536
|
+
/api-?key/i,
|
|
11537
|
+
/secret/i,
|
|
11538
|
+
/token/i,
|
|
11539
|
+
/cookie/i
|
|
11540
|
+
];
|
|
11541
|
+
MASK_BODY_FIELD_PATTERNS = [
|
|
11542
|
+
/password/i,
|
|
11543
|
+
/pwd/i,
|
|
11544
|
+
/token/i,
|
|
11545
|
+
/secret/i,
|
|
11546
|
+
/auth/i,
|
|
11547
|
+
/card[-_ ]?number/i,
|
|
11548
|
+
/ccv/i,
|
|
11549
|
+
/ssn/i
|
|
11550
|
+
];
|
|
11551
|
+
DEFAULT_CONFIG = {
|
|
11552
|
+
enabled: false,
|
|
11553
|
+
logQueryParams: true,
|
|
11554
|
+
logRequestHeaders: false,
|
|
11555
|
+
logRequestBody: false,
|
|
11556
|
+
logResponseHeaders: true,
|
|
11557
|
+
logResponseBody: false,
|
|
11558
|
+
logException: true,
|
|
11559
|
+
maskQueryParams: [],
|
|
11560
|
+
maskHeaders: [],
|
|
11561
|
+
maskBodyFields: [],
|
|
11562
|
+
excludePaths: []
|
|
11563
|
+
};
|
|
11564
|
+
_RequestLogger = class _RequestLogger {
|
|
11565
|
+
config;
|
|
11566
|
+
enabled;
|
|
11567
|
+
suspendUntil = null;
|
|
11568
|
+
pendingWrites = [];
|
|
11569
|
+
currentFile = null;
|
|
11570
|
+
files = [];
|
|
11571
|
+
maintainIntervalId;
|
|
11572
|
+
lock = new import_async_lock.default();
|
|
11573
|
+
constructor(config) {
|
|
11574
|
+
this.config = {
|
|
11575
|
+
...DEFAULT_CONFIG,
|
|
11576
|
+
...config
|
|
11577
|
+
};
|
|
11578
|
+
this.enabled = this.config.enabled && checkWritableFs();
|
|
11579
|
+
if (this.enabled) {
|
|
11580
|
+
this.maintainIntervalId = setInterval(() => {
|
|
11581
|
+
this.maintain();
|
|
11582
|
+
}, 1e3);
|
|
11583
|
+
}
|
|
11834
11584
|
}
|
|
11835
|
-
|
|
11836
|
-
|
|
11837
|
-
this.errorDetails.clear();
|
|
11838
|
-
return data;
|
|
11839
|
-
}
|
|
11840
|
-
getKey(validationError) {
|
|
11841
|
-
const hashInput = [
|
|
11842
|
-
validationError.consumer || "",
|
|
11843
|
-
validationError.method.toUpperCase(),
|
|
11844
|
-
validationError.path,
|
|
11845
|
-
validationError.loc,
|
|
11846
|
-
validationError.msg.trim(),
|
|
11847
|
-
validationError.type
|
|
11848
|
-
].join("|");
|
|
11849
|
-
return (0, import_crypto4.createHash)("md5").update(hashInput).digest("hex");
|
|
11850
|
-
}
|
|
11851
|
-
};
|
|
11852
|
-
__name(_ValidationErrorCounter, "ValidationErrorCounter");
|
|
11853
|
-
var ValidationErrorCounter = _ValidationErrorCounter;
|
|
11854
|
-
|
|
11855
|
-
// src/common/client.ts
|
|
11856
|
-
var SYNC_INTERVAL = 6e4;
|
|
11857
|
-
var INITIAL_SYNC_INTERVAL = 1e4;
|
|
11858
|
-
var INITIAL_SYNC_INTERVAL_DURATION = 36e5;
|
|
11859
|
-
var MAX_QUEUE_TIME = 36e5;
|
|
11860
|
-
var _a;
|
|
11861
|
-
var HTTPError = (_a = class extends Error {
|
|
11862
|
-
response;
|
|
11863
|
-
constructor(response) {
|
|
11864
|
-
const reason = response.status ? `status code ${response.status}` : "an unknown error";
|
|
11865
|
-
super(`Request failed with ${reason}`);
|
|
11866
|
-
this.response = response;
|
|
11867
|
-
}
|
|
11868
|
-
}, __name(_a, "HTTPError"), _a);
|
|
11869
|
-
var _ApitallyClient = class _ApitallyClient {
|
|
11870
|
-
clientId;
|
|
11871
|
-
env;
|
|
11872
|
-
instanceUuid;
|
|
11873
|
-
syncDataQueue;
|
|
11874
|
-
syncIntervalId;
|
|
11875
|
-
startupData;
|
|
11876
|
-
startupDataSent = false;
|
|
11877
|
-
enabled = true;
|
|
11878
|
-
requestCounter;
|
|
11879
|
-
requestLogger;
|
|
11880
|
-
validationErrorCounter;
|
|
11881
|
-
serverErrorCounter;
|
|
11882
|
-
consumerRegistry;
|
|
11883
|
-
logger;
|
|
11884
|
-
constructor({ clientId, env = "dev", requestLogging, requestLoggingConfig, logger }) {
|
|
11885
|
-
if (_ApitallyClient.instance) {
|
|
11886
|
-
throw new Error("Apitally client is already initialized");
|
|
11887
|
-
}
|
|
11888
|
-
if (!isValidClientId(clientId)) {
|
|
11889
|
-
throw new Error(`Invalid Apitally client ID '${clientId}' (expecting hexadecimal UUID format)`);
|
|
11890
|
-
}
|
|
11891
|
-
if (!isValidEnv(env)) {
|
|
11892
|
-
throw new Error(`Invalid env '${env}' (expecting 1-32 alphanumeric lowercase characters and hyphens only)`);
|
|
11893
|
-
}
|
|
11894
|
-
if (requestLoggingConfig && !requestLogging) {
|
|
11895
|
-
console.warn("requestLoggingConfig is deprecated, use requestLogging instead.");
|
|
11896
|
-
}
|
|
11897
|
-
_ApitallyClient.instance = this;
|
|
11898
|
-
this.clientId = clientId;
|
|
11899
|
-
this.env = env;
|
|
11900
|
-
this.instanceUuid = (0, import_crypto5.randomUUID)();
|
|
11901
|
-
this.syncDataQueue = [];
|
|
11902
|
-
this.requestCounter = new RequestCounter();
|
|
11903
|
-
this.requestLogger = new RequestLogger(requestLogging ?? requestLoggingConfig);
|
|
11904
|
-
this.validationErrorCounter = new ValidationErrorCounter();
|
|
11905
|
-
this.serverErrorCounter = new ServerErrorCounter();
|
|
11906
|
-
this.consumerRegistry = new ConsumerRegistry();
|
|
11907
|
-
this.logger = logger ?? getLogger();
|
|
11908
|
-
this.startSync();
|
|
11909
|
-
this.handleShutdown = this.handleShutdown.bind(this);
|
|
11910
|
-
}
|
|
11911
|
-
static getInstance() {
|
|
11912
|
-
if (!_ApitallyClient.instance) {
|
|
11913
|
-
throw new Error("Apitally client is not initialized");
|
|
11914
|
-
}
|
|
11915
|
-
return _ApitallyClient.instance;
|
|
11916
|
-
}
|
|
11917
|
-
isEnabled() {
|
|
11918
|
-
return this.enabled;
|
|
11919
|
-
}
|
|
11920
|
-
static async shutdown() {
|
|
11921
|
-
if (_ApitallyClient.instance) {
|
|
11922
|
-
await _ApitallyClient.instance.handleShutdown();
|
|
11923
|
-
}
|
|
11924
|
-
}
|
|
11925
|
-
async handleShutdown() {
|
|
11926
|
-
this.enabled = false;
|
|
11927
|
-
this.stopSync();
|
|
11928
|
-
await this.sendSyncData();
|
|
11929
|
-
await this.sendLogData();
|
|
11930
|
-
await this.requestLogger.close();
|
|
11931
|
-
_ApitallyClient.instance = void 0;
|
|
11932
|
-
}
|
|
11933
|
-
getHubUrlPrefix() {
|
|
11934
|
-
const baseURL = process.env.APITALLY_HUB_BASE_URL || "https://hub.apitally.io";
|
|
11935
|
-
const version = "v2";
|
|
11936
|
-
return `${baseURL}/${version}/${this.clientId}/${this.env}/`;
|
|
11937
|
-
}
|
|
11938
|
-
async sendData(url, payload) {
|
|
11939
|
-
const fetchWithRetry = (0, import_fetch_retry.default)(fetch, {
|
|
11940
|
-
retries: 3,
|
|
11941
|
-
retryDelay: 1e3,
|
|
11942
|
-
retryOn: [
|
|
11943
|
-
408,
|
|
11944
|
-
429,
|
|
11945
|
-
500,
|
|
11946
|
-
502,
|
|
11947
|
-
503,
|
|
11948
|
-
504
|
|
11949
|
-
]
|
|
11950
|
-
});
|
|
11951
|
-
const response = await fetchWithRetry(this.getHubUrlPrefix() + url, {
|
|
11952
|
-
method: "POST",
|
|
11953
|
-
body: JSON.stringify(payload),
|
|
11954
|
-
headers: {
|
|
11955
|
-
"Content-Type": "application/json"
|
|
11585
|
+
get maxBodySize() {
|
|
11586
|
+
return MAX_BODY_SIZE;
|
|
11956
11587
|
}
|
|
11957
|
-
|
|
11958
|
-
|
|
11959
|
-
|
|
11960
|
-
|
|
11961
|
-
|
|
11962
|
-
|
|
11963
|
-
this.sync();
|
|
11964
|
-
this.syncIntervalId = setInterval(() => {
|
|
11965
|
-
this.sync();
|
|
11966
|
-
}, INITIAL_SYNC_INTERVAL);
|
|
11967
|
-
setTimeout(() => {
|
|
11968
|
-
clearInterval(this.syncIntervalId);
|
|
11969
|
-
this.syncIntervalId = setInterval(() => {
|
|
11970
|
-
this.sync();
|
|
11971
|
-
}, SYNC_INTERVAL);
|
|
11972
|
-
}, INITIAL_SYNC_INTERVAL_DURATION);
|
|
11973
|
-
}
|
|
11974
|
-
async sync() {
|
|
11975
|
-
try {
|
|
11976
|
-
const promises = [
|
|
11977
|
-
this.sendSyncData(),
|
|
11978
|
-
this.sendLogData()
|
|
11979
|
-
];
|
|
11980
|
-
if (!this.startupDataSent) {
|
|
11981
|
-
promises.push(this.sendStartupData());
|
|
11588
|
+
shouldExcludePath(urlPath) {
|
|
11589
|
+
const patterns = [
|
|
11590
|
+
...this.config.excludePaths,
|
|
11591
|
+
...EXCLUDE_PATH_PATTERNS
|
|
11592
|
+
];
|
|
11593
|
+
return matchPatterns(urlPath, patterns);
|
|
11982
11594
|
}
|
|
11983
|
-
|
|
11984
|
-
|
|
11985
|
-
this.logger.error("Error while syncing with Apitally Hub", {
|
|
11986
|
-
error
|
|
11987
|
-
});
|
|
11988
|
-
}
|
|
11989
|
-
}
|
|
11990
|
-
stopSync() {
|
|
11991
|
-
if (this.syncIntervalId) {
|
|
11992
|
-
clearInterval(this.syncIntervalId);
|
|
11993
|
-
this.syncIntervalId = void 0;
|
|
11994
|
-
}
|
|
11995
|
-
}
|
|
11996
|
-
setStartupData(data) {
|
|
11997
|
-
this.startupData = data;
|
|
11998
|
-
this.startupDataSent = false;
|
|
11999
|
-
this.sendStartupData();
|
|
12000
|
-
}
|
|
12001
|
-
async sendStartupData() {
|
|
12002
|
-
if (this.startupData) {
|
|
12003
|
-
this.logger.debug("Sending startup data to Apitally Hub");
|
|
12004
|
-
const payload = {
|
|
12005
|
-
instance_uuid: this.instanceUuid,
|
|
12006
|
-
message_uuid: (0, import_crypto5.randomUUID)(),
|
|
12007
|
-
...this.startupData
|
|
12008
|
-
};
|
|
12009
|
-
try {
|
|
12010
|
-
await this.sendData("startup", payload);
|
|
12011
|
-
this.startupDataSent = true;
|
|
12012
|
-
} catch (error) {
|
|
12013
|
-
const handled = this.handleHubError(error);
|
|
12014
|
-
if (!handled) {
|
|
12015
|
-
this.logger.error(error.message);
|
|
12016
|
-
this.logger.debug("Error while sending startup data to Apitally Hub (will retry)", {
|
|
12017
|
-
error
|
|
12018
|
-
});
|
|
12019
|
-
}
|
|
11595
|
+
shouldExcludeUserAgent(userAgent) {
|
|
11596
|
+
return userAgent ? matchPatterns(userAgent, EXCLUDE_USER_AGENT_PATTERNS) : false;
|
|
12020
11597
|
}
|
|
12021
|
-
|
|
12022
|
-
|
|
12023
|
-
|
|
12024
|
-
|
|
12025
|
-
|
|
12026
|
-
|
|
12027
|
-
|
|
12028
|
-
|
|
12029
|
-
|
|
12030
|
-
|
|
12031
|
-
|
|
12032
|
-
|
|
12033
|
-
|
|
12034
|
-
|
|
12035
|
-
|
|
12036
|
-
|
|
12037
|
-
|
|
12038
|
-
|
|
12039
|
-
|
|
12040
|
-
|
|
12041
|
-
|
|
12042
|
-
|
|
12043
|
-
|
|
12044
|
-
|
|
12045
|
-
|
|
12046
|
-
|
|
12047
|
-
|
|
12048
|
-
|
|
12049
|
-
|
|
12050
|
-
|
|
12051
|
-
|
|
12052
|
-
|
|
12053
|
-
|
|
12054
|
-
|
|
11598
|
+
shouldMaskQueryParam(name) {
|
|
11599
|
+
const patterns = [
|
|
11600
|
+
...this.config.maskQueryParams,
|
|
11601
|
+
...MASK_QUERY_PARAM_PATTERNS
|
|
11602
|
+
];
|
|
11603
|
+
return matchPatterns(name, patterns);
|
|
11604
|
+
}
|
|
11605
|
+
shouldMaskHeader(name) {
|
|
11606
|
+
const patterns = [
|
|
11607
|
+
...this.config.maskHeaders,
|
|
11608
|
+
...MASK_HEADER_PATTERNS
|
|
11609
|
+
];
|
|
11610
|
+
return matchPatterns(name, patterns);
|
|
11611
|
+
}
|
|
11612
|
+
shouldMaskBodyField(name) {
|
|
11613
|
+
const patterns = [
|
|
11614
|
+
...this.config.maskBodyFields,
|
|
11615
|
+
...MASK_BODY_FIELD_PATTERNS
|
|
11616
|
+
];
|
|
11617
|
+
return matchPatterns(name, patterns);
|
|
11618
|
+
}
|
|
11619
|
+
hasSupportedContentType(headers) {
|
|
11620
|
+
var _a3;
|
|
11621
|
+
const contentType = (_a3 = headers.find(([k]) => k.toLowerCase() === "content-type")) == null ? void 0 : _a3[1];
|
|
11622
|
+
return this.isSupportedContentType(contentType);
|
|
11623
|
+
}
|
|
11624
|
+
hasJsonContentType(headers) {
|
|
11625
|
+
var _a3;
|
|
11626
|
+
const contentType = (_a3 = headers.find(([k]) => k.toLowerCase() === "content-type")) == null ? void 0 : _a3[1];
|
|
11627
|
+
return contentType ? /\bjson\b/i.test(contentType) : null;
|
|
11628
|
+
}
|
|
11629
|
+
isSupportedContentType(contentType) {
|
|
11630
|
+
return typeof contentType === "string" && ALLOWED_CONTENT_TYPES.some((t) => contentType.startsWith(t));
|
|
11631
|
+
}
|
|
11632
|
+
maskQueryParams(search) {
|
|
11633
|
+
const params = new URLSearchParams(search);
|
|
11634
|
+
for (const [key] of params) {
|
|
11635
|
+
if (this.shouldMaskQueryParam(key)) {
|
|
11636
|
+
params.set(key, MASKED);
|
|
12055
11637
|
}
|
|
12056
11638
|
}
|
|
11639
|
+
return params.toString();
|
|
12057
11640
|
}
|
|
12058
|
-
|
|
12059
|
-
|
|
12060
|
-
|
|
12061
|
-
|
|
12062
|
-
|
|
12063
|
-
const fetchWithRetry = (0, import_fetch_retry.default)(fetch, {
|
|
12064
|
-
retries: 3,
|
|
12065
|
-
retryDelay: 1e3,
|
|
12066
|
-
retryOn: [
|
|
12067
|
-
408,
|
|
12068
|
-
429,
|
|
12069
|
-
500,
|
|
12070
|
-
502,
|
|
12071
|
-
503,
|
|
12072
|
-
504
|
|
12073
|
-
]
|
|
12074
|
-
});
|
|
12075
|
-
let i = 0;
|
|
12076
|
-
let logFile;
|
|
12077
|
-
while (logFile = this.requestLogger.getFile()) {
|
|
12078
|
-
if (i > 0) {
|
|
12079
|
-
await this.randomDelay();
|
|
11641
|
+
maskHeaders(headers) {
|
|
11642
|
+
return headers.map(([k, v]) => [
|
|
11643
|
+
k,
|
|
11644
|
+
this.shouldMaskHeader(k) ? MASKED : v
|
|
11645
|
+
]);
|
|
12080
11646
|
}
|
|
12081
|
-
|
|
12082
|
-
|
|
12083
|
-
|
|
12084
|
-
|
|
12085
|
-
|
|
12086
|
-
|
|
12087
|
-
|
|
12088
|
-
|
|
12089
|
-
|
|
12090
|
-
this.requestLogger.clear();
|
|
12091
|
-
return;
|
|
11647
|
+
maskBody(data) {
|
|
11648
|
+
if (typeof data === "object" && data !== null && !Array.isArray(data)) {
|
|
11649
|
+
const result = {};
|
|
11650
|
+
for (const [key, value] of Object.entries(data)) {
|
|
11651
|
+
if (typeof value === "string" && this.shouldMaskBodyField(key)) {
|
|
11652
|
+
result[key] = MASKED;
|
|
11653
|
+
} else {
|
|
11654
|
+
result[key] = this.maskBody(value);
|
|
11655
|
+
}
|
|
12092
11656
|
}
|
|
11657
|
+
return result;
|
|
12093
11658
|
}
|
|
12094
|
-
if (
|
|
12095
|
-
|
|
11659
|
+
if (Array.isArray(data)) {
|
|
11660
|
+
return data.map((item) => this.maskBody(item));
|
|
12096
11661
|
}
|
|
12097
|
-
|
|
12098
|
-
} catch (error) {
|
|
12099
|
-
this.requestLogger.retryFileLater(logFile);
|
|
12100
|
-
break;
|
|
11662
|
+
return data;
|
|
12101
11663
|
}
|
|
12102
|
-
|
|
12103
|
-
|
|
12104
|
-
|
|
11664
|
+
applyMasking(item) {
|
|
11665
|
+
if (this.config.maskRequestBodyCallback && item.request.body && item.request.body !== BODY_TOO_LARGE) {
|
|
11666
|
+
try {
|
|
11667
|
+
const maskedBody = this.config.maskRequestBodyCallback(item.request);
|
|
11668
|
+
item.request.body = maskedBody ?? BODY_MASKED;
|
|
11669
|
+
} catch {
|
|
11670
|
+
item.request.body = void 0;
|
|
11671
|
+
}
|
|
11672
|
+
}
|
|
11673
|
+
if (this.config.maskResponseBodyCallback && item.response.body && item.response.body !== BODY_TOO_LARGE) {
|
|
11674
|
+
try {
|
|
11675
|
+
const maskedBody = this.config.maskResponseBodyCallback(item.request, item.response);
|
|
11676
|
+
item.response.body = maskedBody ?? BODY_MASKED;
|
|
11677
|
+
} catch {
|
|
11678
|
+
item.response.body = void 0;
|
|
11679
|
+
}
|
|
11680
|
+
}
|
|
11681
|
+
if (item.request.body && item.request.body.length > MAX_BODY_SIZE) {
|
|
11682
|
+
item.request.body = BODY_TOO_LARGE;
|
|
11683
|
+
}
|
|
11684
|
+
if (item.response.body && item.response.body.length > MAX_BODY_SIZE) {
|
|
11685
|
+
item.response.body = BODY_TOO_LARGE;
|
|
11686
|
+
}
|
|
11687
|
+
for (const key of [
|
|
11688
|
+
"request",
|
|
11689
|
+
"response"
|
|
11690
|
+
]) {
|
|
11691
|
+
const bodyData = item[key].body;
|
|
11692
|
+
if (!bodyData || bodyData === BODY_TOO_LARGE || bodyData === BODY_MASKED) {
|
|
11693
|
+
continue;
|
|
11694
|
+
}
|
|
11695
|
+
const headers = item[key].headers;
|
|
11696
|
+
const hasJsonContent = this.hasJsonContentType(headers);
|
|
11697
|
+
if (hasJsonContent === null || hasJsonContent) {
|
|
11698
|
+
try {
|
|
11699
|
+
const parsedBody = JSON.parse(bodyData.toString());
|
|
11700
|
+
const maskedBody = this.maskBody(parsedBody);
|
|
11701
|
+
item[key].body = import_buffer2.Buffer.from(JSON.stringify(maskedBody));
|
|
11702
|
+
} catch {
|
|
11703
|
+
}
|
|
11704
|
+
}
|
|
11705
|
+
}
|
|
11706
|
+
item.request.headers = this.config.logRequestHeaders ? this.maskHeaders(item.request.headers) : [];
|
|
11707
|
+
item.response.headers = this.config.logResponseHeaders ? this.maskHeaders(item.response.headers) : [];
|
|
11708
|
+
const url = new URL(item.request.url);
|
|
11709
|
+
url.search = this.config.logQueryParams ? this.maskQueryParams(url.search) : "";
|
|
11710
|
+
item.request.url = url.toString();
|
|
11711
|
+
return item;
|
|
11712
|
+
}
|
|
11713
|
+
logRequest(request, response, error) {
|
|
11714
|
+
var _a3, _b, _c;
|
|
11715
|
+
if (!this.enabled || this.suspendUntil !== null) return;
|
|
11716
|
+
const url = new URL(request.url);
|
|
11717
|
+
const path = request.path ?? url.pathname;
|
|
11718
|
+
const userAgent = (_a3 = request.headers.find(([k]) => k.toLowerCase() === "user-agent")) == null ? void 0 : _a3[1];
|
|
11719
|
+
if (this.shouldExcludePath(path) || this.shouldExcludeUserAgent(userAgent) || (((_c = (_b = this.config).excludeCallback) == null ? void 0 : _c.call(_b, request, response)) ?? false)) {
|
|
11720
|
+
return;
|
|
11721
|
+
}
|
|
11722
|
+
if (!this.config.logRequestBody || !this.hasSupportedContentType(request.headers)) {
|
|
11723
|
+
request.body = void 0;
|
|
11724
|
+
}
|
|
11725
|
+
if (!this.config.logResponseBody || !this.hasSupportedContentType(response.headers)) {
|
|
11726
|
+
response.body = void 0;
|
|
11727
|
+
}
|
|
11728
|
+
if (request.size !== void 0 && request.size < 0) {
|
|
11729
|
+
request.size = void 0;
|
|
11730
|
+
}
|
|
11731
|
+
if (response.size !== void 0 && response.size < 0) {
|
|
11732
|
+
response.size = void 0;
|
|
11733
|
+
}
|
|
11734
|
+
const item = {
|
|
11735
|
+
uuid: (0, import_crypto3.randomUUID)(),
|
|
11736
|
+
request,
|
|
11737
|
+
response,
|
|
11738
|
+
exception: error && this.config.logException ? {
|
|
11739
|
+
type: error.name,
|
|
11740
|
+
message: truncateExceptionMessage(error.message),
|
|
11741
|
+
stacktrace: truncateExceptionStackTrace(error.stack || ""),
|
|
11742
|
+
sentryEventId: getSentryEventId()
|
|
11743
|
+
} : void 0
|
|
11744
|
+
};
|
|
11745
|
+
this.pendingWrites.push(item);
|
|
11746
|
+
if (this.pendingWrites.length > MAX_PENDING_WRITES) {
|
|
11747
|
+
this.pendingWrites.shift();
|
|
11748
|
+
}
|
|
11749
|
+
}
|
|
11750
|
+
async writeToFile() {
|
|
11751
|
+
if (!this.enabled || this.pendingWrites.length === 0) {
|
|
11752
|
+
return;
|
|
11753
|
+
}
|
|
11754
|
+
return this.lock.acquire("file", async () => {
|
|
11755
|
+
if (!this.currentFile) {
|
|
11756
|
+
this.currentFile = new TempGzipFile();
|
|
11757
|
+
}
|
|
11758
|
+
while (this.pendingWrites.length > 0) {
|
|
11759
|
+
let item = this.pendingWrites.shift();
|
|
11760
|
+
if (item) {
|
|
11761
|
+
item = this.applyMasking(item);
|
|
11762
|
+
const finalItem = {
|
|
11763
|
+
uuid: item.uuid,
|
|
11764
|
+
request: skipEmptyValues(item.request),
|
|
11765
|
+
response: skipEmptyValues(item.response),
|
|
11766
|
+
exception: item.exception
|
|
11767
|
+
};
|
|
11768
|
+
[
|
|
11769
|
+
finalItem.request.body,
|
|
11770
|
+
finalItem.response.body
|
|
11771
|
+
].forEach((body) => {
|
|
11772
|
+
if (body) {
|
|
11773
|
+
body.toJSON = function() {
|
|
11774
|
+
return this.toString("base64");
|
|
11775
|
+
};
|
|
11776
|
+
}
|
|
11777
|
+
});
|
|
11778
|
+
await this.currentFile.writeLine(import_buffer2.Buffer.from(JSON.stringify(finalItem)));
|
|
11779
|
+
}
|
|
11780
|
+
}
|
|
11781
|
+
});
|
|
11782
|
+
}
|
|
11783
|
+
getFile() {
|
|
11784
|
+
return this.files.shift();
|
|
11785
|
+
}
|
|
11786
|
+
retryFileLater(file) {
|
|
11787
|
+
this.files.unshift(file);
|
|
11788
|
+
}
|
|
11789
|
+
async rotateFile() {
|
|
11790
|
+
return this.lock.acquire("file", async () => {
|
|
11791
|
+
if (this.currentFile) {
|
|
11792
|
+
await this.currentFile.close();
|
|
11793
|
+
this.files.push(this.currentFile);
|
|
11794
|
+
this.currentFile = null;
|
|
11795
|
+
}
|
|
11796
|
+
});
|
|
11797
|
+
}
|
|
11798
|
+
async maintain() {
|
|
11799
|
+
await this.writeToFile();
|
|
11800
|
+
if (this.currentFile && this.currentFile.size > MAX_FILE_SIZE) {
|
|
11801
|
+
await this.rotateFile();
|
|
11802
|
+
}
|
|
11803
|
+
while (this.files.length > MAX_FILES) {
|
|
11804
|
+
const file = this.files.shift();
|
|
11805
|
+
file == null ? void 0 : file.delete();
|
|
11806
|
+
}
|
|
11807
|
+
if (this.suspendUntil !== null && this.suspendUntil < Date.now()) {
|
|
11808
|
+
this.suspendUntil = null;
|
|
11809
|
+
}
|
|
11810
|
+
}
|
|
11811
|
+
async clear() {
|
|
11812
|
+
this.pendingWrites = [];
|
|
11813
|
+
await this.rotateFile();
|
|
11814
|
+
this.files.forEach((file) => {
|
|
11815
|
+
file.delete();
|
|
11816
|
+
});
|
|
11817
|
+
this.files = [];
|
|
11818
|
+
}
|
|
11819
|
+
async close() {
|
|
11820
|
+
this.enabled = false;
|
|
11821
|
+
await this.clear();
|
|
11822
|
+
if (this.maintainIntervalId) {
|
|
11823
|
+
clearInterval(this.maintainIntervalId);
|
|
11824
|
+
}
|
|
11825
|
+
}
|
|
11826
|
+
};
|
|
11827
|
+
__name(_RequestLogger, "RequestLogger");
|
|
11828
|
+
RequestLogger = _RequestLogger;
|
|
11829
|
+
__name(convertHeaders, "convertHeaders");
|
|
11830
|
+
__name(convertBody, "convertBody");
|
|
11831
|
+
__name(isValidJsonString, "isValidJsonString");
|
|
11832
|
+
__name(matchPatterns, "matchPatterns");
|
|
11833
|
+
__name(skipEmptyValues, "skipEmptyValues");
|
|
11834
|
+
__name(checkWritableFs, "checkWritableFs");
|
|
11835
|
+
}
|
|
11836
|
+
});
|
|
11837
|
+
|
|
11838
|
+
// src/common/validationErrorCounter.ts
|
|
11839
|
+
var import_crypto4, _ValidationErrorCounter, ValidationErrorCounter;
|
|
11840
|
+
var init_validationErrorCounter = __esm({
|
|
11841
|
+
"src/common/validationErrorCounter.ts"() {
|
|
11842
|
+
"use strict";
|
|
11843
|
+
import_crypto4 = require("crypto");
|
|
11844
|
+
_ValidationErrorCounter = class _ValidationErrorCounter {
|
|
11845
|
+
errorCounts;
|
|
11846
|
+
errorDetails;
|
|
11847
|
+
constructor() {
|
|
11848
|
+
this.errorCounts = /* @__PURE__ */ new Map();
|
|
11849
|
+
this.errorDetails = /* @__PURE__ */ new Map();
|
|
11850
|
+
}
|
|
11851
|
+
addValidationError(validationError) {
|
|
11852
|
+
const key = this.getKey(validationError);
|
|
11853
|
+
if (!this.errorDetails.has(key)) {
|
|
11854
|
+
this.errorDetails.set(key, validationError);
|
|
11855
|
+
}
|
|
11856
|
+
this.errorCounts.set(key, (this.errorCounts.get(key) || 0) + 1);
|
|
11857
|
+
}
|
|
11858
|
+
getAndResetValidationErrors() {
|
|
11859
|
+
const data = [];
|
|
11860
|
+
this.errorCounts.forEach((count, key) => {
|
|
11861
|
+
const validationError = this.errorDetails.get(key);
|
|
11862
|
+
if (validationError) {
|
|
11863
|
+
data.push({
|
|
11864
|
+
consumer: validationError.consumer || null,
|
|
11865
|
+
method: validationError.method,
|
|
11866
|
+
path: validationError.path,
|
|
11867
|
+
loc: validationError.loc.split("."),
|
|
11868
|
+
msg: validationError.msg,
|
|
11869
|
+
type: validationError.type,
|
|
11870
|
+
error_count: count
|
|
11871
|
+
});
|
|
11872
|
+
}
|
|
11873
|
+
});
|
|
11874
|
+
this.errorCounts.clear();
|
|
11875
|
+
this.errorDetails.clear();
|
|
11876
|
+
return data;
|
|
11877
|
+
}
|
|
11878
|
+
getKey(validationError) {
|
|
11879
|
+
const hashInput = [
|
|
11880
|
+
validationError.consumer || "",
|
|
11881
|
+
validationError.method.toUpperCase(),
|
|
11882
|
+
validationError.path,
|
|
11883
|
+
validationError.loc,
|
|
11884
|
+
validationError.msg.trim(),
|
|
11885
|
+
validationError.type
|
|
11886
|
+
].join("|");
|
|
11887
|
+
return (0, import_crypto4.createHash)("md5").update(hashInput).digest("hex");
|
|
11888
|
+
}
|
|
11889
|
+
};
|
|
11890
|
+
__name(_ValidationErrorCounter, "ValidationErrorCounter");
|
|
11891
|
+
ValidationErrorCounter = _ValidationErrorCounter;
|
|
12105
11892
|
}
|
|
12106
|
-
|
|
12107
|
-
|
|
12108
|
-
|
|
12109
|
-
|
|
11893
|
+
});
|
|
11894
|
+
|
|
11895
|
+
// src/common/client.ts
|
|
11896
|
+
var import_crypto5, import_fetch_retry, SYNC_INTERVAL, INITIAL_SYNC_INTERVAL, INITIAL_SYNC_INTERVAL_DURATION, MAX_QUEUE_TIME, _a, HTTPError, _ApitallyClient, ApitallyClient;
|
|
11897
|
+
var init_client = __esm({
|
|
11898
|
+
"src/common/client.ts"() {
|
|
11899
|
+
"use strict";
|
|
11900
|
+
import_crypto5 = require("crypto");
|
|
11901
|
+
import_fetch_retry = __toESM(require("fetch-retry"), 1);
|
|
11902
|
+
init_consumerRegistry();
|
|
11903
|
+
init_logging();
|
|
11904
|
+
init_paramValidation();
|
|
11905
|
+
init_requestCounter();
|
|
11906
|
+
init_requestLogger();
|
|
11907
|
+
init_serverErrorCounter();
|
|
11908
|
+
init_validationErrorCounter();
|
|
11909
|
+
SYNC_INTERVAL = 6e4;
|
|
11910
|
+
INITIAL_SYNC_INTERVAL = 1e4;
|
|
11911
|
+
INITIAL_SYNC_INTERVAL_DURATION = 36e5;
|
|
11912
|
+
MAX_QUEUE_TIME = 36e5;
|
|
11913
|
+
HTTPError = (_a = class extends Error {
|
|
11914
|
+
response;
|
|
11915
|
+
constructor(response) {
|
|
11916
|
+
const reason = response.status ? `status code ${response.status}` : "an unknown error";
|
|
11917
|
+
super(`Request failed with ${reason}`);
|
|
11918
|
+
this.response = response;
|
|
11919
|
+
}
|
|
11920
|
+
}, __name(_a, "HTTPError"), _a);
|
|
11921
|
+
_ApitallyClient = class _ApitallyClient {
|
|
11922
|
+
clientId;
|
|
11923
|
+
env;
|
|
11924
|
+
instanceUuid;
|
|
11925
|
+
syncDataQueue;
|
|
11926
|
+
syncIntervalId;
|
|
11927
|
+
startupData;
|
|
11928
|
+
startupDataSent = false;
|
|
11929
|
+
enabled = true;
|
|
11930
|
+
requestCounter;
|
|
11931
|
+
requestLogger;
|
|
11932
|
+
validationErrorCounter;
|
|
11933
|
+
serverErrorCounter;
|
|
11934
|
+
consumerRegistry;
|
|
11935
|
+
logger;
|
|
11936
|
+
constructor({ clientId, env = "dev", requestLogging, requestLoggingConfig, logger }) {
|
|
11937
|
+
if (_ApitallyClient.instance) {
|
|
11938
|
+
throw new Error("Apitally client is already initialized");
|
|
11939
|
+
}
|
|
11940
|
+
if (!isValidClientId(clientId)) {
|
|
11941
|
+
throw new Error(`Invalid Apitally client ID '${clientId}' (expecting hexadecimal UUID format)`);
|
|
11942
|
+
}
|
|
11943
|
+
if (!isValidEnv(env)) {
|
|
11944
|
+
throw new Error(`Invalid env '${env}' (expecting 1-32 alphanumeric lowercase characters and hyphens only)`);
|
|
11945
|
+
}
|
|
11946
|
+
if (requestLoggingConfig && !requestLogging) {
|
|
11947
|
+
console.warn("requestLoggingConfig is deprecated, use requestLogging instead.");
|
|
11948
|
+
}
|
|
11949
|
+
_ApitallyClient.instance = this;
|
|
11950
|
+
this.clientId = clientId;
|
|
11951
|
+
this.env = env;
|
|
11952
|
+
this.instanceUuid = (0, import_crypto5.randomUUID)();
|
|
11953
|
+
this.syncDataQueue = [];
|
|
11954
|
+
this.requestCounter = new RequestCounter();
|
|
11955
|
+
this.requestLogger = new RequestLogger(requestLogging ?? requestLoggingConfig);
|
|
11956
|
+
this.validationErrorCounter = new ValidationErrorCounter();
|
|
11957
|
+
this.serverErrorCounter = new ServerErrorCounter();
|
|
11958
|
+
this.consumerRegistry = new ConsumerRegistry();
|
|
11959
|
+
this.logger = logger ?? getLogger();
|
|
11960
|
+
this.startSync();
|
|
11961
|
+
this.handleShutdown = this.handleShutdown.bind(this);
|
|
11962
|
+
}
|
|
11963
|
+
static getInstance() {
|
|
11964
|
+
if (!_ApitallyClient.instance) {
|
|
11965
|
+
throw new Error("Apitally client is not initialized");
|
|
11966
|
+
}
|
|
11967
|
+
return _ApitallyClient.instance;
|
|
11968
|
+
}
|
|
11969
|
+
isEnabled() {
|
|
11970
|
+
return this.enabled;
|
|
11971
|
+
}
|
|
11972
|
+
static async shutdown() {
|
|
11973
|
+
if (_ApitallyClient.instance) {
|
|
11974
|
+
await _ApitallyClient.instance.handleShutdown();
|
|
11975
|
+
}
|
|
11976
|
+
}
|
|
11977
|
+
async handleShutdown() {
|
|
12110
11978
|
this.enabled = false;
|
|
12111
11979
|
this.stopSync();
|
|
12112
|
-
|
|
11980
|
+
await this.sendSyncData();
|
|
11981
|
+
await this.sendLogData();
|
|
11982
|
+
await this.requestLogger.close();
|
|
11983
|
+
_ApitallyClient.instance = void 0;
|
|
11984
|
+
}
|
|
11985
|
+
getHubUrlPrefix() {
|
|
11986
|
+
const baseURL = process.env.APITALLY_HUB_BASE_URL || "https://hub.apitally.io";
|
|
11987
|
+
const version = "v2";
|
|
11988
|
+
return `${baseURL}/${version}/${this.clientId}/${this.env}/`;
|
|
11989
|
+
}
|
|
11990
|
+
async sendData(url, payload) {
|
|
11991
|
+
const fetchWithRetry = (0, import_fetch_retry.default)(fetch, {
|
|
11992
|
+
retries: 3,
|
|
11993
|
+
retryDelay: 1e3,
|
|
11994
|
+
retryOn: [
|
|
11995
|
+
408,
|
|
11996
|
+
429,
|
|
11997
|
+
500,
|
|
11998
|
+
502,
|
|
11999
|
+
503,
|
|
12000
|
+
504
|
|
12001
|
+
]
|
|
12002
|
+
});
|
|
12003
|
+
const response = await fetchWithRetry(this.getHubUrlPrefix() + url, {
|
|
12004
|
+
method: "POST",
|
|
12005
|
+
body: JSON.stringify(payload),
|
|
12006
|
+
headers: {
|
|
12007
|
+
"Content-Type": "application/json"
|
|
12008
|
+
}
|
|
12009
|
+
});
|
|
12010
|
+
if (!response.ok) {
|
|
12011
|
+
throw new HTTPError(response);
|
|
12012
|
+
}
|
|
12113
12013
|
}
|
|
12114
|
-
|
|
12115
|
-
this.
|
|
12116
|
-
|
|
12014
|
+
startSync() {
|
|
12015
|
+
this.sync();
|
|
12016
|
+
this.syncIntervalId = setInterval(() => {
|
|
12017
|
+
this.sync();
|
|
12018
|
+
}, INITIAL_SYNC_INTERVAL);
|
|
12019
|
+
setTimeout(() => {
|
|
12020
|
+
clearInterval(this.syncIntervalId);
|
|
12021
|
+
this.syncIntervalId = setInterval(() => {
|
|
12022
|
+
this.sync();
|
|
12023
|
+
}, SYNC_INTERVAL);
|
|
12024
|
+
}, INITIAL_SYNC_INTERVAL_DURATION);
|
|
12025
|
+
}
|
|
12026
|
+
async sync() {
|
|
12027
|
+
try {
|
|
12028
|
+
const promises = [
|
|
12029
|
+
this.sendSyncData(),
|
|
12030
|
+
this.sendLogData()
|
|
12031
|
+
];
|
|
12032
|
+
if (!this.startupDataSent) {
|
|
12033
|
+
promises.push(this.sendStartupData());
|
|
12034
|
+
}
|
|
12035
|
+
await Promise.all(promises);
|
|
12036
|
+
} catch (error) {
|
|
12037
|
+
this.logger.error("Error while syncing with Apitally Hub", {
|
|
12038
|
+
error
|
|
12039
|
+
});
|
|
12040
|
+
}
|
|
12117
12041
|
}
|
|
12118
|
-
|
|
12119
|
-
|
|
12120
|
-
|
|
12121
|
-
|
|
12122
|
-
|
|
12123
|
-
|
|
12042
|
+
stopSync() {
|
|
12043
|
+
if (this.syncIntervalId) {
|
|
12044
|
+
clearInterval(this.syncIntervalId);
|
|
12045
|
+
this.syncIntervalId = void 0;
|
|
12046
|
+
}
|
|
12047
|
+
}
|
|
12048
|
+
setStartupData(data) {
|
|
12049
|
+
this.startupData = data;
|
|
12050
|
+
this.startupDataSent = false;
|
|
12051
|
+
this.sendStartupData();
|
|
12052
|
+
}
|
|
12053
|
+
async sendStartupData() {
|
|
12054
|
+
if (this.startupData) {
|
|
12055
|
+
this.logger.debug("Sending startup data to Apitally Hub");
|
|
12056
|
+
const payload = {
|
|
12057
|
+
instance_uuid: this.instanceUuid,
|
|
12058
|
+
message_uuid: (0, import_crypto5.randomUUID)(),
|
|
12059
|
+
...this.startupData
|
|
12060
|
+
};
|
|
12061
|
+
try {
|
|
12062
|
+
await this.sendData("startup", payload);
|
|
12063
|
+
this.startupDataSent = true;
|
|
12064
|
+
} catch (error) {
|
|
12065
|
+
const handled = this.handleHubError(error);
|
|
12066
|
+
if (!handled) {
|
|
12067
|
+
this.logger.error(error.message);
|
|
12068
|
+
this.logger.debug("Error while sending startup data to Apitally Hub (will retry)", {
|
|
12069
|
+
error
|
|
12070
|
+
});
|
|
12071
|
+
}
|
|
12072
|
+
}
|
|
12073
|
+
}
|
|
12074
|
+
}
|
|
12075
|
+
async sendSyncData() {
|
|
12076
|
+
this.logger.debug("Synchronizing data with Apitally Hub");
|
|
12077
|
+
const newPayload = {
|
|
12078
|
+
timestamp: Date.now() / 1e3,
|
|
12079
|
+
instance_uuid: this.instanceUuid,
|
|
12080
|
+
message_uuid: (0, import_crypto5.randomUUID)(),
|
|
12081
|
+
requests: this.requestCounter.getAndResetRequests(),
|
|
12082
|
+
validation_errors: this.validationErrorCounter.getAndResetValidationErrors(),
|
|
12083
|
+
server_errors: this.serverErrorCounter.getAndResetServerErrors(),
|
|
12084
|
+
consumers: this.consumerRegistry.getAndResetUpdatedConsumers()
|
|
12085
|
+
};
|
|
12086
|
+
this.syncDataQueue.push(newPayload);
|
|
12087
|
+
let i = 0;
|
|
12088
|
+
while (this.syncDataQueue.length > 0) {
|
|
12089
|
+
const payload = this.syncDataQueue.shift();
|
|
12090
|
+
if (payload) {
|
|
12091
|
+
try {
|
|
12092
|
+
if (Date.now() - payload.timestamp * 1e3 <= MAX_QUEUE_TIME) {
|
|
12093
|
+
if (i > 0) {
|
|
12094
|
+
await this.randomDelay();
|
|
12095
|
+
}
|
|
12096
|
+
await this.sendData("sync", payload);
|
|
12097
|
+
i += 1;
|
|
12098
|
+
}
|
|
12099
|
+
} catch (error) {
|
|
12100
|
+
const handled = this.handleHubError(error);
|
|
12101
|
+
if (!handled) {
|
|
12102
|
+
this.logger.debug("Error while synchronizing data with Apitally Hub (will retry)", {
|
|
12103
|
+
error
|
|
12104
|
+
});
|
|
12105
|
+
this.syncDataQueue.push(payload);
|
|
12106
|
+
break;
|
|
12107
|
+
}
|
|
12108
|
+
}
|
|
12109
|
+
}
|
|
12110
|
+
}
|
|
12111
|
+
}
|
|
12112
|
+
async sendLogData() {
|
|
12113
|
+
this.logger.debug("Sending request log data to Apitally Hub");
|
|
12114
|
+
await this.requestLogger.rotateFile();
|
|
12115
|
+
const fetchWithRetry = (0, import_fetch_retry.default)(fetch, {
|
|
12116
|
+
retries: 3,
|
|
12117
|
+
retryDelay: 1e3,
|
|
12118
|
+
retryOn: [
|
|
12119
|
+
408,
|
|
12120
|
+
429,
|
|
12121
|
+
500,
|
|
12122
|
+
502,
|
|
12123
|
+
503,
|
|
12124
|
+
504
|
|
12125
|
+
]
|
|
12126
|
+
});
|
|
12127
|
+
let i = 0;
|
|
12128
|
+
let logFile;
|
|
12129
|
+
while (logFile = this.requestLogger.getFile()) {
|
|
12130
|
+
if (i > 0) {
|
|
12131
|
+
await this.randomDelay();
|
|
12132
|
+
}
|
|
12133
|
+
try {
|
|
12134
|
+
const response = await fetchWithRetry(`${this.getHubUrlPrefix()}log?uuid=${logFile.uuid}`, {
|
|
12135
|
+
method: "POST",
|
|
12136
|
+
body: await logFile.getContent()
|
|
12137
|
+
});
|
|
12138
|
+
if (response.status === 402 && response.headers.has("Retry-After")) {
|
|
12139
|
+
const retryAfter = parseInt(response.headers.get("Retry-After") ?? "0");
|
|
12140
|
+
if (retryAfter > 0) {
|
|
12141
|
+
this.requestLogger.suspendUntil = Date.now() + retryAfter * 1e3;
|
|
12142
|
+
this.requestLogger.clear();
|
|
12143
|
+
return;
|
|
12144
|
+
}
|
|
12145
|
+
}
|
|
12146
|
+
if (!response.ok) {
|
|
12147
|
+
throw new HTTPError(response);
|
|
12148
|
+
}
|
|
12149
|
+
logFile.delete();
|
|
12150
|
+
} catch (error) {
|
|
12151
|
+
this.requestLogger.retryFileLater(logFile);
|
|
12152
|
+
break;
|
|
12153
|
+
}
|
|
12154
|
+
i++;
|
|
12155
|
+
if (i >= 10) break;
|
|
12156
|
+
}
|
|
12157
|
+
}
|
|
12158
|
+
handleHubError(error) {
|
|
12159
|
+
if (error instanceof HTTPError) {
|
|
12160
|
+
if (error.response.status === 404) {
|
|
12161
|
+
this.logger.error(`Invalid Apitally client ID: '${this.clientId}'`);
|
|
12162
|
+
this.enabled = false;
|
|
12163
|
+
this.stopSync();
|
|
12164
|
+
return true;
|
|
12165
|
+
}
|
|
12166
|
+
if (error.response.status === 422) {
|
|
12167
|
+
this.logger.error("Received validation error from Apitally Hub");
|
|
12168
|
+
return true;
|
|
12169
|
+
}
|
|
12170
|
+
}
|
|
12171
|
+
return false;
|
|
12172
|
+
}
|
|
12173
|
+
async randomDelay() {
|
|
12174
|
+
const delay = 100 + Math.random() * 400;
|
|
12175
|
+
await new Promise((resolve) => setTimeout(resolve, delay));
|
|
12176
|
+
}
|
|
12177
|
+
};
|
|
12178
|
+
__name(_ApitallyClient, "ApitallyClient");
|
|
12179
|
+
__publicField(_ApitallyClient, "instance");
|
|
12180
|
+
ApitallyClient = _ApitallyClient;
|
|
12124
12181
|
}
|
|
12125
|
-
};
|
|
12126
|
-
__name(_ApitallyClient, "ApitallyClient");
|
|
12127
|
-
__publicField(_ApitallyClient, "instance");
|
|
12128
|
-
var ApitallyClient = _ApitallyClient;
|
|
12182
|
+
});
|
|
12129
12183
|
|
|
12130
12184
|
// src/common/headers.ts
|
|
12131
12185
|
function parseContentLength(contentLength) {
|
|
@@ -12144,11 +12198,14 @@ function parseContentLength(contentLength) {
|
|
|
12144
12198
|
}
|
|
12145
12199
|
return void 0;
|
|
12146
12200
|
}
|
|
12147
|
-
|
|
12201
|
+
var init_headers = __esm({
|
|
12202
|
+
"src/common/headers.ts"() {
|
|
12203
|
+
"use strict";
|
|
12204
|
+
__name(parseContentLength, "parseContentLength");
|
|
12205
|
+
}
|
|
12206
|
+
});
|
|
12148
12207
|
|
|
12149
12208
|
// src/common/packageVersions.ts
|
|
12150
|
-
var import_module = require("module");
|
|
12151
|
-
var import_meta = {};
|
|
12152
12209
|
function getPackageVersion(name) {
|
|
12153
12210
|
const packageJsonPath = `${name}/package.json`;
|
|
12154
12211
|
try {
|
|
@@ -12162,176 +12219,190 @@ function getPackageVersion(name) {
|
|
|
12162
12219
|
}
|
|
12163
12220
|
}
|
|
12164
12221
|
}
|
|
12165
|
-
|
|
12222
|
+
var import_module, import_meta;
|
|
12223
|
+
var init_packageVersions = __esm({
|
|
12224
|
+
"src/common/packageVersions.ts"() {
|
|
12225
|
+
"use strict";
|
|
12226
|
+
import_module = require("module");
|
|
12227
|
+
import_meta = {};
|
|
12228
|
+
__name(getPackageVersion, "getPackageVersion");
|
|
12229
|
+
}
|
|
12230
|
+
});
|
|
12166
12231
|
|
|
12167
12232
|
// src/express/utils.js
|
|
12168
|
-
var regExpToParseExpressPathRegExp
|
|
12169
|
-
var
|
|
12170
|
-
|
|
12171
|
-
|
|
12172
|
-
|
|
12173
|
-
|
|
12174
|
-
|
|
12175
|
-
|
|
12176
|
-
|
|
12177
|
-
|
|
12178
|
-
|
|
12179
|
-
|
|
12180
|
-
|
|
12181
|
-
|
|
12182
|
-
|
|
12183
|
-
|
|
12184
|
-
|
|
12185
|
-
|
|
12186
|
-
|
|
12187
|
-
|
|
12188
|
-
|
|
12189
|
-
|
|
12190
|
-
|
|
12191
|
-
|
|
12192
|
-
|
|
12193
|
-
|
|
12194
|
-
|
|
12195
|
-
|
|
12196
|
-
|
|
12197
|
-
|
|
12198
|
-
|
|
12199
|
-
|
|
12200
|
-
|
|
12201
|
-
|
|
12202
|
-
|
|
12203
|
-
|
|
12204
|
-
|
|
12205
|
-
|
|
12206
|
-
|
|
12207
|
-
|
|
12208
|
-
|
|
12209
|
-
|
|
12210
|
-
|
|
12211
|
-
|
|
12212
|
-
|
|
12213
|
-
|
|
12214
|
-
}
|
|
12215
|
-
|
|
12216
|
-
|
|
12217
|
-
|
|
12218
|
-
|
|
12219
|
-
|
|
12220
|
-
|
|
12221
|
-
|
|
12222
|
-
|
|
12223
|
-
|
|
12224
|
-
|
|
12225
|
-
|
|
12226
|
-
|
|
12227
|
-
|
|
12228
|
-
|
|
12229
|
-
|
|
12230
|
-
|
|
12231
|
-
|
|
12232
|
-
}
|
|
12233
|
-
|
|
12234
|
-
|
|
12235
|
-
|
|
12236
|
-
|
|
12237
|
-
|
|
12238
|
-
|
|
12239
|
-
|
|
12240
|
-
|
|
12241
|
-
|
|
12242
|
-
|
|
12243
|
-
|
|
12244
|
-
|
|
12245
|
-
|
|
12246
|
-
|
|
12247
|
-
|
|
12248
|
-
|
|
12249
|
-
|
|
12250
|
-
|
|
12251
|
-
|
|
12252
|
-
|
|
12253
|
-
|
|
12254
|
-
|
|
12255
|
-
|
|
12256
|
-
|
|
12257
|
-
|
|
12258
|
-
|
|
12259
|
-
|
|
12260
|
-
|
|
12261
|
-
|
|
12262
|
-
|
|
12263
|
-
|
|
12264
|
-
|
|
12265
|
-
|
|
12266
|
-
|
|
12267
|
-
|
|
12268
|
-
endpoints =
|
|
12269
|
-
|
|
12270
|
-
|
|
12271
|
-
|
|
12272
|
-
|
|
12233
|
+
var regExpToParseExpressPathRegExp, regExpToReplaceExpressPathRegExpParams, regexpExpressParamRegexp, regexpExpressPathParamRegexp, EXPRESS_ROOT_PATH_REGEXP_VALUE, STACK_ITEM_VALID_NAMES, getRouterInfo, getRouteMethods, getRouteMiddlewares, hasParams, parseExpressRoute, parseExpressPathRegExp, parseExpressPath, parseEndpoints, addEndpoints, parseStack, getEndpoints;
|
|
12234
|
+
var init_utils = __esm({
|
|
12235
|
+
"src/express/utils.js"() {
|
|
12236
|
+
"use strict";
|
|
12237
|
+
regExpToParseExpressPathRegExp = /^\/\^\\?\/?(?:(:?[\w\\.-]*(?:\\\/:?[\w\\.-]*)*)|(\(\?:\\?\/?\([^)]+\)\)))\\\/.*/;
|
|
12238
|
+
regExpToReplaceExpressPathRegExpParams = /\(\?:\\?\/?\([^)]+\)\)/;
|
|
12239
|
+
regexpExpressParamRegexp = /\(\?:\\?\\?\/?\([^)]+\)\)/g;
|
|
12240
|
+
regexpExpressPathParamRegexp = /(:[^)]+)\([^)]+\)/g;
|
|
12241
|
+
EXPRESS_ROOT_PATH_REGEXP_VALUE = "/^\\/?(?=\\/|$)/i";
|
|
12242
|
+
STACK_ITEM_VALID_NAMES = [
|
|
12243
|
+
"router",
|
|
12244
|
+
"bound dispatch",
|
|
12245
|
+
"mounted_app"
|
|
12246
|
+
];
|
|
12247
|
+
getRouterInfo = /* @__PURE__ */ __name(function(app) {
|
|
12248
|
+
var _a3, _b;
|
|
12249
|
+
if (app.stack) {
|
|
12250
|
+
return {
|
|
12251
|
+
stack: app.stack,
|
|
12252
|
+
version: "v4"
|
|
12253
|
+
};
|
|
12254
|
+
} else if ((_a3 = app._router) == null ? void 0 : _a3.stack) {
|
|
12255
|
+
return {
|
|
12256
|
+
stack: app._router.stack,
|
|
12257
|
+
version: "v4"
|
|
12258
|
+
};
|
|
12259
|
+
} else if ((_b = app.router) == null ? void 0 : _b.stack) {
|
|
12260
|
+
return {
|
|
12261
|
+
stack: app.router.stack,
|
|
12262
|
+
version: "v5"
|
|
12263
|
+
};
|
|
12264
|
+
}
|
|
12265
|
+
return {
|
|
12266
|
+
stack: null,
|
|
12267
|
+
version: "v4"
|
|
12268
|
+
};
|
|
12269
|
+
}, "getRouterInfo");
|
|
12270
|
+
getRouteMethods = /* @__PURE__ */ __name(function(route) {
|
|
12271
|
+
let methods = Object.keys(route.methods);
|
|
12272
|
+
methods = methods.filter((method) => method !== "_all");
|
|
12273
|
+
methods = methods.map((method) => method.toUpperCase());
|
|
12274
|
+
return methods;
|
|
12275
|
+
}, "getRouteMethods");
|
|
12276
|
+
getRouteMiddlewares = /* @__PURE__ */ __name(function(route) {
|
|
12277
|
+
return route.stack.map((item) => {
|
|
12278
|
+
return item.handle.name || "anonymous";
|
|
12279
|
+
});
|
|
12280
|
+
}, "getRouteMiddlewares");
|
|
12281
|
+
hasParams = /* @__PURE__ */ __name(function(expressPathRegExp) {
|
|
12282
|
+
return regexpExpressParamRegexp.test(expressPathRegExp);
|
|
12283
|
+
}, "hasParams");
|
|
12284
|
+
parseExpressRoute = /* @__PURE__ */ __name(function(route, basePath) {
|
|
12285
|
+
const paths = [];
|
|
12286
|
+
if (Array.isArray(route.path)) {
|
|
12287
|
+
paths.push(...route.path);
|
|
12288
|
+
} else {
|
|
12289
|
+
paths.push(route.path);
|
|
12290
|
+
}
|
|
12291
|
+
const endpoints = paths.map((path) => {
|
|
12292
|
+
const completePath = basePath && path === "/" ? basePath : `${basePath}${path}`;
|
|
12293
|
+
const endpoint = {
|
|
12294
|
+
path: completePath.replace(regexpExpressPathParamRegexp, "$1"),
|
|
12295
|
+
methods: getRouteMethods(route),
|
|
12296
|
+
middlewares: getRouteMiddlewares(route)
|
|
12297
|
+
};
|
|
12298
|
+
return endpoint;
|
|
12299
|
+
});
|
|
12300
|
+
return endpoints;
|
|
12301
|
+
}, "parseExpressRoute");
|
|
12302
|
+
parseExpressPathRegExp = /* @__PURE__ */ __name(function(expressPathRegExp, keys) {
|
|
12303
|
+
let parsedRegExp = expressPathRegExp.toString();
|
|
12304
|
+
let expressPathRegExpExec = regExpToParseExpressPathRegExp.exec(parsedRegExp);
|
|
12305
|
+
let paramIndex = 0;
|
|
12306
|
+
while (hasParams(parsedRegExp)) {
|
|
12307
|
+
const paramName = keys[paramIndex].name;
|
|
12308
|
+
const paramId = `:${paramName}`;
|
|
12309
|
+
parsedRegExp = parsedRegExp.replace(regExpToReplaceExpressPathRegExpParams, (str) => {
|
|
12310
|
+
if (str.startsWith("(?:\\/")) {
|
|
12311
|
+
return `\\/${paramId}`;
|
|
12312
|
+
}
|
|
12313
|
+
return paramId;
|
|
12314
|
+
});
|
|
12315
|
+
paramIndex++;
|
|
12316
|
+
}
|
|
12317
|
+
if (parsedRegExp !== expressPathRegExp.toString()) {
|
|
12318
|
+
expressPathRegExpExec = regExpToParseExpressPathRegExp.exec(parsedRegExp);
|
|
12319
|
+
}
|
|
12320
|
+
return expressPathRegExpExec[1].replace(/\\\//g, "/");
|
|
12321
|
+
}, "parseExpressPathRegExp");
|
|
12322
|
+
parseExpressPath = /* @__PURE__ */ __name(function(expressPath, params) {
|
|
12323
|
+
let result = expressPath;
|
|
12324
|
+
for (const [paramName, paramValue] of Object.entries(params)) {
|
|
12325
|
+
result = result.replace(paramValue, `:${paramName}`);
|
|
12326
|
+
}
|
|
12327
|
+
return result;
|
|
12328
|
+
}, "parseExpressPath");
|
|
12329
|
+
parseEndpoints = /* @__PURE__ */ __name(function(app, basePath, endpoints) {
|
|
12330
|
+
const routerInfo = getRouterInfo(app);
|
|
12331
|
+
const stack = routerInfo.stack;
|
|
12332
|
+
const version = routerInfo.version;
|
|
12333
|
+
endpoints = endpoints || [];
|
|
12334
|
+
basePath = basePath || "";
|
|
12335
|
+
if (!stack) {
|
|
12336
|
+
if (endpoints.length) {
|
|
12337
|
+
endpoints = addEndpoints(endpoints, [
|
|
12338
|
+
{
|
|
12339
|
+
path: basePath,
|
|
12340
|
+
methods: [],
|
|
12341
|
+
middlewares: []
|
|
12342
|
+
}
|
|
12343
|
+
]);
|
|
12273
12344
|
}
|
|
12274
|
-
|
|
12275
|
-
|
|
12276
|
-
|
|
12277
|
-
|
|
12278
|
-
|
|
12279
|
-
|
|
12280
|
-
|
|
12281
|
-
|
|
12282
|
-
|
|
12283
|
-
|
|
12284
|
-
|
|
12285
|
-
|
|
12286
|
-
|
|
12287
|
-
} else {
|
|
12288
|
-
currentEndpoints.push(newEndpoint);
|
|
12289
|
-
}
|
|
12290
|
-
});
|
|
12291
|
-
return currentEndpoints;
|
|
12292
|
-
}, "addEndpoints");
|
|
12293
|
-
var parseStack = /* @__PURE__ */ __name(function(stack, basePath, endpoints, version) {
|
|
12294
|
-
stack.forEach((stackItem) => {
|
|
12295
|
-
if (stackItem.route) {
|
|
12296
|
-
const newEndpoints = parseExpressRoute(stackItem.route, basePath);
|
|
12297
|
-
endpoints = addEndpoints(endpoints, newEndpoints);
|
|
12298
|
-
} else if (STACK_ITEM_VALID_NAMES.includes(stackItem.name)) {
|
|
12299
|
-
let newBasePath = basePath;
|
|
12300
|
-
if (version === "v4") {
|
|
12301
|
-
const isExpressPathRegExp = regExpToParseExpressPathRegExp.test(stackItem.regexp);
|
|
12302
|
-
if (isExpressPathRegExp) {
|
|
12303
|
-
const parsedPath = parseExpressPathRegExp(stackItem.regexp, stackItem.keys);
|
|
12304
|
-
newBasePath += `/${parsedPath}`;
|
|
12305
|
-
} else if (!stackItem.path && stackItem.regexp && stackItem.regexp.toString() !== EXPRESS_ROOT_PATH_REGEXP_VALUE) {
|
|
12306
|
-
const regExpPath = `RegExp(${stackItem.regexp})`;
|
|
12307
|
-
newBasePath += `/${regExpPath}`;
|
|
12308
|
-
}
|
|
12309
|
-
} else if (version === "v5") {
|
|
12310
|
-
if (!stackItem.path) {
|
|
12311
|
-
return;
|
|
12312
|
-
} else if (stackItem.path !== "/") {
|
|
12313
|
-
newBasePath += stackItem.path.startsWith("/") ? stackItem.path : `/${stackItem.path}`;
|
|
12345
|
+
} else {
|
|
12346
|
+
endpoints = parseStack(stack, basePath, endpoints, version);
|
|
12347
|
+
}
|
|
12348
|
+
return endpoints;
|
|
12349
|
+
}, "parseEndpoints");
|
|
12350
|
+
addEndpoints = /* @__PURE__ */ __name(function(currentEndpoints, endpointsToAdd) {
|
|
12351
|
+
endpointsToAdd.forEach((newEndpoint) => {
|
|
12352
|
+
const existingEndpoint = currentEndpoints.find((endpoint) => endpoint.path === newEndpoint.path);
|
|
12353
|
+
if (existingEndpoint !== void 0) {
|
|
12354
|
+
const newMethods = newEndpoint.methods.filter((method) => !existingEndpoint.methods.includes(method));
|
|
12355
|
+
existingEndpoint.methods = existingEndpoint.methods.concat(newMethods);
|
|
12356
|
+
} else {
|
|
12357
|
+
currentEndpoints.push(newEndpoint);
|
|
12314
12358
|
}
|
|
12315
|
-
}
|
|
12316
|
-
|
|
12317
|
-
}
|
|
12318
|
-
|
|
12319
|
-
|
|
12320
|
-
|
|
12321
|
-
|
|
12322
|
-
|
|
12323
|
-
|
|
12324
|
-
|
|
12325
|
-
|
|
12326
|
-
|
|
12327
|
-
|
|
12328
|
-
|
|
12329
|
-
|
|
12330
|
-
|
|
12331
|
-
|
|
12332
|
-
|
|
12333
|
-
|
|
12334
|
-
}
|
|
12359
|
+
});
|
|
12360
|
+
return currentEndpoints;
|
|
12361
|
+
}, "addEndpoints");
|
|
12362
|
+
parseStack = /* @__PURE__ */ __name(function(stack, basePath, endpoints, version) {
|
|
12363
|
+
stack.forEach((stackItem) => {
|
|
12364
|
+
if (stackItem.route) {
|
|
12365
|
+
const newEndpoints = parseExpressRoute(stackItem.route, basePath);
|
|
12366
|
+
endpoints = addEndpoints(endpoints, newEndpoints);
|
|
12367
|
+
} else if (STACK_ITEM_VALID_NAMES.includes(stackItem.name)) {
|
|
12368
|
+
let newBasePath = basePath;
|
|
12369
|
+
if (version === "v4") {
|
|
12370
|
+
const isExpressPathRegExp = regExpToParseExpressPathRegExp.test(stackItem.regexp);
|
|
12371
|
+
if (isExpressPathRegExp) {
|
|
12372
|
+
const parsedPath = parseExpressPathRegExp(stackItem.regexp, stackItem.keys);
|
|
12373
|
+
newBasePath += `/${parsedPath}`;
|
|
12374
|
+
} else if (!stackItem.path && stackItem.regexp && stackItem.regexp.toString() !== EXPRESS_ROOT_PATH_REGEXP_VALUE) {
|
|
12375
|
+
const regExpPath = `RegExp(${stackItem.regexp})`;
|
|
12376
|
+
newBasePath += `/${regExpPath}`;
|
|
12377
|
+
}
|
|
12378
|
+
} else if (version === "v5") {
|
|
12379
|
+
if (!stackItem.path) {
|
|
12380
|
+
return;
|
|
12381
|
+
} else if (stackItem.path !== "/") {
|
|
12382
|
+
newBasePath += stackItem.path.startsWith("/") ? stackItem.path : `/${stackItem.path}`;
|
|
12383
|
+
}
|
|
12384
|
+
}
|
|
12385
|
+
endpoints = parseEndpoints(stackItem.handle, newBasePath, endpoints);
|
|
12386
|
+
}
|
|
12387
|
+
});
|
|
12388
|
+
return endpoints;
|
|
12389
|
+
}, "parseStack");
|
|
12390
|
+
getEndpoints = /* @__PURE__ */ __name(function(app, basePath) {
|
|
12391
|
+
const endpoints = parseEndpoints(app);
|
|
12392
|
+
const standardHttpMethods = [
|
|
12393
|
+
"GET",
|
|
12394
|
+
"POST",
|
|
12395
|
+
"PUT",
|
|
12396
|
+
"DELETE",
|
|
12397
|
+
"PATCH"
|
|
12398
|
+
];
|
|
12399
|
+
return endpoints.flatMap((route) => route.methods.filter((method) => standardHttpMethods.includes(method.toUpperCase())).map((method) => ({
|
|
12400
|
+
method,
|
|
12401
|
+
path: (basePath + route.path).replace(/\/\//g, "/")
|
|
12402
|
+
})));
|
|
12403
|
+
}, "getEndpoints");
|
|
12404
|
+
}
|
|
12405
|
+
});
|
|
12335
12406
|
|
|
12336
12407
|
// src/express/middleware.ts
|
|
12337
12408
|
function useApitally(app, config) {
|
|
@@ -12348,7 +12419,6 @@ function useApitally(app, config) {
|
|
|
12348
12419
|
}, "setStartupData");
|
|
12349
12420
|
setTimeout(() => setStartupData(), 500);
|
|
12350
12421
|
}
|
|
12351
|
-
__name(useApitally, "useApitally");
|
|
12352
12422
|
function getMiddleware(app, client) {
|
|
12353
12423
|
let errorHandlerConfigured = false;
|
|
12354
12424
|
return (req, res, next) => {
|
|
@@ -12467,7 +12537,6 @@ function getMiddleware(app, client) {
|
|
|
12467
12537
|
}
|
|
12468
12538
|
};
|
|
12469
12539
|
}
|
|
12470
|
-
__name(getMiddleware, "getMiddleware");
|
|
12471
12540
|
function getRoutePath(req) {
|
|
12472
12541
|
if (!req.route) {
|
|
12473
12542
|
return;
|
|
@@ -12481,7 +12550,6 @@ function getRoutePath(req) {
|
|
|
12481
12550
|
}
|
|
12482
12551
|
return req.route.path;
|
|
12483
12552
|
}
|
|
12484
|
-
__name(getRoutePath, "getRoutePath");
|
|
12485
12553
|
function getRouterPath(stack, baseUrl) {
|
|
12486
12554
|
var _a3;
|
|
12487
12555
|
const routerPaths = [];
|
|
@@ -12508,11 +12576,9 @@ function getRouterPath(stack, baseUrl) {
|
|
|
12508
12576
|
}
|
|
12509
12577
|
return routerPaths.filter((path) => path !== "/").join("");
|
|
12510
12578
|
}
|
|
12511
|
-
__name(getRouterPath, "getRouterPath");
|
|
12512
12579
|
function setConsumer(req, consumer) {
|
|
12513
12580
|
req.apitallyConsumer = consumer || void 0;
|
|
12514
12581
|
}
|
|
12515
|
-
__name(setConsumer, "setConsumer");
|
|
12516
12582
|
function getConsumer(req) {
|
|
12517
12583
|
if (req.apitallyConsumer) {
|
|
12518
12584
|
return consumerFromStringOrObject(req.apitallyConsumer);
|
|
@@ -12522,7 +12588,6 @@ function getConsumer(req) {
|
|
|
12522
12588
|
}
|
|
12523
12589
|
return null;
|
|
12524
12590
|
}
|
|
12525
|
-
__name(getConsumer, "getConsumer");
|
|
12526
12591
|
function extractExpressValidatorErrors(responseBody) {
|
|
12527
12592
|
try {
|
|
12528
12593
|
const errors = [];
|
|
@@ -12542,7 +12607,6 @@ function extractExpressValidatorErrors(responseBody) {
|
|
|
12542
12607
|
return [];
|
|
12543
12608
|
}
|
|
12544
12609
|
}
|
|
12545
|
-
__name(extractExpressValidatorErrors, "extractExpressValidatorErrors");
|
|
12546
12610
|
function extractCelebrateErrors(responseBody) {
|
|
12547
12611
|
try {
|
|
12548
12612
|
const errors = [];
|
|
@@ -12564,7 +12628,6 @@ function extractCelebrateErrors(responseBody) {
|
|
|
12564
12628
|
return [];
|
|
12565
12629
|
}
|
|
12566
12630
|
}
|
|
12567
|
-
__name(extractCelebrateErrors, "extractCelebrateErrors");
|
|
12568
12631
|
function extractNestValidationErrors(responseBody) {
|
|
12569
12632
|
try {
|
|
12570
12633
|
const errors = [];
|
|
@@ -12582,12 +12645,10 @@ function extractNestValidationErrors(responseBody) {
|
|
|
12582
12645
|
return [];
|
|
12583
12646
|
}
|
|
12584
12647
|
}
|
|
12585
|
-
__name(extractNestValidationErrors, "extractNestValidationErrors");
|
|
12586
12648
|
function subsetJoiMessage(message, key) {
|
|
12587
12649
|
const messageWithKey = message.split(". ").find((message2) => message2.includes(`"${key}"`));
|
|
12588
12650
|
return messageWithKey ? messageWithKey : message;
|
|
12589
12651
|
}
|
|
12590
|
-
__name(subsetJoiMessage, "subsetJoiMessage");
|
|
12591
12652
|
function getAppInfo(app, basePath, appVersion) {
|
|
12592
12653
|
const versions = [
|
|
12593
12654
|
[
|
|
@@ -12628,9 +12689,298 @@ function getAppInfo(app, basePath, appVersion) {
|
|
|
12628
12689
|
client: "js:express"
|
|
12629
12690
|
};
|
|
12630
12691
|
}
|
|
12631
|
-
|
|
12692
|
+
var import_perf_hooks;
|
|
12693
|
+
var init_middleware = __esm({
|
|
12694
|
+
"src/express/middleware.ts"() {
|
|
12695
|
+
"use strict";
|
|
12696
|
+
import_perf_hooks = require("perf_hooks");
|
|
12697
|
+
init_client();
|
|
12698
|
+
init_consumerRegistry();
|
|
12699
|
+
init_headers();
|
|
12700
|
+
init_packageVersions();
|
|
12701
|
+
init_requestLogger();
|
|
12702
|
+
init_utils();
|
|
12703
|
+
__name(useApitally, "useApitally");
|
|
12704
|
+
__name(getMiddleware, "getMiddleware");
|
|
12705
|
+
__name(getRoutePath, "getRoutePath");
|
|
12706
|
+
__name(getRouterPath, "getRouterPath");
|
|
12707
|
+
__name(setConsumer, "setConsumer");
|
|
12708
|
+
__name(getConsumer, "getConsumer");
|
|
12709
|
+
__name(extractExpressValidatorErrors, "extractExpressValidatorErrors");
|
|
12710
|
+
__name(extractCelebrateErrors, "extractCelebrateErrors");
|
|
12711
|
+
__name(extractNestValidationErrors, "extractNestValidationErrors");
|
|
12712
|
+
__name(subsetJoiMessage, "subsetJoiMessage");
|
|
12713
|
+
__name(getAppInfo, "getAppInfo");
|
|
12714
|
+
}
|
|
12715
|
+
});
|
|
12716
|
+
|
|
12717
|
+
// src/express/index.ts
|
|
12718
|
+
var express_exports = {};
|
|
12719
|
+
__export(express_exports, {
|
|
12720
|
+
setConsumer: () => setConsumer,
|
|
12721
|
+
useApitally: () => useApitally
|
|
12722
|
+
});
|
|
12723
|
+
var init_express = __esm({
|
|
12724
|
+
"src/express/index.ts"() {
|
|
12725
|
+
"use strict";
|
|
12726
|
+
init_middleware();
|
|
12727
|
+
}
|
|
12728
|
+
});
|
|
12729
|
+
|
|
12730
|
+
// src/fastify/plugin.ts
|
|
12731
|
+
function getAppInfo2(routes, appVersion) {
|
|
12732
|
+
const versions = [
|
|
12733
|
+
[
|
|
12734
|
+
"nodejs",
|
|
12735
|
+
process.version.replace(/^v/, "")
|
|
12736
|
+
]
|
|
12737
|
+
];
|
|
12738
|
+
const fastifyVersion = getPackageVersion("fastify");
|
|
12739
|
+
const nestjsVersion = getPackageVersion("@nestjs/core");
|
|
12740
|
+
const apitallyVersion = getPackageVersion("../..");
|
|
12741
|
+
if (fastifyVersion) {
|
|
12742
|
+
versions.push([
|
|
12743
|
+
"fastify",
|
|
12744
|
+
fastifyVersion
|
|
12745
|
+
]);
|
|
12746
|
+
}
|
|
12747
|
+
if (nestjsVersion) {
|
|
12748
|
+
versions.push([
|
|
12749
|
+
"nestjs",
|
|
12750
|
+
nestjsVersion
|
|
12751
|
+
]);
|
|
12752
|
+
}
|
|
12753
|
+
if (apitallyVersion) {
|
|
12754
|
+
versions.push([
|
|
12755
|
+
"apitally",
|
|
12756
|
+
apitallyVersion
|
|
12757
|
+
]);
|
|
12758
|
+
}
|
|
12759
|
+
if (appVersion) {
|
|
12760
|
+
versions.push([
|
|
12761
|
+
"app",
|
|
12762
|
+
appVersion
|
|
12763
|
+
]);
|
|
12764
|
+
}
|
|
12765
|
+
return {
|
|
12766
|
+
paths: routes,
|
|
12767
|
+
versions: Object.fromEntries(versions),
|
|
12768
|
+
client: "js:fastify"
|
|
12769
|
+
};
|
|
12770
|
+
}
|
|
12771
|
+
function setConsumer2(request, consumer) {
|
|
12772
|
+
request.apitallyConsumer = consumer || void 0;
|
|
12773
|
+
}
|
|
12774
|
+
function getConsumer2(request) {
|
|
12775
|
+
if (request.apitallyConsumer) {
|
|
12776
|
+
return consumerFromStringOrObject(request.apitallyConsumer);
|
|
12777
|
+
} else if (request.consumerIdentifier) {
|
|
12778
|
+
process.emitWarning("The consumerIdentifier property on the request object is deprecated. Use apitallyConsumer instead.", "DeprecationWarning");
|
|
12779
|
+
return consumerFromStringOrObject(request.consumerIdentifier);
|
|
12780
|
+
}
|
|
12781
|
+
return null;
|
|
12782
|
+
}
|
|
12783
|
+
function getResponseTime(reply) {
|
|
12784
|
+
if (reply.elapsedTime !== void 0) {
|
|
12785
|
+
return reply.elapsedTime;
|
|
12786
|
+
} else if (reply.getResponseTime !== void 0) {
|
|
12787
|
+
return reply.getResponseTime();
|
|
12788
|
+
}
|
|
12789
|
+
return 0;
|
|
12790
|
+
}
|
|
12791
|
+
function extractAjvErrors(message) {
|
|
12792
|
+
try {
|
|
12793
|
+
const regex = /(?<=^|, )((?:headers|params|query|querystring|body)[/.][^ ]+)(?= )/g;
|
|
12794
|
+
const matches = [];
|
|
12795
|
+
let match;
|
|
12796
|
+
while ((match = regex.exec(message)) !== null) {
|
|
12797
|
+
matches.push({
|
|
12798
|
+
match: match[0],
|
|
12799
|
+
index: match.index
|
|
12800
|
+
});
|
|
12801
|
+
}
|
|
12802
|
+
return matches.map((m, i) => {
|
|
12803
|
+
const endIndex = i + 1 < matches.length ? matches[i + 1].index - 2 : message.length;
|
|
12804
|
+
const matchSplit = m.match.split(/[/.]/);
|
|
12805
|
+
if (matchSplit[0] === "querystring") {
|
|
12806
|
+
matchSplit[0] = "query";
|
|
12807
|
+
}
|
|
12808
|
+
return {
|
|
12809
|
+
loc: matchSplit.join("."),
|
|
12810
|
+
msg: message.substring(m.index, endIndex),
|
|
12811
|
+
type: ""
|
|
12812
|
+
};
|
|
12813
|
+
});
|
|
12814
|
+
} catch (error) {
|
|
12815
|
+
return [];
|
|
12816
|
+
}
|
|
12817
|
+
}
|
|
12818
|
+
function extractNestValidationErrors2(message) {
|
|
12819
|
+
try {
|
|
12820
|
+
return message.filter((msg) => typeof msg === "string").map((msg) => ({
|
|
12821
|
+
loc: "",
|
|
12822
|
+
msg,
|
|
12823
|
+
type: ""
|
|
12824
|
+
}));
|
|
12825
|
+
} catch (error) {
|
|
12826
|
+
return [];
|
|
12827
|
+
}
|
|
12828
|
+
}
|
|
12829
|
+
var import_fastify_plugin, apitallyPlugin, plugin_default;
|
|
12830
|
+
var init_plugin = __esm({
|
|
12831
|
+
"src/fastify/plugin.ts"() {
|
|
12832
|
+
"use strict";
|
|
12833
|
+
import_fastify_plugin = __toESM(require("fastify-plugin"), 1);
|
|
12834
|
+
init_client();
|
|
12835
|
+
init_consumerRegistry();
|
|
12836
|
+
init_headers();
|
|
12837
|
+
init_packageVersions();
|
|
12838
|
+
init_requestLogger();
|
|
12839
|
+
apitallyPlugin = /* @__PURE__ */ __name(async (fastify, config) => {
|
|
12840
|
+
const client = new ApitallyClient(config);
|
|
12841
|
+
const routes = [];
|
|
12842
|
+
fastify.decorateRequest("apitallyConsumer", null);
|
|
12843
|
+
fastify.decorateRequest("consumerIdentifier", null);
|
|
12844
|
+
fastify.decorateReply("payload", null);
|
|
12845
|
+
fastify.addHook("onRoute", (routeOptions) => {
|
|
12846
|
+
const methods = Array.isArray(routeOptions.method) ? routeOptions.method : [
|
|
12847
|
+
routeOptions.method
|
|
12848
|
+
];
|
|
12849
|
+
methods.forEach((method) => {
|
|
12850
|
+
if (![
|
|
12851
|
+
"HEAD",
|
|
12852
|
+
"OPTIONS"
|
|
12853
|
+
].includes(method.toUpperCase())) {
|
|
12854
|
+
routes.push({
|
|
12855
|
+
method: method.toUpperCase(),
|
|
12856
|
+
path: routeOptions.url
|
|
12857
|
+
});
|
|
12858
|
+
}
|
|
12859
|
+
});
|
|
12860
|
+
});
|
|
12861
|
+
fastify.addHook("onReady", () => {
|
|
12862
|
+
client.setStartupData(getAppInfo2(routes, config.appVersion));
|
|
12863
|
+
});
|
|
12864
|
+
fastify.addHook("onClose", async () => {
|
|
12865
|
+
await client.handleShutdown();
|
|
12866
|
+
});
|
|
12867
|
+
fastify.addHook("onSend", (request, reply, payload, done) => {
|
|
12868
|
+
const contentType = reply.getHeader("content-type");
|
|
12869
|
+
if (client.requestLogger.isSupportedContentType(contentType)) {
|
|
12870
|
+
reply.payload = payload;
|
|
12871
|
+
}
|
|
12872
|
+
done();
|
|
12873
|
+
});
|
|
12874
|
+
fastify.addHook("onError", (request, reply, error, done) => {
|
|
12875
|
+
if (!error.statusCode || error.statusCode === 500) {
|
|
12876
|
+
reply.serverError = error;
|
|
12877
|
+
}
|
|
12878
|
+
done();
|
|
12879
|
+
});
|
|
12880
|
+
fastify.addHook("onResponse", (request, reply, done) => {
|
|
12881
|
+
var _a3;
|
|
12882
|
+
if (client.isEnabled() && request.method.toUpperCase() !== "OPTIONS") {
|
|
12883
|
+
const consumer = getConsumer2(request);
|
|
12884
|
+
const path = "routeOptions" in request ? request.routeOptions.url : request.routerPath;
|
|
12885
|
+
const requestSize = parseContentLength(request.headers["content-length"]);
|
|
12886
|
+
const responseSize = parseContentLength(reply.getHeader("content-length"));
|
|
12887
|
+
const responseTime = getResponseTime(reply);
|
|
12888
|
+
client.consumerRegistry.addOrUpdateConsumer(consumer);
|
|
12889
|
+
client.requestCounter.addRequest({
|
|
12890
|
+
consumer: consumer == null ? void 0 : consumer.identifier,
|
|
12891
|
+
method: request.method,
|
|
12892
|
+
path,
|
|
12893
|
+
statusCode: reply.statusCode,
|
|
12894
|
+
responseTime,
|
|
12895
|
+
requestSize,
|
|
12896
|
+
responseSize
|
|
12897
|
+
});
|
|
12898
|
+
if ((reply.statusCode === 400 || reply.statusCode === 422) && reply.payload) {
|
|
12899
|
+
try {
|
|
12900
|
+
const parsedPayload = JSON.parse(reply.payload);
|
|
12901
|
+
const validationErrors = [];
|
|
12902
|
+
if ((!parsedPayload.code || parsedPayload.code === "FST_ERR_VALIDATION") && typeof parsedPayload.message === "string") {
|
|
12903
|
+
validationErrors.push(...extractAjvErrors(parsedPayload.message));
|
|
12904
|
+
} else if (Array.isArray(parsedPayload.message)) {
|
|
12905
|
+
validationErrors.push(...extractNestValidationErrors2(parsedPayload.message));
|
|
12906
|
+
}
|
|
12907
|
+
validationErrors.forEach((error) => {
|
|
12908
|
+
client.validationErrorCounter.addValidationError({
|
|
12909
|
+
consumer: consumer == null ? void 0 : consumer.identifier,
|
|
12910
|
+
method: request.method,
|
|
12911
|
+
path,
|
|
12912
|
+
...error
|
|
12913
|
+
});
|
|
12914
|
+
});
|
|
12915
|
+
} catch (error) {
|
|
12916
|
+
}
|
|
12917
|
+
}
|
|
12918
|
+
if (reply.statusCode === 500 && reply.serverError) {
|
|
12919
|
+
client.serverErrorCounter.addServerError({
|
|
12920
|
+
consumer: consumer == null ? void 0 : consumer.identifier,
|
|
12921
|
+
method: request.method,
|
|
12922
|
+
path,
|
|
12923
|
+
type: reply.serverError.name,
|
|
12924
|
+
msg: reply.serverError.message,
|
|
12925
|
+
traceback: reply.serverError.stack || ""
|
|
12926
|
+
});
|
|
12927
|
+
}
|
|
12928
|
+
if (client.requestLogger.enabled) {
|
|
12929
|
+
client.requestLogger.logRequest({
|
|
12930
|
+
timestamp: Date.now() / 1e3,
|
|
12931
|
+
method: request.method,
|
|
12932
|
+
path,
|
|
12933
|
+
url: `${request.protocol}://${request.host ?? request.hostname}${request.originalUrl ?? request.url}`,
|
|
12934
|
+
headers: convertHeaders(request.headers),
|
|
12935
|
+
size: Number(requestSize),
|
|
12936
|
+
consumer: consumer == null ? void 0 : consumer.identifier,
|
|
12937
|
+
body: convertBody(request.body, request.headers["content-type"])
|
|
12938
|
+
}, {
|
|
12939
|
+
statusCode: reply.statusCode,
|
|
12940
|
+
responseTime: responseTime / 1e3,
|
|
12941
|
+
headers: convertHeaders(reply.getHeaders()),
|
|
12942
|
+
size: Number(responseSize),
|
|
12943
|
+
body: convertBody(reply.payload, (_a3 = reply.getHeader("content-type")) == null ? void 0 : _a3.toString())
|
|
12944
|
+
}, reply.serverError);
|
|
12945
|
+
}
|
|
12946
|
+
}
|
|
12947
|
+
done();
|
|
12948
|
+
});
|
|
12949
|
+
}, "apitallyPlugin");
|
|
12950
|
+
__name(getAppInfo2, "getAppInfo");
|
|
12951
|
+
__name(setConsumer2, "setConsumer");
|
|
12952
|
+
__name(getConsumer2, "getConsumer");
|
|
12953
|
+
__name(getResponseTime, "getResponseTime");
|
|
12954
|
+
__name(extractAjvErrors, "extractAjvErrors");
|
|
12955
|
+
__name(extractNestValidationErrors2, "extractNestValidationErrors");
|
|
12956
|
+
plugin_default = (0, import_fastify_plugin.default)(apitallyPlugin, {
|
|
12957
|
+
name: "apitally"
|
|
12958
|
+
});
|
|
12959
|
+
}
|
|
12960
|
+
});
|
|
12961
|
+
|
|
12962
|
+
// src/fastify/index.ts
|
|
12963
|
+
var fastify_exports = {};
|
|
12964
|
+
__export(fastify_exports, {
|
|
12965
|
+
apitallyPlugin: () => plugin_default,
|
|
12966
|
+
setConsumer: () => setConsumer2
|
|
12967
|
+
});
|
|
12968
|
+
var init_fastify = __esm({
|
|
12969
|
+
"src/fastify/index.ts"() {
|
|
12970
|
+
"use strict";
|
|
12971
|
+
init_plugin();
|
|
12972
|
+
}
|
|
12973
|
+
});
|
|
12632
12974
|
|
|
12633
12975
|
// src/nestjs/index.ts
|
|
12976
|
+
var nestjs_exports = {};
|
|
12977
|
+
__export(nestjs_exports, {
|
|
12978
|
+
setConsumer: () => setConsumer3,
|
|
12979
|
+
useApitally: () => useApitally2
|
|
12980
|
+
});
|
|
12981
|
+
module.exports = __toCommonJS(nestjs_exports);
|
|
12982
|
+
var import_common = require("@nestjs/common");
|
|
12983
|
+
var import_rxjs = __toESM(require_cjs(), 1);
|
|
12634
12984
|
function _ts_decorate(decorators, target, key, desc) {
|
|
12635
12985
|
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
12636
12986
|
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
|
@@ -12638,22 +12988,48 @@ function _ts_decorate(decorators, target, key, desc) {
|
|
|
12638
12988
|
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
12639
12989
|
}
|
|
12640
12990
|
__name(_ts_decorate, "_ts_decorate");
|
|
12641
|
-
function
|
|
12991
|
+
function _ts_metadata(k, v) {
|
|
12992
|
+
if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
|
|
12993
|
+
}
|
|
12994
|
+
__name(_ts_metadata, "_ts_metadata");
|
|
12995
|
+
var setConsumerFn = null;
|
|
12996
|
+
async function useApitally2(app, config) {
|
|
12642
12997
|
const httpAdapter = app.getHttpAdapter();
|
|
12643
|
-
const
|
|
12644
|
-
|
|
12645
|
-
|
|
12998
|
+
const instance = httpAdapter.getInstance();
|
|
12999
|
+
const platform = httpAdapter.constructor.name.toLowerCase().includes("fastify") ? "fastify" : "express";
|
|
13000
|
+
if (platform === "express") {
|
|
13001
|
+
const { useApitally: useApitally3, setConsumer: setConsumer4 } = await Promise.resolve().then(() => (init_express(), express_exports));
|
|
13002
|
+
setConsumerFn = setConsumer4;
|
|
13003
|
+
useApitally3(instance, config);
|
|
13004
|
+
} else if (platform === "fastify") {
|
|
13005
|
+
const { apitallyPlugin: apitallyPlugin2, setConsumer: setConsumer4 } = await Promise.resolve().then(() => (init_fastify(), fastify_exports));
|
|
13006
|
+
setConsumerFn = setConsumer4;
|
|
13007
|
+
await instance.register(apitallyPlugin2, config);
|
|
13008
|
+
}
|
|
13009
|
+
app.useGlobalInterceptors(new ApitallyInterceptor(platform));
|
|
12646
13010
|
}
|
|
12647
13011
|
__name(useApitally2, "useApitally");
|
|
13012
|
+
function setConsumer3(request, consumer) {
|
|
13013
|
+
if (setConsumerFn) {
|
|
13014
|
+
setConsumerFn(request, consumer);
|
|
13015
|
+
}
|
|
13016
|
+
}
|
|
13017
|
+
__name(setConsumer3, "setConsumer");
|
|
12648
13018
|
var _a2;
|
|
12649
13019
|
var ApitallyInterceptor = (_a2 = class {
|
|
13020
|
+
platform;
|
|
13021
|
+
constructor(platform) {
|
|
13022
|
+
this.platform = platform;
|
|
13023
|
+
}
|
|
12650
13024
|
intercept(context, next) {
|
|
12651
13025
|
return next.handle().pipe((0, import_rxjs.catchError)((exception) => {
|
|
12652
13026
|
if (context.getType() === "http") {
|
|
12653
13027
|
const ctx = context.switchToHttp();
|
|
12654
13028
|
const res = ctx.getResponse();
|
|
12655
|
-
if (res.locals) {
|
|
13029
|
+
if (this.platform === "express" && res.locals) {
|
|
12656
13030
|
res.locals.serverError = exception;
|
|
13031
|
+
} else if (this.platform === "fastify" && (!exception.statusCode || exception.statusCode === 500)) {
|
|
13032
|
+
res.serverError = exception;
|
|
12657
13033
|
}
|
|
12658
13034
|
}
|
|
12659
13035
|
return (0, import_rxjs.throwError)(() => exception);
|
|
@@ -12661,7 +13037,11 @@ var ApitallyInterceptor = (_a2 = class {
|
|
|
12661
13037
|
}
|
|
12662
13038
|
}, __name(_a2, "ApitallyInterceptor"), _a2);
|
|
12663
13039
|
ApitallyInterceptor = _ts_decorate([
|
|
12664
|
-
(0, import_common.Injectable)()
|
|
13040
|
+
(0, import_common.Injectable)(),
|
|
13041
|
+
_ts_metadata("design:type", Function),
|
|
13042
|
+
_ts_metadata("design:paramtypes", [
|
|
13043
|
+
String
|
|
13044
|
+
])
|
|
12665
13045
|
], ApitallyInterceptor);
|
|
12666
13046
|
// Annotate the CommonJS export names for ESM import in node:
|
|
12667
13047
|
0 && (module.exports = {
|