@oconde/radar 0.2.0 → 0.3.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/CHANGELOG.md +10 -0
- package/README.md +8 -0
- package/dist/{client-CZHtsQAd.d.cts → client-BB-to8cr.d.cts} +11 -0
- package/dist/{client-DbBsXgpj.d.ts → client-BS798K3S.d.ts} +11 -0
- package/dist/index.cjs +177 -14
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +2 -2
- package/dist/index.d.ts +2 -2
- package/dist/index.js +186 -23
- package/dist/index.js.map +1 -1
- package/dist/nest/index.cjs +177 -14
- package/dist/nest/index.cjs.map +1 -1
- package/dist/nest/index.d.cts +1 -1
- package/dist/nest/index.d.ts +1 -1
- package/dist/nest/index.js +186 -23
- package/dist/nest/index.js.map +1 -1
- package/dist/sveltekit/index.cjs +179 -16
- package/dist/sveltekit/index.cjs.map +1 -1
- package/dist/sveltekit/index.d.cts +1 -1
- package/dist/sveltekit/index.d.ts +1 -1
- package/dist/sveltekit/index.js +190 -27
- package/dist/sveltekit/index.js.map +1 -1
- package/package.json +3 -3
package/dist/sveltekit/index.cjs
CHANGED
|
@@ -289,7 +289,10 @@ function requestPath(req) {
|
|
|
289
289
|
}
|
|
290
290
|
function requestRoute(req, route) {
|
|
291
291
|
if (route) return route;
|
|
292
|
-
|
|
292
|
+
if (typeof req.route?.path !== "string") return void 0;
|
|
293
|
+
const base = typeof req.baseUrl === "string" ? req.baseUrl.replace(/\/+$/, "") : "";
|
|
294
|
+
if (!base) return req.route.path;
|
|
295
|
+
return req.route.path === "/" ? base : `${base}${req.route.path}`;
|
|
293
296
|
}
|
|
294
297
|
var ROUTE_PARAM = /^:([A-Za-z_$][\w$]*)/;
|
|
295
298
|
function pathSegments(value) {
|
|
@@ -423,6 +426,12 @@ function createMiddleware(logger) {
|
|
|
423
426
|
// src/options.ts
|
|
424
427
|
var DEFAULT_ENDPOINT = "https://radar-ingest.oconde.dev";
|
|
425
428
|
var LEVELS = ["debug", "info", "warn", "error"];
|
|
429
|
+
function resolveTraceFetch(value) {
|
|
430
|
+
if (!value) return { enabled: false, propagateTo: [] };
|
|
431
|
+
if (value === true) return { enabled: true, propagateTo: [] };
|
|
432
|
+
const targets2 = Array.isArray(value.propagateTo) ? value.propagateTo : [];
|
|
433
|
+
return { enabled: true, propagateTo: targets2.filter((target) => typeof target === "string" ? target.trim() !== "" : target instanceof RegExp) };
|
|
434
|
+
}
|
|
426
435
|
function resolveOptions(options = {}, env = process.env) {
|
|
427
436
|
const key = options.key?.trim() || void 0;
|
|
428
437
|
return {
|
|
@@ -438,6 +447,7 @@ function resolveOptions(options = {}, env = process.env) {
|
|
|
438
447
|
logRequests: options.logRequests ?? true,
|
|
439
448
|
ignorePaths: options.ignorePaths ?? ["/healthz", "/health"],
|
|
440
449
|
captureUnhandled: options.captureUnhandled ?? true,
|
|
450
|
+
traceFetch: resolveTraceFetch(options.traceFetch),
|
|
441
451
|
debug: options.debug ?? false
|
|
442
452
|
};
|
|
443
453
|
}
|
|
@@ -505,6 +515,7 @@ var IDENTIFIER = "[A-Za-z_$][\\w$]*";
|
|
|
505
515
|
var MAX_LINES_UP = 400;
|
|
506
516
|
var MAX_HEADER_LINES = 6;
|
|
507
517
|
var MAX_NAME_LENGTH = 100;
|
|
518
|
+
var MAX_COMMENT_LINES = 40;
|
|
508
519
|
var CONTROL_BLOCK = /^\s*(?:\}\s*)?(?:if|else|for|while|do|switch|try|catch|finally|with)\b/;
|
|
509
520
|
var CLASS_BODY = new RegExp(`\\bclass\\s+${IDENTIFIER}`);
|
|
510
521
|
var MARKUP_BOUNDARY = /<\/?(?:script|style|template)\b/i;
|
|
@@ -517,8 +528,58 @@ var NAME_PATTERNS = [
|
|
|
517
528
|
];
|
|
518
529
|
var METHOD_PATTERN = new RegExp(`^\\s*(?:(?:export|default|public|private|protected|static|async|override|readonly|get|set)\\s+)*\\*?\\s*(${IDENTIFIER})\\s*(?:<[^>]*>)?\\s*\\([^]*\\)\\s*(?::\\s*[^{]+)?$`);
|
|
519
530
|
var ANONYMOUS_FUNCTION = /\bfunction\b|=>/;
|
|
520
|
-
|
|
521
|
-
|
|
531
|
+
var STRING_LITERAL = /(["'`])(?:\\.|(?!\1)[^\\])*\1/g;
|
|
532
|
+
function lineCommentAt(text, from) {
|
|
533
|
+
for (let index = text.indexOf("//", from); index >= 0; index = text.indexOf("//", index + 1)) {
|
|
534
|
+
if (index === 0 || text[index - 1] !== ":") return index;
|
|
535
|
+
}
|
|
536
|
+
return -1;
|
|
537
|
+
}
|
|
538
|
+
function blockCommentAt(text, from) {
|
|
539
|
+
for (let index = text.indexOf("/*", from); index >= 0; index = text.indexOf("/*", index + 1)) {
|
|
540
|
+
if (index === 0 || text[index - 1] !== "\\") return index;
|
|
541
|
+
}
|
|
542
|
+
return -1;
|
|
543
|
+
}
|
|
544
|
+
function stripComments(text, insideComment, closesLater) {
|
|
545
|
+
let code = "";
|
|
546
|
+
let position = 0;
|
|
547
|
+
let inside = insideComment;
|
|
548
|
+
while (position < text.length) {
|
|
549
|
+
if (inside) {
|
|
550
|
+
const end = text.indexOf("*/", position);
|
|
551
|
+
if (end < 0) return { code, insideComment: true };
|
|
552
|
+
inside = false;
|
|
553
|
+
position = end + 2;
|
|
554
|
+
continue;
|
|
555
|
+
}
|
|
556
|
+
const block = blockCommentAt(text, position);
|
|
557
|
+
const line = lineCommentAt(text, position);
|
|
558
|
+
if (line >= 0 && (block < 0 || line < block)) return { code: code + text.slice(position, line), insideComment: false };
|
|
559
|
+
if (block < 0) return { code: code + text.slice(position), insideComment: false };
|
|
560
|
+
if (text.indexOf("*/", block + 2) < 0 && !closesLater()) {
|
|
561
|
+
code += text.slice(position, block + 2);
|
|
562
|
+
position = block + 2;
|
|
563
|
+
continue;
|
|
564
|
+
}
|
|
565
|
+
code += text.slice(position, block);
|
|
566
|
+
inside = true;
|
|
567
|
+
position = block + 2;
|
|
568
|
+
}
|
|
569
|
+
return { code, insideComment: inside };
|
|
570
|
+
}
|
|
571
|
+
function codeLines(lines, from, start, column) {
|
|
572
|
+
const plain = lines.slice(from, start + 1).map((line) => line.replace(STRING_LITERAL, '""'));
|
|
573
|
+
const closesWithin = (index) => plain.slice(index + 1, index + 1 + MAX_COMMENT_LINES).some((line) => line.includes("*/"));
|
|
574
|
+
const result = [];
|
|
575
|
+
let insideComment = false;
|
|
576
|
+
for (let index = 0; index < plain.length; index++) {
|
|
577
|
+
const text = index === plain.length - 1 && column ? (lines[start] ?? "").slice(0, Math.max(0, column - 1)).replace(STRING_LITERAL, '""') : plain[index] ?? "";
|
|
578
|
+
const stripped = stripComments(text, insideComment, () => closesWithin(index));
|
|
579
|
+
insideComment = stripped.insideComment;
|
|
580
|
+
result.push(stripped.code);
|
|
581
|
+
}
|
|
582
|
+
return result;
|
|
522
583
|
}
|
|
523
584
|
function parenBalance(text) {
|
|
524
585
|
let balance = 0;
|
|
@@ -528,11 +589,11 @@ function parenBalance(text) {
|
|
|
528
589
|
}
|
|
529
590
|
return balance;
|
|
530
591
|
}
|
|
531
|
-
function headerOf(
|
|
592
|
+
function headerOf(code, index, prefix) {
|
|
532
593
|
let header = prefix;
|
|
533
594
|
for (let previous = index - 1; previous >= 0 && previous >= index - MAX_HEADER_LINES; previous--) {
|
|
534
595
|
if (header.trim() !== "" && parenBalance(header) >= 0) break;
|
|
535
|
-
header = `${
|
|
596
|
+
header = `${code[previous] ?? ""} ${header}`;
|
|
536
597
|
}
|
|
537
598
|
return header;
|
|
538
599
|
}
|
|
@@ -547,11 +608,12 @@ function nameIn(header) {
|
|
|
547
608
|
function enclosingFunctionName(lines, line, column) {
|
|
548
609
|
const start = line - 1;
|
|
549
610
|
if (start < 0 || start >= lines.length) return void 0;
|
|
611
|
+
const from = Math.max(0, start - MAX_LINES_UP - MAX_HEADER_LINES);
|
|
612
|
+
const cleaned = codeLines(lines, from, start, column);
|
|
550
613
|
let depth = 0;
|
|
551
614
|
for (let index = start; index >= 0 && index >= start - MAX_LINES_UP; index--) {
|
|
552
|
-
|
|
553
|
-
|
|
554
|
-
const code = codeOnly(index === start && column ? raw.slice(0, Math.max(0, column - 1)) : raw);
|
|
615
|
+
if (index < start && MARKUP_BOUNDARY.test(lines[index] ?? "")) return void 0;
|
|
616
|
+
const code = cleaned[index - from] ?? "";
|
|
555
617
|
for (let position = code.length - 1; position >= 0; position--) {
|
|
556
618
|
const char = code[position];
|
|
557
619
|
if (char === "}") {
|
|
@@ -561,7 +623,7 @@ function enclosingFunctionName(lines, line, column) {
|
|
|
561
623
|
depth -= 1;
|
|
562
624
|
continue;
|
|
563
625
|
}
|
|
564
|
-
const header = headerOf(
|
|
626
|
+
const header = headerOf(cleaned, index - from, code.slice(0, position));
|
|
565
627
|
if (CLASS_BODY.test(header)) return void 0;
|
|
566
628
|
if (CONTROL_BLOCK.test(header)) continue;
|
|
567
629
|
const name = nameIn(header);
|
|
@@ -826,10 +888,6 @@ function safeStringify(value) {
|
|
|
826
888
|
}
|
|
827
889
|
}
|
|
828
890
|
|
|
829
|
-
// src/transport.ts
|
|
830
|
-
var import_node_util2 = require("util");
|
|
831
|
-
var import_node_zlib = require("zlib");
|
|
832
|
-
|
|
833
891
|
// src/util.ts
|
|
834
892
|
var import_node_perf_hooks2 = require("perf_hooks");
|
|
835
893
|
function describeError(error) {
|
|
@@ -839,7 +897,101 @@ function elapsedSince(startedAt) {
|
|
|
839
897
|
return Math.round(import_node_perf_hooks2.performance.now() - startedAt);
|
|
840
898
|
}
|
|
841
899
|
|
|
900
|
+
// src/trace-fetch.ts
|
|
901
|
+
var WRAPPED = /* @__PURE__ */ Symbol.for("@oconde/radar.fetch");
|
|
902
|
+
var REQUEST_ID_HEADER = "x-request-id";
|
|
903
|
+
var UUID = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;
|
|
904
|
+
var TELEGRAM_BOT = /^bot\d{5,}:[\w-]{20,}$/;
|
|
905
|
+
var TOKEN_LIKE = /^[\w\-.~+=]{20,}$/;
|
|
906
|
+
function secretSegment(segment) {
|
|
907
|
+
if (UUID.test(segment)) return false;
|
|
908
|
+
if (TELEGRAM_BOT.test(segment) || looksLikeCredential(segment)) return true;
|
|
909
|
+
return TOKEN_LIKE.test(segment) && /[A-Za-z]/.test(segment) && /\d/.test(segment);
|
|
910
|
+
}
|
|
911
|
+
function outboundPath(pathname, mode) {
|
|
912
|
+
if (mode === "none") return pathname;
|
|
913
|
+
return pathname.split("/").map((segment) => {
|
|
914
|
+
let decoded = segment;
|
|
915
|
+
try {
|
|
916
|
+
decoded = decodeURIComponent(segment);
|
|
917
|
+
} catch {
|
|
918
|
+
decoded = segment;
|
|
919
|
+
}
|
|
920
|
+
return secretSegment(decoded) ? maskValue(decoded, false) : segment;
|
|
921
|
+
}).join("/");
|
|
922
|
+
}
|
|
923
|
+
function failureOf(error) {
|
|
924
|
+
const message = describeError(error);
|
|
925
|
+
const cause = error instanceof Error ? error.cause : void 0;
|
|
926
|
+
const detail = typeof cause?.code === "string" ? cause.code : typeof cause?.message === "string" ? cause.message : "";
|
|
927
|
+
return detail && !message.includes(detail) ? `${message} (${detail})` : message;
|
|
928
|
+
}
|
|
929
|
+
function urlOf(input) {
|
|
930
|
+
try {
|
|
931
|
+
if (typeof input === "string") return new URL(input);
|
|
932
|
+
if (input instanceof URL) return input;
|
|
933
|
+
return new URL(input.url);
|
|
934
|
+
} catch {
|
|
935
|
+
return null;
|
|
936
|
+
}
|
|
937
|
+
}
|
|
938
|
+
function originOf(value) {
|
|
939
|
+
try {
|
|
940
|
+
return new URL(value).origin;
|
|
941
|
+
} catch {
|
|
942
|
+
return null;
|
|
943
|
+
}
|
|
944
|
+
}
|
|
945
|
+
function targets(url, target) {
|
|
946
|
+
if (target instanceof RegExp) return target.test(url.host);
|
|
947
|
+
const wanted = target.trim().toLowerCase();
|
|
948
|
+
if (wanted.startsWith(".")) return url.hostname.toLowerCase().endsWith(wanted);
|
|
949
|
+
return url.host.toLowerCase() === wanted || url.hostname.toLowerCase() === wanted;
|
|
950
|
+
}
|
|
951
|
+
function isPlainObject(value) {
|
|
952
|
+
if (value === null || typeof value !== "object") return false;
|
|
953
|
+
const prototype = Object.getPrototypeOf(value);
|
|
954
|
+
return prototype === Object.prototype || prototype === null;
|
|
955
|
+
}
|
|
956
|
+
function withRequestId(input, init, requestId) {
|
|
957
|
+
const headers = new Headers(init?.headers ?? (input instanceof Request ? input.headers : void 0));
|
|
958
|
+
if (headers.has(REQUEST_ID_HEADER)) return [input, init];
|
|
959
|
+
headers.set(REQUEST_ID_HEADER, requestId);
|
|
960
|
+
if (init === void 0 || isPlainObject(init)) return [input, { ...init, headers }];
|
|
961
|
+
return [new Request(input, init), { headers }];
|
|
962
|
+
}
|
|
963
|
+
function traceFetch(config) {
|
|
964
|
+
const current = globalThis.fetch;
|
|
965
|
+
if (typeof current !== "function" || current[WRAPPED]) return () => void 0;
|
|
966
|
+
const original = current;
|
|
967
|
+
const radarOrigin = originOf(config.endpoint);
|
|
968
|
+
const traced = async (input, init) => {
|
|
969
|
+
const url = urlOf(input);
|
|
970
|
+
if (!url || url.origin === radarOrigin || url.protocol !== "http:" && url.protocol !== "https:") return original(input, init);
|
|
971
|
+
const method = (init?.method ?? (input instanceof Request ? input.method : "GET")).toUpperCase();
|
|
972
|
+
const context = currentContext();
|
|
973
|
+
const [nextInput, nextInit] = context && config.propagateTo.some((target) => targets(url, target)) ? withRequestId(input, init, context.requestId) : [input, init];
|
|
974
|
+
const attrs = { method, host: url.host, path: outboundPath(url.pathname, config.redact) };
|
|
975
|
+
const started = performance.now();
|
|
976
|
+
try {
|
|
977
|
+
const response = await original(nextInput, nextInit);
|
|
978
|
+
config.record(response.status >= 500 ? "error" : response.status >= 400 ? "warn" : "info", { ...attrs, status: response.status, durationMs: elapsedSince(started) });
|
|
979
|
+
return response;
|
|
980
|
+
} catch (error) {
|
|
981
|
+
config.record("error", { ...attrs, error: failureOf(error), durationMs: elapsedSince(started) });
|
|
982
|
+
throw error;
|
|
983
|
+
}
|
|
984
|
+
};
|
|
985
|
+
Object.defineProperty(traced, WRAPPED, { value: original });
|
|
986
|
+
globalThis.fetch = traced;
|
|
987
|
+
return () => {
|
|
988
|
+
if (globalThis.fetch === traced) globalThis.fetch = original;
|
|
989
|
+
};
|
|
990
|
+
}
|
|
991
|
+
|
|
842
992
|
// src/transport.ts
|
|
993
|
+
var import_node_util2 = require("util");
|
|
994
|
+
var import_node_zlib = require("zlib");
|
|
843
995
|
var gzipAsync = (0, import_node_util2.promisify)(import_node_zlib.gzip);
|
|
844
996
|
var MAX_BATCH_BYTES = 9e5;
|
|
845
997
|
var GZIP_THRESHOLD_BYTES = 8192;
|
|
@@ -1067,7 +1219,7 @@ function withTimeout(promise, ms) {
|
|
|
1067
1219
|
|
|
1068
1220
|
// src/version.ts
|
|
1069
1221
|
var SDK_NAME = "@oconde/radar";
|
|
1070
|
-
var SDK_VERSION = true ? "0.
|
|
1222
|
+
var SDK_VERSION = true ? "0.3.0" : "0.0.0-dev";
|
|
1071
1223
|
|
|
1072
1224
|
// src/client.ts
|
|
1073
1225
|
var MAX_CHECK_IN_DURATION_MS = 7 * 864e5;
|
|
@@ -1079,6 +1231,7 @@ var RadarClient = class {
|
|
|
1079
1231
|
initialized = false;
|
|
1080
1232
|
closed = false;
|
|
1081
1233
|
captured = /* @__PURE__ */ new WeakSet();
|
|
1234
|
+
restoreFetch = null;
|
|
1082
1235
|
get isEnabled() {
|
|
1083
1236
|
return this.transport !== null && !this.closed;
|
|
1084
1237
|
}
|
|
@@ -1106,6 +1259,14 @@ var RadarClient = class {
|
|
|
1106
1259
|
});
|
|
1107
1260
|
}
|
|
1108
1261
|
if (this.options.captureUnhandled && (this.transport || this.options.console)) installProcessHandlers(this);
|
|
1262
|
+
if (this.options.traceFetch.enabled && (this.transport || this.options.console)) {
|
|
1263
|
+
this.restoreFetch = traceFetch({
|
|
1264
|
+
endpoint: this.options.endpoint,
|
|
1265
|
+
propagateTo: this.options.traceFetch.propagateTo,
|
|
1266
|
+
redact: this.options.redact,
|
|
1267
|
+
record: (level, attrs) => this.safely(() => this.emitLog(level, "http.client", attrs))
|
|
1268
|
+
});
|
|
1269
|
+
}
|
|
1109
1270
|
} catch (error) {
|
|
1110
1271
|
this.debugWarn(`radar.init falhou: ${describeError(error)}`);
|
|
1111
1272
|
}
|
|
@@ -1242,6 +1403,8 @@ var RadarClient = class {
|
|
|
1242
1403
|
async close(timeoutMs = 2e3) {
|
|
1243
1404
|
if (this.closed) return;
|
|
1244
1405
|
await this.flush(timeoutMs);
|
|
1406
|
+
this.restoreFetch?.();
|
|
1407
|
+
this.restoreFetch = null;
|
|
1245
1408
|
this.closed = true;
|
|
1246
1409
|
this.transport?.stop();
|
|
1247
1410
|
}
|
|
@@ -1625,7 +1788,7 @@ function contextFor2(event, chooseRequestId) {
|
|
|
1625
1788
|
const chosen = chooseRequestId?.(event);
|
|
1626
1789
|
return { requestId: requestIdFrom(chosen || event.request.headers.get("x-request-id")), startedAt: import_node_perf_hooks4.performance.now(), req, ...route ? { route } : {} };
|
|
1627
1790
|
}
|
|
1628
|
-
function
|
|
1791
|
+
function withRequestId2(response, requestId) {
|
|
1629
1792
|
try {
|
|
1630
1793
|
response.headers.set("x-request-id", requestId);
|
|
1631
1794
|
return response;
|
|
@@ -1657,7 +1820,7 @@ function radarHandle(options = {}) {
|
|
|
1657
1820
|
if (client.shouldLogRequest(req)) client.logHttpRequest(context, 500);
|
|
1658
1821
|
throw error;
|
|
1659
1822
|
}
|
|
1660
|
-
const tagged =
|
|
1823
|
+
const tagged = withRequestId2(response, context.requestId);
|
|
1661
1824
|
if (client.shouldLogRequest(req)) client.logHttpRequest(context, tagged.status);
|
|
1662
1825
|
return tagged;
|
|
1663
1826
|
});
|