@cross-deck/node 1.1.0 → 1.1.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.mjs CHANGED
@@ -1037,13 +1037,21 @@ function isInAppFrame(filename) {
1037
1037
  if (/^internal[\\/]/.test(filename)) return false;
1038
1038
  return true;
1039
1039
  }
1040
- function fingerprintError(message, frames) {
1040
+ function fingerprintError(message, frames, location) {
1041
1041
  const inAppFrames = frames.filter((f) => f.in_app).slice(0, 3);
1042
- const key = [
1042
+ const parts = [
1043
1043
  (message || "").slice(0, 200),
1044
1044
  ...inAppFrames.map((f) => `${f.function}@${f.filename}:${f.lineno}`)
1045
- ].join("|");
1046
- return djb2Hex(key);
1045
+ ];
1046
+ if (inAppFrames.length === 0 && location) {
1047
+ const loc = [
1048
+ location.errorType ?? "",
1049
+ location.filename ?? "",
1050
+ location.lineno ?? ""
1051
+ ].join(":");
1052
+ if (loc !== "::") parts.push(loc);
1053
+ }
1054
+ return djb2Hex(parts.join("|"));
1047
1055
  }
1048
1056
  function djb2Hex(input) {
1049
1057
  let h = 5381;
@@ -1274,34 +1282,30 @@ var ErrorTracker = class {
1274
1282
  * runtime-agnostic.
1275
1283
  */
1276
1284
  buildFromUnknown(err, kind, level) {
1277
- if (err instanceof Error) {
1278
- const frames = parseStack(err.stack);
1279
- return {
1280
- timestamp: Date.now(),
1281
- kind,
1282
- level,
1283
- message: String(err.message).slice(0, 1024),
1284
- errorType: err.name,
1285
- frames,
1286
- rawStack: err.stack ?? null,
1287
- fingerprint: fingerprintError(err.message, frames),
1288
- breadcrumbs: this.opts.breadcrumbs.snapshot(),
1289
- context: this.opts.getContext(),
1290
- tags: this.opts.getTags()
1291
- };
1292
- }
1293
- const message = safeStringify3(err).slice(0, 1024);
1285
+ const payload = coerceErrorPayload(err);
1286
+ const message = (payload.message || "Unknown error").slice(0, 1024);
1287
+ const stack = err instanceof Error ? err.stack ?? null : null;
1288
+ const frames = parseStack(stack);
1289
+ const errorType = payload.errorType ?? null;
1290
+ const context = payload.extras ? { ...this.opts.getContext(), __error_extras: payload.extras } : this.opts.getContext();
1294
1291
  return {
1295
1292
  timestamp: Date.now(),
1296
1293
  kind,
1297
1294
  level,
1298
1295
  message,
1299
- errorType: null,
1300
- frames: [],
1301
- rawStack: null,
1302
- fingerprint: fingerprintError(message, []),
1296
+ errorType,
1297
+ frames,
1298
+ rawStack: stack,
1299
+ // Location fallback ensures distinct call sites stay separate
1300
+ // even when the message is generic and there are no parseable
1301
+ // frames (e.g. `throw "boom"` from a middleware).
1302
+ fingerprint: fingerprintError(message, frames, {
1303
+ filename: frames[0]?.filename ?? null,
1304
+ lineno: frames[0]?.lineno ?? null,
1305
+ errorType
1306
+ }),
1303
1307
  breadcrumbs: this.opts.breadcrumbs.snapshot(),
1304
- context: this.opts.getContext(),
1308
+ context,
1305
1309
  tags: this.opts.getTags()
1306
1310
  };
1307
1311
  }
@@ -1316,7 +1320,10 @@ var ErrorTracker = class {
1316
1320
  errorType: "HTTPError",
1317
1321
  frames: [],
1318
1322
  rawStack: null,
1319
- fingerprint: fingerprintError(`HTTP ${info.status} ${info.method}`, []),
1323
+ fingerprint: fingerprintError(`HTTP ${info.status} ${info.method}`, [], {
1324
+ filename: info.url,
1325
+ errorType: "HTTPError"
1326
+ }),
1320
1327
  breadcrumbs: this.opts.breadcrumbs.snapshot(),
1321
1328
  context: this.opts.getContext(),
1322
1329
  tags: this.opts.getTags(),
@@ -1419,16 +1426,151 @@ var ErrorTracker = class {
1419
1426
  }
1420
1427
  }
1421
1428
  };
1422
- function safeStringify3(v) {
1423
- if (v == null) return String(v);
1424
- if (typeof v === "string") return v;
1425
- if (typeof v === "number" || typeof v === "boolean") return String(v);
1429
+ function coerceErrorPayload(v) {
1430
+ if (v === null) return { message: "(thrown: null)", errorType: null, extras: null };
1431
+ if (v === void 0) return { message: "(thrown: undefined)", errorType: null, extras: null };
1432
+ if (typeof v === "string") {
1433
+ return { message: v, errorType: null, extras: null };
1434
+ }
1435
+ if (typeof v === "number" || typeof v === "boolean" || typeof v === "bigint") {
1436
+ return { message: String(v), errorType: typeof v, extras: null };
1437
+ }
1438
+ if (typeof v === "symbol") {
1439
+ return { message: v.toString(), errorType: "symbol", extras: null };
1440
+ }
1441
+ if (typeof v === "function") {
1442
+ return { message: `(thrown function: ${v.name || "anonymous"})`, errorType: "function", extras: null };
1443
+ }
1444
+ if (v instanceof Error) {
1445
+ const errorType = v.name || v.constructor?.name || "Error";
1446
+ const message = typeof v.message === "string" && v.message.length > 0 ? v.message : safeToString(v) || errorType;
1447
+ const extras = {};
1448
+ const causeChain = collectCauseChain(v);
1449
+ if (causeChain.length > 0) extras.cause = causeChain;
1450
+ const aggErrors = v.errors;
1451
+ if (Array.isArray(aggErrors)) {
1452
+ extras.aggregatedErrors = aggErrors.slice(0, 10).map((inner) => {
1453
+ if (inner instanceof Error) {
1454
+ return { name: inner.name || "Error", message: inner.message || "" };
1455
+ }
1456
+ return { name: "non-Error", message: safeToString(inner) };
1457
+ });
1458
+ }
1459
+ for (const key of [
1460
+ "code",
1461
+ "errno",
1462
+ "syscall",
1463
+ "path",
1464
+ "status",
1465
+ "statusCode",
1466
+ "response",
1467
+ "data",
1468
+ "detail",
1469
+ "details"
1470
+ ]) {
1471
+ const val = v[key];
1472
+ if (val !== void 0 && typeof val !== "function") {
1473
+ extras[key] = safeClone(val);
1474
+ }
1475
+ }
1476
+ for (const key of Object.keys(v)) {
1477
+ if (key === "message" || key === "stack" || key === "name" || key === "cause" || key === "errors") continue;
1478
+ if (key in extras) continue;
1479
+ const val = v[key];
1480
+ if (typeof val === "function") continue;
1481
+ extras[key] = safeClone(val);
1482
+ }
1483
+ return {
1484
+ message,
1485
+ errorType,
1486
+ extras: Object.keys(extras).length > 0 ? extras : null
1487
+ };
1488
+ }
1489
+ if (typeof Response !== "undefined" && v instanceof Response) {
1490
+ return {
1491
+ message: `HTTP ${v.status} ${v.statusText || ""}${v.url ? ` ${v.url}` : ""}`.trim(),
1492
+ errorType: "Response",
1493
+ extras: { status: v.status, statusText: v.statusText, url: v.url, type: v.type }
1494
+ };
1495
+ }
1496
+ if (typeof v === "object") {
1497
+ const obj = v;
1498
+ const ctorName = obj.constructor && typeof obj.constructor === "function" && obj.constructor.name || null;
1499
+ const ownMessage = typeof obj.message === "string" && obj.message ? obj.message : null;
1500
+ const ownName = typeof obj.name === "string" && obj.name ? obj.name : null;
1501
+ let jsonForm = null;
1502
+ try {
1503
+ const serialised = JSON.stringify(obj);
1504
+ jsonForm = serialised === "{}" ? null : serialised;
1505
+ } catch {
1506
+ jsonForm = null;
1507
+ }
1508
+ const fallbackString = safeToString(obj);
1509
+ const message = ownMessage ?? jsonForm ?? (fallbackString && fallbackString !== "[object Object]" ? fallbackString : null) ?? (ctorName ? `(thrown ${ctorName} with no message)` : "(thrown object with no message)");
1510
+ const errorType = ownName ?? ctorName ?? null;
1511
+ const extras = {};
1512
+ let count = 0;
1513
+ for (const key of Object.keys(obj)) {
1514
+ if (count >= 20) break;
1515
+ if (key === "message" || key === "name") continue;
1516
+ const val = obj[key];
1517
+ if (typeof val === "function") continue;
1518
+ extras[key] = safeClone(val);
1519
+ count++;
1520
+ }
1521
+ return {
1522
+ message,
1523
+ errorType,
1524
+ extras: Object.keys(extras).length > 0 ? extras : null
1525
+ };
1526
+ }
1527
+ return { message: safeToString(v) || "(unstringifiable thrown value)", errorType: null, extras: null };
1528
+ }
1529
+ function collectCauseChain(err) {
1530
+ const out = [];
1531
+ let cur = err.cause;
1532
+ let depth = 0;
1533
+ while (cur != null && depth < 5) {
1534
+ if (cur instanceof Error) {
1535
+ out.push({ name: cur.name || "Error", message: cur.message || "" });
1536
+ cur = cur.cause;
1537
+ } else {
1538
+ out.push({ name: "non-Error", message: safeToString(cur) });
1539
+ cur = null;
1540
+ }
1541
+ depth++;
1542
+ }
1543
+ return out;
1544
+ }
1545
+ function safeToString(v) {
1546
+ try {
1547
+ const s = Object.prototype.toString.call(v);
1548
+ if (s !== "[object Object]") return s;
1549
+ const own = v?.toString;
1550
+ if (typeof own === "function" && own !== Object.prototype.toString) {
1551
+ const r = own.call(v);
1552
+ if (typeof r === "string") return r;
1553
+ }
1554
+ return s;
1555
+ } catch {
1556
+ return "(throwing toString)";
1557
+ }
1558
+ }
1559
+ function safeClone(v) {
1560
+ if (v == null) return v;
1561
+ const t = typeof v;
1562
+ if (t === "string" || t === "number" || t === "boolean") return v;
1563
+ if (t === "bigint") return String(v);
1426
1564
  try {
1427
- return JSON.stringify(v);
1565
+ const s = JSON.stringify(v);
1566
+ return s === void 0 ? safeToString(v) : JSON.parse(s);
1428
1567
  } catch {
1429
- return Object.prototype.toString.call(v);
1568
+ return safeToString(v);
1430
1569
  }
1431
1570
  }
1571
+ function safeStringify3(v) {
1572
+ return coerceErrorPayload(v).message;
1573
+ }
1432
1574
 
1433
1575
  // src/runtime-info.ts
1434
1576
  import { hostname as osHostname, platform as osPlatform, release as osRelease } from "os";