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