@angelitosystems/nest-devtools 1.0.7 → 1.0.9
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/dist/index.cjs +124 -44
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +124 -51
- package/dist/index.js.map +1 -1
- package/package.json +3 -3
package/dist/index.js
CHANGED
|
@@ -1,10 +1,3 @@
|
|
|
1
|
-
var __require = /* @__PURE__ */ ((x) => typeof require !== "undefined" ? require : typeof Proxy !== "undefined" ? new Proxy(x, {
|
|
2
|
-
get: (a, b) => (typeof require !== "undefined" ? require : a)[b]
|
|
3
|
-
}) : x)(function(x) {
|
|
4
|
-
if (typeof require !== "undefined") return require.apply(this, arguments);
|
|
5
|
-
throw Error('Dynamic require of "' + x + '" is not supported');
|
|
6
|
-
});
|
|
7
|
-
|
|
8
1
|
// src/sdk.ts
|
|
9
2
|
import { hostname } from "os";
|
|
10
3
|
import { devtools as coreDevtools2, resolveConfig } from "@angelitosystems/devtools-core";
|
|
@@ -53,25 +46,6 @@ function recordSpan(requestId, layer, label, options) {
|
|
|
53
46
|
}
|
|
54
47
|
|
|
55
48
|
// src/instrumentation/http.ts
|
|
56
|
-
var REQUEST_HEADERS = [
|
|
57
|
-
"content-type",
|
|
58
|
-
"content-length",
|
|
59
|
-
"accept",
|
|
60
|
-
"origin",
|
|
61
|
-
"referer",
|
|
62
|
-
"user-agent",
|
|
63
|
-
"x-forwarded-for",
|
|
64
|
-
"x-request-id",
|
|
65
|
-
"x-forwarded-proto"
|
|
66
|
-
];
|
|
67
|
-
var RESPONSE_HEADERS = [
|
|
68
|
-
"content-type",
|
|
69
|
-
"content-length",
|
|
70
|
-
"location",
|
|
71
|
-
"set-cookie",
|
|
72
|
-
"x-request-id",
|
|
73
|
-
"x-response-time"
|
|
74
|
-
];
|
|
75
49
|
var WRAPPED = /* @__PURE__ */ Symbol("nest-devtools.wrapped");
|
|
76
50
|
var HttpInstrumentation = class {
|
|
77
51
|
constructor(ctx) {
|
|
@@ -169,6 +143,7 @@ var HttpInstrumentation = class {
|
|
|
169
143
|
};
|
|
170
144
|
spans.push(middlewareSpan);
|
|
171
145
|
const capturedBody = this.ctx.config.capture.requests && this.ctx.config.maxPayloadBytes > 0 ? captureRequestPreview(req, this.redactor) : void 0;
|
|
146
|
+
const responseCapture = createResponseCapture(res, this.ctx.config.maxPayloadBytes, this.redactor);
|
|
172
147
|
const onFinished = () => {
|
|
173
148
|
const finishedAt = Date.now();
|
|
174
149
|
middlewareSpan.duration = Math.max(0, finishedAt - middlewareSpan.startedAt);
|
|
@@ -182,7 +157,8 @@ var HttpInstrumentation = class {
|
|
|
182
157
|
};
|
|
183
158
|
spans.push(responseSpan);
|
|
184
159
|
const responseHeaders = this.collectResponseHeaders(res);
|
|
185
|
-
const responsePreview =
|
|
160
|
+
const responsePreview = responseCapture.read();
|
|
161
|
+
const requestBody = this.ctx.config.capture.requests && this.ctx.config.maxPayloadBytes > 0 ? captureRequestPreview(req, this.redactor) : void 0;
|
|
186
162
|
const errored = res.statusCode >= 500;
|
|
187
163
|
const completed = {
|
|
188
164
|
requestId,
|
|
@@ -194,10 +170,11 @@ var HttpInstrumentation = class {
|
|
|
194
170
|
duration: finishedAt - startedAt,
|
|
195
171
|
startedAt,
|
|
196
172
|
timeline: spans,
|
|
173
|
+
requestHeaders: started.headers,
|
|
197
174
|
query: parseQuery(rawUrl),
|
|
198
175
|
headers: responseHeaders,
|
|
199
176
|
responsePreview,
|
|
200
|
-
requestBody: capturedBody,
|
|
177
|
+
requestBody: requestBody ?? capturedBody,
|
|
201
178
|
errored
|
|
202
179
|
};
|
|
203
180
|
emit("request.completed", completed);
|
|
@@ -222,8 +199,7 @@ var HttpInstrumentation = class {
|
|
|
222
199
|
}
|
|
223
200
|
collectRequestHeaders(req) {
|
|
224
201
|
const out = {};
|
|
225
|
-
for (const key of
|
|
226
|
-
const value = req.headers[key];
|
|
202
|
+
for (const [key, value] of Object.entries(req.headers)) {
|
|
227
203
|
if (value === void 0) continue;
|
|
228
204
|
out[key] = this.redactor.isSensitive(key) ? "[REDACTED]" : asString(value).slice(0, 200);
|
|
229
205
|
}
|
|
@@ -231,12 +207,9 @@ var HttpInstrumentation = class {
|
|
|
231
207
|
}
|
|
232
208
|
collectResponseHeaders(res) {
|
|
233
209
|
const out = {};
|
|
234
|
-
const headers = res.
|
|
235
|
-
if (!headers || typeof headers !== "object") return out;
|
|
210
|
+
const headers = typeof res.getHeaders === "function" ? res.getHeaders() : {};
|
|
236
211
|
for (const rawKey of Object.keys(headers)) {
|
|
237
212
|
const key = rawKey.toLowerCase();
|
|
238
|
-
const ok = RESPONSE_HEADERS.some((h) => h.toLowerCase() === key);
|
|
239
|
-
if (!ok) continue;
|
|
240
213
|
const raw = headers[rawKey] ?? "";
|
|
241
214
|
const value = String(raw);
|
|
242
215
|
if (value === "") continue;
|
|
@@ -313,16 +286,38 @@ function captureRequestPreview(req, redactor) {
|
|
|
313
286
|
return void 0;
|
|
314
287
|
}
|
|
315
288
|
}
|
|
316
|
-
function
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
289
|
+
function createResponseCapture(res, maxBytes, redactor) {
|
|
290
|
+
if (maxBytes <= 0) return { read: () => void 0 };
|
|
291
|
+
const chunks = [];
|
|
292
|
+
let size = 0;
|
|
293
|
+
const originalWrite = res.write.bind(res);
|
|
294
|
+
const originalEnd = res.end.bind(res);
|
|
295
|
+
const capture2 = (chunk) => {
|
|
296
|
+
if (chunk === void 0 || chunk === null || size >= maxBytes) return;
|
|
297
|
+
const buffer = Buffer.isBuffer(chunk) ? chunk : Buffer.from(String(chunk));
|
|
298
|
+
const remaining = maxBytes - size;
|
|
299
|
+
chunks.push(buffer.subarray(0, remaining));
|
|
300
|
+
size += Math.min(buffer.length, remaining);
|
|
301
|
+
};
|
|
302
|
+
res.write = (chunk, ...args) => {
|
|
303
|
+
capture2(chunk);
|
|
304
|
+
return originalWrite(chunk, ...args);
|
|
305
|
+
};
|
|
306
|
+
res.end = (chunk, ...args) => {
|
|
307
|
+
capture2(chunk);
|
|
308
|
+
return originalEnd(chunk, ...args);
|
|
309
|
+
};
|
|
310
|
+
res.once("finish", () => {
|
|
311
|
+
res.write = originalWrite;
|
|
312
|
+
res.end = originalEnd;
|
|
313
|
+
});
|
|
314
|
+
return {
|
|
315
|
+
read: () => {
|
|
316
|
+
if (chunks.length === 0) return void 0;
|
|
317
|
+
const raw = Buffer.concat(chunks).toString("utf8");
|
|
318
|
+
return redactor.redactString(raw);
|
|
319
|
+
}
|
|
320
|
+
};
|
|
326
321
|
}
|
|
327
322
|
|
|
328
323
|
// src/instrumentation/console.ts
|
|
@@ -639,6 +634,13 @@ var AppExplorer = class {
|
|
|
639
634
|
extractMembers(node) {
|
|
640
635
|
const controllers = [];
|
|
641
636
|
const providers = [];
|
|
637
|
+
const controllersMap = node.controllers;
|
|
638
|
+
if (controllersMap instanceof Map) {
|
|
639
|
+
for (const [id, wrapper] of controllersMap) {
|
|
640
|
+
const member = this.memberFromWrapper(id, wrapper, "controller");
|
|
641
|
+
if (member) controllers.push(member);
|
|
642
|
+
}
|
|
643
|
+
}
|
|
642
644
|
const providersMap = node.providers;
|
|
643
645
|
if (providersMap instanceof Map) {
|
|
644
646
|
for (const [id, wrapper] of providersMap) {
|
|
@@ -653,10 +655,10 @@ var AppExplorer = class {
|
|
|
653
655
|
}
|
|
654
656
|
return { controllers, providers };
|
|
655
657
|
}
|
|
656
|
-
memberFromWrapper(id, wrapper) {
|
|
658
|
+
memberFromWrapper(id, wrapper, forcedType) {
|
|
657
659
|
const w = wrapper;
|
|
658
660
|
const name = w?.metatype?.name ?? (typeof id === "string" ? id.replace(/^[A-Z_0-9]+:/, "") : "unknown");
|
|
659
|
-
const type = classify(name, w?.instance);
|
|
661
|
+
const type = forcedType ?? classify(name, w?.instance);
|
|
660
662
|
const routes = type === "controller" ? extractControllerRoutes(w?.metatype) : void 0;
|
|
661
663
|
return { name, type, routes };
|
|
662
664
|
}
|
|
@@ -813,6 +815,7 @@ var WebsocketInstrumentation = class {
|
|
|
813
815
|
}
|
|
814
816
|
if (method === "handleMessage" || method === "handleEvent") {
|
|
815
817
|
const payload = this.extractPayload(args);
|
|
818
|
+
this.emitMessage("received", instance, args, payload, requestId, started);
|
|
816
819
|
recordSpan(requestId, "websocket", `ws.receive:${this.estimateEvent(args)}`, {
|
|
817
820
|
detail: `gateway=${instance.constructor?.name} payload=${this.redactor.serialize(payload)}`
|
|
818
821
|
});
|
|
@@ -821,6 +824,7 @@ var WebsocketInstrumentation = class {
|
|
|
821
824
|
const result = await Promise.resolve(original.call(instance, ...args));
|
|
822
825
|
if (method === "handleMessage" || method === "handleEvent") {
|
|
823
826
|
const payload = this.extractPayload(args);
|
|
827
|
+
this.emitMessage("sent", instance, args, payload, requestId, started);
|
|
824
828
|
recordSpan(requestId, "websocket", `ws.send:${this.estimateEvent(args)}`, {
|
|
825
829
|
detail: `gateway=${instance.constructor?.name} payload=${this.redactor.serialize(payload)}`,
|
|
826
830
|
status: "ok"
|
|
@@ -838,6 +842,21 @@ var WebsocketInstrumentation = class {
|
|
|
838
842
|
}
|
|
839
843
|
};
|
|
840
844
|
}
|
|
845
|
+
emitMessage(direction, instance, args, payload, requestId, startedAt) {
|
|
846
|
+
const preview = this.redactor.redact(payload);
|
|
847
|
+
const serialized = this.redactor.serialize(payload);
|
|
848
|
+
emit("websocket.message", {
|
|
849
|
+
projectId: this.projectId,
|
|
850
|
+
gateway: instance.constructor?.name ?? this.estimateGatewayName(instance),
|
|
851
|
+
event: this.estimateEvent(args),
|
|
852
|
+
direction,
|
|
853
|
+
payloadSize: Buffer.byteLength(serialized, "utf8"),
|
|
854
|
+
payloadPreview: preview,
|
|
855
|
+
requestId,
|
|
856
|
+
duration: Date.now() - startedAt,
|
|
857
|
+
timestamp: Date.now()
|
|
858
|
+
});
|
|
859
|
+
}
|
|
841
860
|
extractPayload(args) {
|
|
842
861
|
for (const arg of args) {
|
|
843
862
|
if (arg && typeof arg === "object" && !Buffer.isBuffer(arg) && !ArrayBuffer.isView(arg)) {
|
|
@@ -915,6 +934,23 @@ var DatabaseInstrumentation = class {
|
|
|
915
934
|
if (!app) return false;
|
|
916
935
|
const dataSource = this.resolveTypeOrmDataSource(app);
|
|
917
936
|
if (!dataSource) return false;
|
|
937
|
+
if (typeof dataSource.query === "function") {
|
|
938
|
+
const originalQuery = dataSource.query.bind(dataSource);
|
|
939
|
+
dataSource.__nestDevToolsOriginalQuery = originalQuery;
|
|
940
|
+
dataSource.query = async (query, parameters) => {
|
|
941
|
+
const started = Date.now();
|
|
942
|
+
this.startQuery(String(query), parameters ?? []);
|
|
943
|
+
try {
|
|
944
|
+
const result = await originalQuery(query, parameters);
|
|
945
|
+
this.endQuery(String(query), parameters ?? [], Date.now() - started);
|
|
946
|
+
return result;
|
|
947
|
+
} catch (error) {
|
|
948
|
+
this.endQuery(String(query), parameters ?? [], Date.now() - started, error);
|
|
949
|
+
throw error;
|
|
950
|
+
}
|
|
951
|
+
};
|
|
952
|
+
return true;
|
|
953
|
+
}
|
|
918
954
|
const listener = {
|
|
919
955
|
beforeQuery: (query, parameters) => {
|
|
920
956
|
this.startQuery(query, parameters);
|
|
@@ -967,6 +1003,22 @@ var DatabaseInstrumentation = class {
|
|
|
967
1003
|
if (!app) return false;
|
|
968
1004
|
const prisma = this.resolvePrismaClient(app);
|
|
969
1005
|
if (!prisma) return false;
|
|
1006
|
+
if (typeof prisma.$use === "function") {
|
|
1007
|
+
prisma.$use(async (params, next) => {
|
|
1008
|
+
const label = `${params.model ?? "prisma"}.${params.action ?? "query"}`;
|
|
1009
|
+
const started = Date.now();
|
|
1010
|
+
this.startQuery(label, [params.args]);
|
|
1011
|
+
try {
|
|
1012
|
+
const result = await next(params);
|
|
1013
|
+
this.endQuery(label, [params.args], Date.now() - started);
|
|
1014
|
+
return result;
|
|
1015
|
+
} catch (error) {
|
|
1016
|
+
this.endQuery(label, [params.args], Date.now() - started, error);
|
|
1017
|
+
throw error;
|
|
1018
|
+
}
|
|
1019
|
+
});
|
|
1020
|
+
return true;
|
|
1021
|
+
}
|
|
970
1022
|
const original = prisma.$queryRaw ?? prisma.$executeRaw ?? null;
|
|
971
1023
|
if (!original) return false;
|
|
972
1024
|
const wrapped = (query, parameters) => {
|
|
@@ -1110,8 +1162,8 @@ var DatabaseInstrumentation = class {
|
|
|
1110
1162
|
}
|
|
1111
1163
|
resolveTypeOrmDataSource(app) {
|
|
1112
1164
|
try {
|
|
1113
|
-
const dataSource =
|
|
1114
|
-
if (dataSource
|
|
1165
|
+
const dataSource = this.findProvider(app, (value) => typeof value?.query === "function" && typeof value?.manager === "object");
|
|
1166
|
+
if (dataSource) return dataSource;
|
|
1115
1167
|
return null;
|
|
1116
1168
|
} catch {
|
|
1117
1169
|
return null;
|
|
@@ -1119,7 +1171,7 @@ var DatabaseInstrumentation = class {
|
|
|
1119
1171
|
}
|
|
1120
1172
|
resolvePrismaClient(app) {
|
|
1121
1173
|
try {
|
|
1122
|
-
const prisma =
|
|
1174
|
+
const prisma = this.safeGet(app, "PrismaService") ?? this.safeGet(app, "PrismaClient") ?? this.safeGet(app, "prisma") ?? this.findProvider(app, (value) => typeof value?.$queryRaw === "function");
|
|
1123
1175
|
if (prisma && typeof prisma.$queryRaw === "function") return prisma;
|
|
1124
1176
|
return null;
|
|
1125
1177
|
} catch {
|
|
@@ -1128,13 +1180,34 @@ var DatabaseInstrumentation = class {
|
|
|
1128
1180
|
}
|
|
1129
1181
|
resolveMongoose(app) {
|
|
1130
1182
|
try {
|
|
1131
|
-
const mongoose =
|
|
1183
|
+
const mongoose = this.safeGet(app, "MongooseService") ?? this.safeGet(app, "Mongoose") ?? this.safeGet(app, "mongoose") ?? this.findProvider(app, (value) => typeof value?.plugin === "function");
|
|
1132
1184
|
if (mongoose && typeof mongoose.plugin === "function") return mongoose;
|
|
1133
1185
|
return null;
|
|
1134
1186
|
} catch {
|
|
1135
1187
|
return null;
|
|
1136
1188
|
}
|
|
1137
1189
|
}
|
|
1190
|
+
safeGet(app, token) {
|
|
1191
|
+
try {
|
|
1192
|
+
return app?.get?.(token, { strict: false }) ?? null;
|
|
1193
|
+
} catch {
|
|
1194
|
+
return null;
|
|
1195
|
+
}
|
|
1196
|
+
}
|
|
1197
|
+
findProvider(app, predicate) {
|
|
1198
|
+
try {
|
|
1199
|
+
const modules = app?.container?.getModules?.() ?? /* @__PURE__ */ new Map();
|
|
1200
|
+
for (const module of modules.values()) {
|
|
1201
|
+
for (const wrapper of module.providers?.values?.() ?? []) {
|
|
1202
|
+
const instance = wrapper?.instance;
|
|
1203
|
+
if (instance && predicate(instance)) return instance;
|
|
1204
|
+
}
|
|
1205
|
+
}
|
|
1206
|
+
return null;
|
|
1207
|
+
} catch {
|
|
1208
|
+
return null;
|
|
1209
|
+
}
|
|
1210
|
+
}
|
|
1138
1211
|
};
|
|
1139
1212
|
|
|
1140
1213
|
// src/instrumentation/queue.ts
|
|
@@ -1307,7 +1380,7 @@ function detectNestJsVersion() {
|
|
|
1307
1380
|
}
|
|
1308
1381
|
|
|
1309
1382
|
// src/version.ts
|
|
1310
|
-
var SDK_VERSION = "
|
|
1383
|
+
var SDK_VERSION = "1.0.9";
|
|
1311
1384
|
|
|
1312
1385
|
// src/banner.ts
|
|
1313
1386
|
var RESET = "\x1B[0m";
|