@stainlessdev/xray-emitter 0.3.1 → 0.4.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.
Files changed (75) hide show
  1. package/dist/{chunk-FGXXKIF7.js → chunk-447Z3SDN.js} +4 -4
  2. package/dist/{chunk-GYXI3DWB.js → chunk-7EKBXVZE.js} +59 -12
  3. package/dist/chunk-7EKBXVZE.js.map +1 -0
  4. package/dist/{chunk-NTIUR3OC.js → chunk-AKPTTC2I.js} +2 -2
  5. package/dist/{chunk-7KT6EPVZ.js → chunk-BKJO3FLI.js} +1 -1
  6. package/dist/{chunk-7KT6EPVZ.js.map → chunk-BKJO3FLI.js.map} +1 -1
  7. package/dist/{chunk-DNBARLGB.cjs → chunk-EPQTFPT7.cjs} +1 -1
  8. package/dist/{chunk-DNBARLGB.cjs.map → chunk-EPQTFPT7.cjs.map} +1 -1
  9. package/dist/{chunk-SUVCVINA.cjs → chunk-FZH3IY6R.cjs} +47 -47
  10. package/dist/{chunk-SUVCVINA.cjs.map → chunk-FZH3IY6R.cjs.map} +1 -1
  11. package/dist/{chunk-UJWD5CFA.cjs → chunk-IEWCR3GT.cjs} +86 -39
  12. package/dist/chunk-IEWCR3GT.cjs.map +1 -0
  13. package/dist/{chunk-CPHFCOA5.cjs → chunk-M6G4PEGF.cjs} +9 -9
  14. package/dist/{chunk-CPHFCOA5.cjs.map → chunk-M6G4PEGF.cjs.map} +1 -1
  15. package/dist/{chunk-55YD27PV.cjs → chunk-PIY7CFHY.cjs} +28 -28
  16. package/dist/{chunk-55YD27PV.cjs.map → chunk-PIY7CFHY.cjs.map} +1 -1
  17. package/dist/{chunk-DV3MVQBB.js → chunk-W42SQZKN.js} +4 -4
  18. package/dist/effect.cjs +19 -19
  19. package/dist/effect.d.cts +3 -3
  20. package/dist/effect.d.ts +3 -3
  21. package/dist/effect.js +4 -4
  22. package/dist/{emitter-Bi_m_w5h.d.cts → emitter-DKki0zYl.d.cts} +1 -1
  23. package/dist/{emitter-Dy7bRGTq.d.ts → emitter-DT-EuB8s.d.ts} +1 -1
  24. package/dist/express.cjs +7 -7
  25. package/dist/express.d.cts +2 -2
  26. package/dist/express.d.ts +2 -2
  27. package/dist/express.js +4 -4
  28. package/dist/fastify.cjs +10 -10
  29. package/dist/fastify.d.cts +2 -2
  30. package/dist/fastify.d.ts +2 -2
  31. package/dist/fastify.js +4 -4
  32. package/dist/fetch.cjs +5 -5
  33. package/dist/fetch.d.cts +2 -2
  34. package/dist/fetch.d.ts +2 -2
  35. package/dist/fetch.js +4 -4
  36. package/dist/hono.cjs +9 -9
  37. package/dist/hono.d.cts +3 -3
  38. package/dist/hono.d.ts +3 -3
  39. package/dist/hono.js +4 -4
  40. package/dist/index.cjs +3 -3
  41. package/dist/index.d.cts +2 -2
  42. package/dist/index.d.ts +2 -2
  43. package/dist/index.js +2 -2
  44. package/dist/internal.cjs +3 -3
  45. package/dist/internal.d.cts +1 -1
  46. package/dist/internal.d.ts +1 -1
  47. package/dist/internal.js +2 -2
  48. package/dist/next.cjs +42 -8
  49. package/dist/next.cjs.map +1 -1
  50. package/dist/next.d.cts +3 -3
  51. package/dist/next.d.ts +3 -3
  52. package/dist/next.js +39 -5
  53. package/dist/next.js.map +1 -1
  54. package/dist/node.cjs +5 -5
  55. package/dist/node.d.cts +1 -1
  56. package/dist/node.d.ts +1 -1
  57. package/dist/node.js +4 -4
  58. package/dist/remix.cjs +7 -7
  59. package/dist/remix.d.cts +3 -3
  60. package/dist/remix.d.ts +3 -3
  61. package/dist/remix.js +4 -4
  62. package/dist/stub.cjs +121 -0
  63. package/dist/stub.cjs.map +1 -0
  64. package/dist/stub.d.cts +12 -0
  65. package/dist/stub.d.ts +12 -0
  66. package/dist/stub.js +121 -0
  67. package/dist/stub.js.map +1 -0
  68. package/dist/{types-BrKvhHbn.d.cts → types-C44Eg-i_.d.cts} +6 -2
  69. package/dist/{types-BrKvhHbn.d.ts → types-C44Eg-i_.d.ts} +6 -2
  70. package/package.json +10 -3
  71. package/dist/chunk-GYXI3DWB.js.map +0 -1
  72. package/dist/chunk-UJWD5CFA.cjs.map +0 -1
  73. /package/dist/{chunk-FGXXKIF7.js.map → chunk-447Z3SDN.js.map} +0 -0
  74. /package/dist/{chunk-NTIUR3OC.js.map → chunk-AKPTTC2I.js.map} +0 -0
  75. /package/dist/{chunk-DV3MVQBB.js.map → chunk-W42SQZKN.js.map} +0 -0
@@ -6,7 +6,7 @@
6
6
 
7
7
 
8
8
 
9
- var _chunkDNBARLGBcjs = require('./chunk-DNBARLGB.cjs');
9
+ var _chunkEPQTFPT7cjs = require('./chunk-EPQTFPT7.cjs');
10
10
 
11
11
  // src/core/route.ts
12
12
  function normalizeRoutePattern(route) {
@@ -214,11 +214,12 @@ function normalizeExporter(endpointUrl, cfg) {
214
214
  const resolvedEndpoint = normalizeExporterEndpoint(_nullishCoalesce(_optionalChain([cfg, 'optionalAccess', _8 => _8.endpointUrl]), () => ( endpointUrl)));
215
215
  const rawHeaders = _nullishCoalesce(_nullishCoalesce(_optionalChain([cfg, 'optionalAccess', _9 => _9.headers]), () => ( defaultExporterBase.headers)), () => ( {}));
216
216
  const parsed = applyEndpointAuth(resolvedEndpoint, rawHeaders);
217
+ const spanProcessor = resolveSpanProcessor(_optionalChain([cfg, 'optionalAccess', _10 => _10.spanProcessor]));
217
218
  const exporter = {
218
219
  endpointUrl: parsed.endpointUrl,
219
220
  headers: parsed.headers,
220
- timeoutMs: _nullishCoalesce(_optionalChain([cfg, 'optionalAccess', _10 => _10.timeoutMs]), () => ( defaultExporterBase.timeoutMs)),
221
- spanProcessor: _nullishCoalesce(_optionalChain([cfg, 'optionalAccess', _11 => _11.spanProcessor]), () => ( defaultExporterBase.spanProcessor))
221
+ timeoutMs: _nullishCoalesce(_optionalChain([cfg, 'optionalAccess', _11 => _11.timeoutMs]), () => ( defaultExporterBase.timeoutMs)),
222
+ spanProcessor
222
223
  };
223
224
  return exporter;
224
225
  }
@@ -244,6 +245,22 @@ function normalizeStringList(values) {
244
245
  }
245
246
  return values.map((entry) => entry.trim()).filter(Boolean);
246
247
  }
248
+ function resolveSpanProcessor(configured) {
249
+ if (configured) {
250
+ return configured;
251
+ }
252
+ const envProcessor = typeof process !== "undefined" ? _optionalChain([process, 'access', _14 => _14.env, 'optionalAccess', _15 => _15["STAINLESS_XRAY_SPAN_PROCESSOR"]]) : void 0;
253
+ if (!envProcessor) {
254
+ return defaultExporterBase.spanProcessor;
255
+ }
256
+ if (envProcessor === "simple" || envProcessor === "batch") {
257
+ return envProcessor;
258
+ }
259
+ throw new XrayConfigError(
260
+ "INVALID_CONFIG",
261
+ 'STAINLESS_XRAY_SPAN_PROCESSOR must be "simple" or "batch"'
262
+ );
263
+ }
247
264
  var textEncoder = typeof TextEncoder !== "undefined" ? new TextEncoder() : null;
248
265
  var maybeBuffer = globalThis.Buffer;
249
266
  function applyEndpointAuth(endpointUrl, headers) {
@@ -301,7 +318,7 @@ function encodeBasicAuth(username, password) {
301
318
  if (!bytes) {
302
319
  return void 0;
303
320
  }
304
- const encoded = _chunkDNBARLGBcjs.encodeBase64.call(void 0, bytes);
321
+ const encoded = _chunkEPQTFPT7cjs.encodeBase64.call(void 0, bytes);
305
322
  if (!encoded) {
306
323
  return void 0;
307
324
  }
@@ -680,6 +697,7 @@ var AttributeKeyResponseBody = "http.response.body";
680
697
  var AttributeKeyResponseBodyEncoding = "http.response.body.encoding";
681
698
  var AttributeKeyResponseBodyTruncated = "http.response.body.truncated";
682
699
  var AttributeKeySpanDrop = "stainlessxray.internal.drop";
700
+ var AttributeKeyTags = "stainlessxray.internal.tags";
683
701
  var AttributeKeyTenantID = "stainlessxray.tenant.id";
684
702
 
685
703
  // src/core/attributes.ts
@@ -720,7 +738,7 @@ function extractPath(url) {
720
738
  return new URL(url).pathname;
721
739
  } catch (e5) {
722
740
  const match = url.match(/^[^?#]*/);
723
- return _optionalChain([match, 'optionalAccess', _14 => _14[0]]) || void 0;
741
+ return _optionalChain([match, 'optionalAccess', _16 => _16[0]]) || void 0;
724
742
  }
725
743
  }
726
744
  function clientAddressForRequest(headers, remoteAddress, redactionReplacement) {
@@ -904,6 +922,36 @@ function setTenantIdAttribute(span, tenantId) {
904
922
  function setRequestIdAttribute(span, requestId) {
905
923
  span.setAttribute(AttributeKeyRequestID, requestId);
906
924
  }
925
+ function setTagsAttribute(span, tags) {
926
+ const safe = /* @__PURE__ */ Object.create(null);
927
+ for (const key of Object.keys(tags)) {
928
+ const v = tags[key];
929
+ if (isJSONSafe(v)) {
930
+ safe[key] = v;
931
+ }
932
+ }
933
+ span.setAttribute(AttributeKeyTags, JSON.stringify(safe));
934
+ }
935
+ function isJSONSafe(value, seen) {
936
+ if (value === null || value === void 0) {
937
+ return false;
938
+ }
939
+ const t = typeof value;
940
+ if (t === "string" || t === "number" || t === "boolean") {
941
+ return true;
942
+ }
943
+ if (Array.isArray(value)) {
944
+ if (!seen) {
945
+ seen = /* @__PURE__ */ new Set();
946
+ }
947
+ if (seen.has(value)) {
948
+ return false;
949
+ }
950
+ seen.add(value);
951
+ return value.every((el) => isJSONSafe(el, seen));
952
+ }
953
+ return false;
954
+ }
907
955
 
908
956
  // src/core/otel.ts
909
957
 
@@ -1014,7 +1062,7 @@ function sdkVersion() {
1014
1062
  }
1015
1063
  function isNodeRuntime() {
1016
1064
  const maybeProcess = globalThis.process;
1017
- return !!_optionalChain([maybeProcess, 'optionalAccess', _15 => _15.versions, 'optionalAccess', _16 => _16.node]);
1065
+ return !!_optionalChain([maybeProcess, 'optionalAccess', _17 => _17.versions, 'optionalAccess', _18 => _18.node]);
1018
1066
  }
1019
1067
 
1020
1068
  // src/core/emitter.ts
@@ -1026,7 +1074,7 @@ function createEmitter(config, exporter) {
1026
1074
  "exporter is required (use @stainlessdev/xray-node or @stainlessdev/xray-fetch)"
1027
1075
  );
1028
1076
  }
1029
- _chunkDNBARLGBcjs.logWithLevel.call(void 0, resolved.logger, "info", resolved.logLevel, "xray: emitter configured", {
1077
+ _chunkEPQTFPT7cjs.logWithLevel.call(void 0, resolved.logger, "info", resolved.logLevel, "xray: emitter configured", {
1030
1078
  serviceName: resolved.serviceName,
1031
1079
  environment: resolved.environment,
1032
1080
  version: resolved.version,
@@ -1055,10 +1103,10 @@ function startRequest(config, tracer, req) {
1055
1103
  const span = spanFromTracer(tracer, spanNameFromRequest(req));
1056
1104
  const context = {
1057
1105
  requestId: _nullishCoalesce(explicitRequestId, () => ( "")),
1058
- traceId: _optionalChain([span, 'optionalAccess', _17 => _17.spanContext, 'call', _18 => _18(), 'access', _19 => _19.traceId]),
1059
- spanId: _optionalChain([span, 'optionalAccess', _20 => _20.spanContext, 'call', _21 => _21(), 'access', _22 => _22.spanId]),
1106
+ traceId: _optionalChain([span, 'optionalAccess', _19 => _19.spanContext, 'call', _20 => _20(), 'access', _21 => _21.traceId]),
1107
+ spanId: _optionalChain([span, 'optionalAccess', _22 => _22.spanContext, 'call', _23 => _23(), 'access', _24 => _24.spanId]),
1060
1108
  setActor: (tenantId, userId) => {
1061
- const state2 = _chunkDNBARLGBcjs.getContextState.call(void 0, context);
1109
+ const state2 = _chunkEPQTFPT7cjs.getContextState.call(void 0, context);
1062
1110
  if (!state2) {
1063
1111
  return;
1064
1112
  }
@@ -1071,7 +1119,7 @@ function startRequest(config, tracer, req) {
1071
1119
  setUserIdAttribute(span, userId);
1072
1120
  }
1073
1121
  } catch (err) {
1074
- _chunkDNBARLGBcjs.logWithLevel.call(void 0, config.logger, "error", config.logLevel, "xray: setActor failed", {
1122
+ _chunkEPQTFPT7cjs.logWithLevel.call(void 0, config.logger, "error", config.logLevel, "xray: setActor failed", {
1075
1123
  error: err instanceof Error ? err.message : String(err)
1076
1124
  });
1077
1125
  }
@@ -1079,7 +1127,7 @@ function startRequest(config, tracer, req) {
1079
1127
  },
1080
1128
  // Deprecated compatibility alias; prefer setActor(tenantId, userId).
1081
1129
  setUserId: (id) => {
1082
- const state2 = _chunkDNBARLGBcjs.getContextState.call(void 0, context);
1130
+ const state2 = _chunkEPQTFPT7cjs.getContextState.call(void 0, context);
1083
1131
  if (!state2) {
1084
1132
  return;
1085
1133
  }
@@ -1088,34 +1136,28 @@ function startRequest(config, tracer, req) {
1088
1136
  try {
1089
1137
  setUserIdAttribute(span, id);
1090
1138
  } catch (err) {
1091
- _chunkDNBARLGBcjs.logWithLevel.call(void 0, config.logger, "error", config.logLevel, "xray: setUserId failed", {
1139
+ _chunkEPQTFPT7cjs.logWithLevel.call(void 0, config.logger, "error", config.logLevel, "xray: setUserId failed", {
1092
1140
  error: err instanceof Error ? err.message : String(err)
1093
1141
  });
1094
1142
  }
1095
1143
  }
1096
1144
  },
1097
1145
  setSessionId: (id) => {
1098
- const state2 = _chunkDNBARLGBcjs.getContextState.call(void 0, context);
1146
+ const state2 = _chunkEPQTFPT7cjs.getContextState.call(void 0, context);
1099
1147
  if (!state2) {
1100
1148
  return;
1101
1149
  }
1102
1150
  state2.sessionId = id;
1103
1151
  },
1104
- setAttribute: (key, value) => {
1105
- const state2 = _chunkDNBARLGBcjs.getContextState.call(void 0, context);
1152
+ setTag: (key, value) => {
1153
+ const state2 = _chunkEPQTFPT7cjs.getContextState.call(void 0, context);
1106
1154
  if (!state2) {
1107
1155
  return;
1108
1156
  }
1109
- state2.attributes[key] = value;
1110
- if (span) {
1111
- try {
1112
- span.setAttribute(key, value);
1113
- } catch (e6) {
1114
- }
1115
- }
1157
+ state2.tags[key] = value;
1116
1158
  },
1117
1159
  addEvent: (name, attributes) => {
1118
- const state2 = _chunkDNBARLGBcjs.getContextState.call(void 0, context);
1160
+ const state2 = _chunkEPQTFPT7cjs.getContextState.call(void 0, context);
1119
1161
  if (!state2) {
1120
1162
  return;
1121
1163
  }
@@ -1123,12 +1165,12 @@ function startRequest(config, tracer, req) {
1123
1165
  if (span) {
1124
1166
  try {
1125
1167
  span.addEvent(name, attributes);
1126
- } catch (e7) {
1168
+ } catch (e6) {
1127
1169
  }
1128
1170
  }
1129
1171
  },
1130
1172
  setError: (err) => {
1131
- const state2 = _chunkDNBARLGBcjs.getContextState.call(void 0, context);
1173
+ const state2 = _chunkEPQTFPT7cjs.getContextState.call(void 0, context);
1132
1174
  if (!state2) {
1133
1175
  return;
1134
1176
  }
@@ -1136,7 +1178,7 @@ function startRequest(config, tracer, req) {
1136
1178
  if (span) {
1137
1179
  try {
1138
1180
  spanStatusFromError(span, err);
1139
- } catch (e8) {
1181
+ } catch (e7) {
1140
1182
  }
1141
1183
  }
1142
1184
  }
@@ -1147,13 +1189,14 @@ function startRequest(config, tracer, req) {
1147
1189
  span,
1148
1190
  context,
1149
1191
  attributes: {},
1150
- events: []
1192
+ events: [],
1193
+ tags: /* @__PURE__ */ Object.create(null)
1151
1194
  };
1152
- _chunkDNBARLGBcjs.bindContext.call(void 0, context, state);
1195
+ _chunkEPQTFPT7cjs.bindContext.call(void 0, context, state);
1153
1196
  return context;
1154
1197
  }
1155
1198
  function endRequest(config, ctx, res, err) {
1156
- const state = _chunkDNBARLGBcjs.getContextState.call(void 0, ctx);
1199
+ const state = _chunkEPQTFPT7cjs.getContextState.call(void 0, ctx);
1157
1200
  const endTimeMs = Number.isFinite(res.endTimeMs) ? res.endTimeMs : Date.now();
1158
1201
  res.endTimeMs = endTimeMs;
1159
1202
  if (!state) {
@@ -1181,19 +1224,19 @@ function endRequest(config, ctx, res, err) {
1181
1224
  const capture = resolveCapture(config.capture, state.captureOverride);
1182
1225
  const redaction = resolveRedaction(config.redaction, state.redactionOverride);
1183
1226
  const route = request.route;
1184
- const url = _chunkDNBARLGBcjs.sanitizeLogString.call(void 0, request.url);
1227
+ const url = _chunkEPQTFPT7cjs.sanitizeLogString.call(void 0, request.url);
1185
1228
  const log = {
1186
1229
  requestId: resolvedRequestId,
1187
- traceId: _optionalChain([state, 'access', _23 => _23.span, 'optionalAccess', _24 => _24.spanContext, 'call', _25 => _25(), 'access', _26 => _26.traceId]),
1188
- spanId: _optionalChain([state, 'access', _27 => _27.span, 'optionalAccess', _28 => _28.spanContext, 'call', _29 => _29(), 'access', _30 => _30.spanId]),
1230
+ traceId: _optionalChain([state, 'access', _25 => _25.span, 'optionalAccess', _26 => _26.spanContext, 'call', _27 => _27(), 'access', _28 => _28.traceId]),
1231
+ spanId: _optionalChain([state, 'access', _29 => _29.span, 'optionalAccess', _30 => _30.spanContext, 'call', _31 => _31(), 'access', _32 => _32.spanId]),
1189
1232
  serviceName: config.serviceName,
1190
1233
  method: request.method,
1191
1234
  url,
1192
1235
  route,
1193
1236
  statusCode: res.statusCode,
1194
1237
  durationMs: Math.max(0, endTimeMs - request.startTimeMs),
1195
- requestHeaders: capture.requestHeaders ? _chunkDNBARLGBcjs.sanitizeHeaderValues.call(void 0, request.headers) : void 0,
1196
- responseHeaders: capture.responseHeaders ? _chunkDNBARLGBcjs.sanitizeHeaderValues.call(void 0, res.headers) : void 0,
1238
+ requestHeaders: capture.requestHeaders ? _chunkEPQTFPT7cjs.sanitizeHeaderValues.call(void 0, request.headers) : void 0,
1239
+ responseHeaders: capture.responseHeaders ? _chunkEPQTFPT7cjs.sanitizeHeaderValues.call(void 0, res.headers) : void 0,
1197
1240
  requestBody: capture.requestBody === "none" ? void 0 : request.body,
1198
1241
  responseBody: capture.responseBody === "none" ? void 0 : res.body,
1199
1242
  tenantId: _nullishCoalesce(state.tenantId, () => ( void 0)),
@@ -1201,6 +1244,7 @@ function endRequest(config, ctx, res, err) {
1201
1244
  sessionId: _nullishCoalesce(state.sessionId, () => ( void 0)),
1202
1245
  error: buildError(_nullishCoalesce(err, () => ( state.error))),
1203
1246
  attributes: Object.keys(state.attributes).length > 0 ? { ...state.attributes } : void 0,
1247
+ tags: Object.keys(state.tags).length > 0 ? { ...state.tags } : void 0,
1204
1248
  timestamp: new Date(endTimeMs).toISOString()
1205
1249
  };
1206
1250
  const redacted = applyRedaction(redaction, log);
@@ -1252,12 +1296,15 @@ function endRequest(config, ctx, res, err) {
1252
1296
  if (state.userId) {
1253
1297
  setUserIdAttribute(span, state.userId);
1254
1298
  }
1299
+ if (Object.keys(state.tags).length > 0) {
1300
+ setTagsAttribute(span, state.tags);
1301
+ }
1255
1302
  if (_nullishCoalesce(err, () => ( state.error))) {
1256
1303
  spanStatusFromError(span, _nullishCoalesce(err, () => ( state.error)));
1257
1304
  }
1258
1305
  span.end();
1259
1306
  } catch (spanErr) {
1260
- _chunkDNBARLGBcjs.logWithLevel.call(void 0, config.logger, "warn", config.logLevel, "xray: span finalize failed", {
1307
+ _chunkEPQTFPT7cjs.logWithLevel.call(void 0, config.logger, "warn", config.logLevel, "xray: span finalize failed", {
1261
1308
  error: spanErr instanceof Error ? spanErr.message : String(spanErr)
1262
1309
  });
1263
1310
  }
@@ -1273,7 +1320,7 @@ function resolveFinalRequestId(config, explicitRequestId, responseHeaders) {
1273
1320
  if (headerValue) {
1274
1321
  return headerValue;
1275
1322
  }
1276
- return _chunkDNBARLGBcjs.generateRequestId.call(void 0, );
1323
+ return _chunkEPQTFPT7cjs.generateRequestId.call(void 0, );
1277
1324
  }
1278
1325
  function resolveHeaderRequestId(headerName, headers) {
1279
1326
  if (!headers) {
@@ -1358,7 +1405,7 @@ function safePath(url) {
1358
1405
  try {
1359
1406
  const parsed = new URL(url);
1360
1407
  return parsed.pathname || "/";
1361
- } catch (e9) {
1408
+ } catch (e8) {
1362
1409
  const rawPath = url.split("?")[0] || "/";
1363
1410
  return rawPath || "/";
1364
1411
  }
@@ -1369,4 +1416,4 @@ function safePath(url) {
1369
1416
 
1370
1417
 
1371
1418
  exports.XrayConfigError = XrayConfigError; exports.normalizeConfig = normalizeConfig; exports.createEmitter = createEmitter;
1372
- //# sourceMappingURL=chunk-UJWD5CFA.cjs.map
1419
+ //# sourceMappingURL=chunk-IEWCR3GT.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["/home/runner/work/xray-emitter-js/xray-emitter-js/dist/chunk-IEWCR3GT.cjs","../src/core/route.ts","../src/core/config.ts","../src/core/header_redaction.ts","../src/core/redaction.ts","../src/core/attributes.ts","../src/core/attrkey.ts","../src/core/otel.ts","../src/core/emitter.ts"],"names":["resolvedRequestId"],"mappings":"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","file":"/home/runner/work/xray-emitter-js/xray-emitter-js/dist/chunk-IEWCR3GT.cjs","sourcesContent":[null,"export function normalizeRoutePattern(route: string): string {\n if (!route) {\n return '/';\n }\n\n const cleaned = stripQueryAndFragment(route).trim();\n if (!cleaned) {\n return '/';\n }\n\n const withoutMethod = stripMethodPrefix(cleaned);\n const leading = withoutMethod.startsWith('/') ? withoutMethod : `/${withoutMethod}`;\n const segments = leading.split('/').filter(Boolean);\n if (segments.length === 0) {\n return '/';\n }\n\n const normalized = segments.map(normalizeRouteSegment).join('/');\n return `/${normalized}`;\n}\n\nfunction stripMethodPrefix(value: string): string {\n if (!/^[A-Z]+\\s+\\//.test(value)) {\n return value;\n }\n const spaceIndex = value.search(/\\s+/);\n if (spaceIndex < 0) {\n return value;\n }\n return value.slice(spaceIndex).trim();\n}\n\nfunction stripQueryAndFragment(value: string): string {\n const hashIndex = value.indexOf('#');\n const beforeHash = hashIndex >= 0 ? value.slice(0, hashIndex) : value;\n const queryIndex = beforeHash.indexOf('?');\n return queryIndex >= 0 ? beforeHash.slice(0, queryIndex) : beforeHash;\n}\n\nfunction normalizeRouteSegment(segment: string): string {\n if (segment === '*') {\n return '{wildcard}';\n }\n\n const param = extractRouteParam(segment);\n if (param) {\n return `{${param}}`;\n }\n\n return segment;\n}\n\nfunction extractRouteParam(segment: string): string | null {\n if (!segment) {\n return null;\n }\n\n if (segment.startsWith('[') && segment.endsWith(']')) {\n return normalizeNextParam(segment);\n }\n\n if (segment.startsWith('{') && segment.endsWith('}')) {\n const inner = segment.slice(1, -1);\n const trimmed = stripParamDecorators(inner);\n return extractParamName(trimmed);\n }\n\n if (segment.startsWith(':') || segment.startsWith('$')) {\n return extractParamName(segment.slice(1));\n }\n\n return null;\n}\n\nfunction normalizeNextParam(segment: string): string | null {\n let inner = segment.slice(1, -1);\n if (inner.startsWith('[') && inner.endsWith(']')) {\n inner = inner.slice(1, -1);\n }\n if (inner.startsWith('...')) {\n inner = inner.slice(3);\n }\n return extractParamName(inner);\n}\n\nfunction stripParamDecorators(value: string): string {\n let trimmed = value.trim();\n if (!trimmed) {\n return trimmed;\n }\n if (trimmed.endsWith('...')) {\n trimmed = trimmed.slice(0, -3);\n }\n return trimmed.replace(/[?*+]+$/, '');\n}\n\nfunction extractParamName(value: string): string | null {\n if (!value) {\n return null;\n }\n const match = value.match(/^[A-Za-z0-9_-]+/);\n return match?.[0] ?? null;\n}\n","import { encodeBase64 } from './encoding';\nimport { normalizeRoutePattern } from './route';\nimport type { Logger, LogLevel } from './types';\n\n/**\n * Exporter settings used by the OTLP trace exporter.\n */\nexport interface ExporterConfig {\n /**\n * OTLP trace endpoint URL. `/v1/traces` is appended if missing.\n */\n endpointUrl: string;\n /**\n * Additional OTLP exporter headers (for example `Authorization`).\n */\n headers?: Record<string, string>;\n /**\n * Export timeout in milliseconds.\n */\n timeoutMs: number;\n /**\n * Span processor mode.\n *\n * Use `batch` (default) for lower overhead in long-lived services.\n * Use `simple` to export each span immediately (useful for tests and\n * short-lived runtimes).\n */\n spanProcessor: 'simple' | 'batch';\n}\n\n/**\n * Request/response capture settings.\n */\nexport interface CaptureConfig {\n /**\n * Include sanitized request headers in logs/spans.\n */\n requestHeaders: boolean;\n /**\n * Include sanitized response headers in logs/spans.\n */\n responseHeaders: boolean;\n /**\n * Request body capture mode.\n *\n * `none` disables capture, `text` records UTF-8 text, and `base64` preserves\n * binary payloads safely.\n */\n requestBody: 'none' | 'text' | 'base64';\n /**\n * Response body capture mode.\n *\n * `none` disables capture, `text` records UTF-8 text, and `base64` preserves\n * binary payloads safely.\n */\n responseBody: 'none' | 'text' | 'base64';\n /**\n * Maximum captured bytes per request/response body before truncation.\n */\n maxBodyBytes: number;\n}\n\n/**\n * Redaction settings for logs and captured payloads.\n */\nexport interface RedactionConfig {\n /**\n * Header names to redact (case-insensitive).\n */\n headers: string[];\n /**\n * Query parameter names to redact (case-insensitive).\n */\n queryParams: string[];\n /**\n * JSON paths to redact in captured JSON bodies.\n */\n bodyJsonPaths: string[];\n /**\n * Replacement value used for redacted data.\n */\n replacement: string;\n}\n\n/**\n * Request ID extraction and propagation settings.\n */\nexport interface RequestIdConfig {\n /**\n * Response header name to read request IDs from. This is normalized to\n * lowercase during configuration.\n */\n header: string;\n}\n\n/**\n * Route normalization settings.\n */\nexport interface RouteConfig {\n /**\n * When true, normalize route patterns before emitting logs.\n */\n normalize: boolean;\n /**\n * Optional custom normalizer. Defaults to X-ray's built-in normalizer.\n */\n normalizer?: (path: string) => string;\n}\n\n/**\n * Core emitter configuration.\n */\nexport interface XrayConfig {\n /**\n * Logical service name for all emitted request logs.\n */\n serviceName: string;\n /**\n * Optional deployment environment label.\n */\n environment?: string;\n /**\n * Optional service version label.\n */\n version?: string;\n /**\n * Logger for internal X-ray diagnostics.\n */\n logger?: Logger;\n /**\n * Minimum log level for internal diagnostics.\n */\n logLevel?: LogLevel;\n /**\n * OTLP endpoint URL. Falls back to `STAINLESS_XRAY_ENDPOINT_URL`.\n */\n endpointUrl?: string;\n /**\n * Exporter overrides.\n */\n exporter?: Partial<ExporterConfig>;\n /**\n * Capture overrides.\n */\n capture?: Partial<CaptureConfig>;\n /**\n * Redaction overrides.\n */\n redaction?: Partial<RedactionConfig>;\n /**\n * Request ID resolution settings. The header is read from response headers at\n * the end of the request.\n */\n requestId?: Partial<RequestIdConfig>;\n /**\n * Route normalization overrides.\n */\n route?: Partial<RouteConfig>;\n}\n\n/**\n * Runtime config accepted by framework/node/fetch entrypoints.\n */\nexport type XrayRuntimeConfig = Omit<XrayConfig, 'exporter'> & {\n exporter?: Partial<ExporterConfig> & {\n /**\n * Custom exporter instance. When provided, endpoint/header options are ignored.\n */\n instance?: import('@opentelemetry/sdk-trace-base').SpanExporter;\n };\n};\n\n/**\n * Fully-resolved configuration returned by `normalizeConfig`.\n */\nexport interface ResolvedXrayConfig {\n serviceName: string;\n environment?: string;\n version?: string;\n logger: Logger;\n logLevel: LogLevel;\n exporter: ExporterConfig;\n capture: CaptureConfig;\n redaction: RedactionConfig;\n requestId: RequestIdConfig;\n route: RouteConfig;\n}\n\nconst defaultCapture: CaptureConfig = {\n requestHeaders: true,\n responseHeaders: true,\n requestBody: 'text',\n responseBody: 'text',\n maxBodyBytes: 65536,\n};\n\nconst defaultRedaction: RedactionConfig = {\n headers: ['authorization', 'cookie', 'set-cookie', 'x-api-key'],\n queryParams: [],\n bodyJsonPaths: [],\n replacement: '[REDACTED]',\n};\n\nconst defaultRequestId: RequestIdConfig = {\n header: 'request-id',\n};\n\nconst defaultRoute: RouteConfig = {\n normalize: true,\n normalizer: normalizeRoutePattern,\n};\n\nconst defaultExporterBase: Omit<ExporterConfig, 'endpointUrl'> = {\n headers: {},\n timeoutMs: 30000,\n spanProcessor: 'batch',\n};\n\nexport class XrayConfigError extends Error {\n code: 'INVALID_CONFIG' | 'INVALID_REDACTION';\n\n constructor(code: XrayConfigError['code'], message: string) {\n super(message);\n this.code = code;\n }\n}\n\n/**\n * Normalize and validate user configuration.\n *\n * Applies defaults, validates required fields, and resolves environment\n * fallbacks such as `STAINLESS_XRAY_ENDPOINT_URL`.\n */\nexport function normalizeConfig(config: XrayConfig): ResolvedXrayConfig {\n if (!config || !config.serviceName || !config.serviceName.trim()) {\n throw new XrayConfigError('INVALID_CONFIG', 'serviceName is required');\n }\n\n const logger = config.logger ?? console;\n const logLevel = config.logLevel ?? 'warn';\n\n const capture = normalizeCapture(config.capture);\n const redaction = normalizeRedaction(config.redaction);\n const requestId = normalizeRequestId(config.requestId);\n const route = normalizeRoute(config.route);\n const exporter = normalizeExporter(config.endpointUrl, config.exporter);\n\n return {\n serviceName: config.serviceName.trim(),\n environment: config.environment?.trim() || undefined,\n version: config.version?.trim() || undefined,\n logger,\n logLevel,\n exporter,\n capture,\n redaction,\n requestId,\n route,\n };\n}\n\nfunction normalizeCapture(cfg?: Partial<CaptureConfig>): CaptureConfig {\n const capture: CaptureConfig = {\n ...defaultCapture,\n ...cfg,\n };\n\n if (!['none', 'text', 'base64'].includes(capture.requestBody)) {\n throw new XrayConfigError(\n 'INVALID_CONFIG',\n 'capture.requestBody must be none, text, or base64',\n );\n }\n if (!['none', 'text', 'base64'].includes(capture.responseBody)) {\n throw new XrayConfigError(\n 'INVALID_CONFIG',\n 'capture.responseBody must be none, text, or base64',\n );\n }\n if (!Number.isFinite(capture.maxBodyBytes) || capture.maxBodyBytes < 0) {\n throw new XrayConfigError('INVALID_CONFIG', 'capture.maxBodyBytes must be >= 0');\n }\n\n return capture;\n}\n\nfunction normalizeRedaction(cfg?: Partial<RedactionConfig>): RedactionConfig {\n const redaction: RedactionConfig = {\n ...defaultRedaction,\n ...cfg,\n };\n\n redaction.headers = normalizeStringList(redaction.headers);\n redaction.queryParams = normalizeStringList(redaction.queryParams);\n redaction.bodyJsonPaths = normalizeStringList(redaction.bodyJsonPaths);\n redaction.replacement = redaction.replacement || defaultRedaction.replacement;\n\n if (!redaction.replacement) {\n throw new XrayConfigError('INVALID_REDACTION', 'redaction.replacement must be non-empty');\n }\n\n return redaction;\n}\n\nfunction normalizeRequestId(cfg?: Partial<RequestIdConfig>): RequestIdConfig {\n const requestId: RequestIdConfig = {\n ...defaultRequestId,\n ...cfg,\n };\n\n requestId.header = requestId.header.trim().toLowerCase();\n if (!requestId.header) {\n throw new XrayConfigError('INVALID_CONFIG', 'requestId.header must be non-empty');\n }\n\n return requestId;\n}\n\nfunction normalizeRoute(cfg?: Partial<RouteConfig>): RouteConfig {\n const route: RouteConfig = {\n ...defaultRoute,\n ...cfg,\n };\n\n if (route.normalize && !route.normalizer) {\n route.normalizer = normalizeRoutePattern;\n }\n\n return route;\n}\n\nfunction normalizeExporter(\n endpointUrl: string | undefined,\n cfg?: Partial<ExporterConfig>,\n): ExporterConfig {\n const resolvedEndpoint = normalizeExporterEndpoint(cfg?.endpointUrl ?? endpointUrl);\n const rawHeaders = cfg?.headers ?? defaultExporterBase.headers ?? {};\n const parsed = applyEndpointAuth(resolvedEndpoint, rawHeaders);\n const spanProcessor = resolveSpanProcessor(cfg?.spanProcessor);\n const exporter: ExporterConfig = {\n endpointUrl: parsed.endpointUrl,\n headers: parsed.headers,\n timeoutMs: cfg?.timeoutMs ?? defaultExporterBase.timeoutMs,\n spanProcessor,\n };\n\n return exporter;\n}\n\nfunction normalizeExporterEndpoint(endpointUrl: string | undefined): string {\n const envUrl =\n typeof process !== 'undefined' ? process.env?.['STAINLESS_XRAY_ENDPOINT_URL'] : undefined;\n const resolved = endpointUrl ?? envUrl;\n if (!resolved || !resolved.trim()) {\n throw new XrayConfigError(\n 'INVALID_CONFIG',\n 'endpointUrl is required (set endpointUrl or STAINLESS_XRAY_ENDPOINT_URL)',\n );\n }\n const trimmed = resolved.trim();\n const withoutTrailingSlash = trimmed.endsWith('/') ? trimmed.slice(0, -1) : trimmed;\n if (withoutTrailingSlash.endsWith('/v1/traces')) {\n return withoutTrailingSlash;\n }\n return `${withoutTrailingSlash}/v1/traces`;\n}\n\nfunction normalizeStringList(values: string[] | undefined): string[] {\n if (!values) {\n return [];\n }\n return values.map((entry) => entry.trim()).filter(Boolean);\n}\n\nfunction resolveSpanProcessor(\n configured: ExporterConfig['spanProcessor'] | undefined,\n): ExporterConfig['spanProcessor'] {\n if (configured) {\n return configured;\n }\n\n const envProcessor =\n typeof process !== 'undefined' ? process.env?.['STAINLESS_XRAY_SPAN_PROCESSOR'] : undefined;\n if (!envProcessor) {\n return defaultExporterBase.spanProcessor;\n }\n\n if (envProcessor === 'simple' || envProcessor === 'batch') {\n return envProcessor;\n }\n\n throw new XrayConfigError(\n 'INVALID_CONFIG',\n 'STAINLESS_XRAY_SPAN_PROCESSOR must be \"simple\" or \"batch\"',\n );\n}\n\nconst textEncoder = typeof TextEncoder !== 'undefined' ? new TextEncoder() : null;\nconst maybeBuffer = (\n globalThis as typeof globalThis & {\n Buffer?: { from(data: string, encoding?: string): Uint8Array };\n }\n).Buffer;\n\nfunction applyEndpointAuth(\n endpointUrl: string,\n headers: Record<string, string> | undefined,\n): { endpointUrl: string; headers: Record<string, string> } {\n const resolvedHeaders = headers ?? {};\n let url: URL;\n try {\n url = new URL(endpointUrl);\n } catch {\n return { endpointUrl, headers: resolvedHeaders };\n }\n\n const username = decodeUserInfo(url.username);\n const password = decodeUserInfo(url.password);\n if (!username && !password) {\n return { endpointUrl, headers: resolvedHeaders };\n }\n\n url.username = '';\n url.password = '';\n const sanitizedUrl = url.toString();\n\n if (hasAuthorizationHeader(resolvedHeaders)) {\n return { endpointUrl: sanitizedUrl, headers: resolvedHeaders };\n }\n\n const authorization = encodeBasicAuth(username, password);\n if (!authorization) {\n return { endpointUrl: sanitizedUrl, headers: resolvedHeaders };\n }\n\n return {\n endpointUrl: sanitizedUrl,\n headers: {\n ...resolvedHeaders,\n Authorization: authorization,\n },\n };\n}\n\nfunction decodeUserInfo(value: string): string {\n if (!value) {\n return value;\n }\n try {\n return decodeURIComponent(value);\n } catch {\n return value;\n }\n}\n\nfunction hasAuthorizationHeader(headers: Record<string, string>): boolean {\n return Object.keys(headers).some((key) => key.toLowerCase() === 'authorization');\n}\n\nfunction encodeBasicAuth(username: string, password: string): string | undefined {\n const raw = `${username}:${password}`;\n let bytes: Uint8Array | undefined;\n if (textEncoder) {\n bytes = textEncoder.encode(raw);\n } else if (maybeBuffer) {\n bytes = maybeBuffer.from(raw, 'utf8');\n }\n if (!bytes) {\n return undefined;\n }\n const encoded = encodeBase64(bytes);\n if (!encoded) {\n return undefined;\n }\n return `Basic ${encoded}`;\n}\n","const headerNameCompactor = /[-_.]/g;\nconst headerTokenSplitter = /[-_.]/;\n\ntype HeaderRedactionMatcher = {\n exactSensitive: Set<string>;\n keywordTokens: Set<string>;\n keywordCompacted: string[];\n};\n\nconst defaultHeaderMatcher = newHeaderRedactionMatcher(\n defaultSensitiveHeaderNames(),\n defaultSensitiveKeywords(),\n);\n\nexport function authSchemePrefix(value: string): string {\n if (!value) {\n return '';\n }\n\n const lower = value.toLowerCase();\n if (lower.startsWith('basic')) {\n return value.slice(0, 'basic'.length);\n }\n if (lower.startsWith('bearer')) {\n return value.slice(0, 'bearer'.length);\n }\n if (lower.startsWith('digest')) {\n return value.slice(0, 'digest'.length);\n }\n if (lower.startsWith('negotiate')) {\n return value.slice(0, 'negotiate'.length);\n }\n return '';\n}\n\nexport function redactCookieValue(value: string, replacement: string): string {\n if (!value) {\n return replacement;\n }\n\n const parts = value.split(';');\n const redacted: string[] = [];\n\n for (const part of parts) {\n const segment = part.trim();\n if (!segment) {\n redacted.push(replacement);\n continue;\n }\n const idx = segment.indexOf('=');\n if (idx <= 0) {\n redacted.push(replacement);\n continue;\n }\n const name = segment.slice(0, idx);\n if (!name) {\n redacted.push(replacement);\n continue;\n }\n redacted.push(`${name}=${replacement}`);\n }\n\n return redacted.join('; ');\n}\n\nexport function redactSetCookieValue(value: string, replacement: string): string {\n if (!value) {\n return replacement;\n }\n\n const parts = value.split(';');\n const first = parts.shift() ?? '';\n const idx = first.indexOf('=');\n if (idx <= 0) {\n return replacement;\n }\n const name = first.slice(0, idx);\n if (!name) {\n return replacement;\n }\n\n const redacted = `${name}=${replacement}`;\n if (parts.length === 0) {\n return redacted;\n }\n return `${redacted};${parts.join(';')}`;\n}\n\nexport function isSensitiveHeaderName(key: string): boolean {\n return isSensitiveNormalized(defaultHeaderMatcher, normalizeHeaderName(key));\n}\n\nfunction addSensitiveHeaderNames(target: Set<string>, headers: string[]): void {\n for (const header of headers) {\n const normalized = normalizeHeaderName(header);\n if (normalized) {\n target.add(normalized);\n }\n }\n}\n\nfunction buildKeywordSets(keywords: string[]): { compacted: string[]; tokens: Set<string> } {\n const tokens = new Set<string>();\n const compacted = new Set<string>();\n\n for (const keyword of keywords) {\n const normalized = normalizeHeaderName(keyword);\n if (!normalized) {\n continue;\n }\n const compactedKeyword = compactNormalizedHeaderName(normalized);\n if (compactedKeyword) {\n compacted.add(compactedKeyword);\n }\n if (!normalized.includes('-') && !normalized.includes('_') && !normalized.includes('.')) {\n tokens.add(normalized);\n }\n }\n\n return {\n compacted: Array.from(compacted).sort(),\n tokens,\n };\n}\n\nfunction compactNormalizedHeaderName(normalized: string): string {\n if (!normalized) {\n return '';\n }\n return normalized.replace(headerNameCompactor, '');\n}\n\nfunction defaultSensitiveHeaderNames(): string[] {\n return [\n 'authorization',\n 'cookie',\n 'proxy-authenticate',\n 'proxy-authorization',\n 'set-cookie',\n 'www-authenticate',\n ];\n}\n\nfunction defaultSensitiveKeywords(): string[] {\n return [\n 'api-key',\n 'api_key',\n 'apikey',\n 'auth',\n 'authenticate',\n 'authorization',\n 'credential',\n 'password',\n 'passwd',\n 'private-key',\n 'private_key',\n 'privatekey',\n 'secret',\n 'session',\n 'sessionid',\n 'signature',\n 'token',\n ];\n}\n\nfunction headerNameTokens(name: string): string[] {\n if (!name) {\n return [];\n }\n return name.split(headerTokenSplitter).filter(Boolean);\n}\n\nfunction hasKeywordToken(tokens: string[], keywordTokens: Set<string>): boolean {\n for (const token of tokens) {\n if (keywordTokens.has(token)) {\n return true;\n }\n }\n return false;\n}\n\nfunction isExactMatch(normalized: string, exactSensitive: Set<string>): boolean {\n return exactSensitive.has(normalized);\n}\n\nfunction isSensitiveNormalized(matcher: HeaderRedactionMatcher, normalized: string): boolean {\n if (!normalized) {\n return false;\n }\n if (isExactMatch(normalized, matcher.exactSensitive)) {\n return true;\n }\n if (hasKeywordToken(headerNameTokens(normalized), matcher.keywordTokens)) {\n return true;\n }\n return matchesCompacted(normalized, matcher.keywordCompacted);\n}\n\nfunction matchesCompacted(normalized: string, keywordCompacted: string[]): boolean {\n if (keywordCompacted.length === 0) {\n return false;\n }\n const compacted = compactNormalizedHeaderName(normalized);\n if (!compacted) {\n return false;\n }\n return keywordCompacted.some((keyword) => compacted.includes(keyword));\n}\n\nfunction newHeaderRedactionMatcher(names: string[], keywords: string[]): HeaderRedactionMatcher {\n const exactSensitive = new Set<string>();\n addSensitiveHeaderNames(exactSensitive, names);\n const { compacted, tokens } = buildKeywordSets(keywords);\n return {\n exactSensitive,\n keywordCompacted: compacted,\n keywordTokens: tokens,\n };\n}\n\nfunction normalizeHeaderName(name: string): string {\n return name.trim().toLowerCase();\n}\n","import type { CapturedBody, RequestLog } from './types';\nimport { authSchemePrefix, redactCookieValue, redactSetCookieValue } from './header_redaction';\n\nexport function applyRedaction(\n config: {\n headers: string[];\n queryParams: string[];\n bodyJsonPaths: string[];\n replacement: string;\n },\n log: RequestLog,\n): RequestLog {\n const redacted = { ...log };\n\n if (redacted.requestHeaders) {\n redacted.requestHeaders = redactHeaders(redacted.requestHeaders, config);\n }\n if (redacted.responseHeaders) {\n redacted.responseHeaders = redactHeaders(redacted.responseHeaders, config);\n }\n\n redacted.url = redactUrl(redacted.url, config);\n\n if (redacted.requestBody) {\n redacted.requestBody = redactBody(redacted.requestBody, redacted.requestHeaders, config);\n }\n if (redacted.responseBody) {\n redacted.responseBody = redactBody(redacted.responseBody, redacted.responseHeaders, config);\n }\n\n return redacted;\n}\n\nexport function redactHeaders(\n headers: Record<string, string | string[]>,\n config: { headers: string[]; replacement: string },\n): Record<string, string | string[]> {\n const list = new Set(config.headers.map((name) => name.toLowerCase()));\n const result: Record<string, string | string[]> = {};\n\n for (const [name, value] of Object.entries(headers)) {\n const lower = name.toLowerCase();\n if (!list.has(lower)) {\n result[name] = value;\n continue;\n }\n\n const redactValue = (entry: string) => redactHeaderValue(lower, entry, config.replacement);\n if (Array.isArray(value)) {\n result[name] = value.map(redactValue);\n } else {\n result[name] = redactValue(value);\n }\n }\n\n return result;\n}\n\nfunction redactHeaderValue(name: string, value: string, replacement: string): string {\n switch (name) {\n case 'authorization':\n case 'proxy-authorization': {\n const scheme = authSchemePrefix(value);\n if (!scheme) {\n return replacement;\n }\n return `${scheme} ${replacement}`;\n }\n case 'cookie':\n return redactCookieValue(value, replacement);\n case 'set-cookie':\n return redactSetCookieValue(value, replacement);\n default:\n return replacement;\n }\n}\n\nfunction redactUrl(value: string, config: { queryParams: string[]; replacement: string }): string {\n if (!value || config.queryParams.length === 0) {\n return value;\n }\n\n try {\n const parsed = new URL(value);\n const params = parsed.searchParams;\n if (!params || params.size === 0) {\n return value;\n }\n\n const redact = new Set(config.queryParams.map((key) => key.toLowerCase()));\n const next = new URLSearchParams();\n params.forEach((val, key) => {\n if (redact.has(key.toLowerCase())) {\n next.append(key, config.replacement);\n } else {\n next.append(key, val);\n }\n });\n parsed.search = next.toString();\n return parsed.toString();\n } catch {\n return value;\n }\n}\n\nfunction redactBody(\n body: CapturedBody,\n headers: Record<string, string | string[]> | undefined,\n config: { bodyJsonPaths: string[]; replacement: string },\n): CapturedBody {\n if (config.bodyJsonPaths.length === 0) {\n return body;\n }\n if (!body.value || body.encoding !== 'utf8') {\n return body;\n }\n if (!isJsonContentType(headers)) {\n return body;\n }\n\n let parsed: unknown;\n try {\n parsed = JSON.parse(body.value);\n } catch {\n return body;\n }\n\n for (const path of config.bodyJsonPaths) {\n const segments = parseJsonPath(path);\n if (!segments) {\n continue;\n }\n redactJsonPath(parsed, segments, config.replacement);\n }\n\n const next = { ...body };\n next.value = JSON.stringify(parsed);\n return next;\n}\n\nfunction isJsonContentType(headers?: Record<string, string | string[]>): boolean {\n if (!headers) {\n return false;\n }\n const contentType = headers['content-type'] || headers['Content-Type'];\n const value = Array.isArray(contentType) ? contentType[0] : contentType;\n if (!value) {\n return false;\n }\n const normalized = value.split(';')[0];\n if (!normalized) {\n return false;\n }\n const trimmed = normalized.trim().toLowerCase();\n return trimmed === 'application/json' || trimmed.endsWith('+json');\n}\n\ntype JsonPathSegment = string | number;\n\nfunction parseJsonPath(path: string): JsonPathSegment[] | null {\n const trimmed = path.trim();\n if (!trimmed) {\n return null;\n }\n\n const normalized = trimmed.startsWith('$.') ? trimmed.slice(2) : trimmed;\n if (!normalized) {\n return null;\n }\n\n const segments: JsonPathSegment[] = [];\n const parts = normalized.split('.');\n for (const part of parts) {\n if (!part) {\n continue;\n }\n let cursor = part;\n const bracketIndex = cursor.indexOf('[');\n if (bracketIndex === -1) {\n segments.push(cursor);\n continue;\n }\n\n const name = cursor.slice(0, bracketIndex);\n if (name) {\n segments.push(name);\n }\n cursor = cursor.slice(bracketIndex);\n const matches = cursor.match(/\\[(\\d+)\\]/g);\n if (!matches) {\n continue;\n }\n for (const match of matches) {\n const indexValue = match.slice(1, -1);\n const index = Number.parseInt(indexValue, 10);\n if (Number.isFinite(index)) {\n segments.push(index);\n }\n }\n }\n\n return segments.length > 0 ? segments : null;\n}\n\nfunction redactJsonPath(value: unknown, segments: JsonPathSegment[], replacement: string): void {\n if (!value || segments.length === 0) {\n return;\n }\n\n let current: unknown = value;\n for (let i = 0; i < segments.length; i += 1) {\n const segment = segments[i];\n if (segment === undefined) {\n return;\n }\n const isLast = i === segments.length - 1;\n\n if (typeof segment === 'number') {\n if (!Array.isArray(current) || segment < 0 || segment >= current.length) {\n return;\n }\n if (isLast) {\n current[segment] = replacement;\n return;\n }\n current = current[segment];\n continue;\n }\n\n if (!current || typeof current !== 'object') {\n return;\n }\n const record = current as Record<string, unknown>;\n if (!(segment in record)) {\n return;\n }\n if (isLast) {\n record[segment] = replacement;\n return;\n }\n current = record[segment];\n }\n}\n","import type { Span } from '@opentelemetry/api';\nimport {\n ATTR_CLIENT_ADDRESS,\n ATTR_HTTP_REQUEST_BODY_SIZE,\n ATTR_HTTP_REQUEST_METHOD,\n ATTR_HTTP_RESPONSE_BODY_SIZE,\n ATTR_HTTP_RESPONSE_STATUS_CODE,\n ATTR_HTTP_ROUTE,\n ATTR_URL_FULL,\n ATTR_URL_PATH,\n ATTR_USER_ID,\n} from '@opentelemetry/semantic-conventions/incubating';\nimport type { AttributeValue, CapturedBody } from './types';\nimport {\n AttributeKeyRequestBody,\n AttributeKeyRequestBodyEncoding,\n AttributeKeyRequestBodyTruncated,\n AttributeKeyRequestID,\n AttributeKeyResponseBody,\n AttributeKeyResponseBodyEncoding,\n AttributeKeyResponseBodyTruncated,\n AttributeKeyTags,\n AttributeKeyTenantID,\n} from './attrkey';\n\nexport function setHeaderAttributes(\n span: Span,\n headers: Record<string, string | string[]> | undefined,\n prefix: string,\n): void {\n if (!headers) {\n return;\n }\n const keys = Object.keys(headers).sort((a, b) => a.toLowerCase().localeCompare(b.toLowerCase()));\n for (const key of keys) {\n const values = headers[key];\n if (!values || (Array.isArray(values) && values.length === 0)) {\n continue;\n }\n span.setAttribute(prefix + key.toLowerCase(), Array.isArray(values) ? values : [values]);\n }\n}\n\nexport function setRequestAttributes(\n span: Span,\n request: {\n method: string;\n url?: string;\n headers?: Record<string, string | string[]>;\n remoteAddress?: string;\n redactionReplacement?: string;\n },\n urlFull: string | undefined,\n): void {\n span.setAttribute(ATTR_HTTP_REQUEST_METHOD, request.method);\n const effectiveUrl = urlFull ?? request.url;\n if (effectiveUrl) {\n span.setAttribute(ATTR_URL_FULL, effectiveUrl);\n const path = extractPath(effectiveUrl);\n if (path) {\n span.setAttribute(ATTR_URL_PATH, path);\n }\n }\n const clientAddress = clientAddressForRequest(\n request.headers,\n request.remoteAddress,\n request.redactionReplacement,\n );\n if (clientAddress) {\n span.setAttribute(ATTR_CLIENT_ADDRESS, clientAddress);\n }\n}\n\nfunction extractPath(url: string): string | undefined {\n try {\n return new URL(url).pathname;\n } catch {\n // If not a full URL, try to extract path directly\n const match = url.match(/^[^?#]*/);\n return match?.[0] || undefined;\n }\n}\n\nfunction clientAddressForRequest(\n headers?: Record<string, string | string[]>,\n remoteAddress?: string,\n redactionReplacement?: string,\n): string | undefined {\n const forwarded = forwardedClientAddress(\n headerValues(headers, 'forwarded'),\n redactionReplacement,\n );\n if (forwarded) {\n return forwarded;\n }\n const xForwarded = xForwardedForClientAddress(\n headerValues(headers, 'x-forwarded-for'),\n redactionReplacement,\n );\n if (xForwarded) {\n return xForwarded;\n }\n const xRealIp = xRealIpClientAddress(headerValues(headers, 'x-real-ip'), redactionReplacement);\n if (xRealIp) {\n return xRealIp;\n }\n if (!remoteAddress) {\n return undefined;\n }\n return remoteAddrHost(remoteAddress);\n}\n\nfunction forwardedClientAddress(\n values: string[],\n redactionReplacement?: string,\n): string | undefined {\n for (const value of values) {\n if (!value) {\n continue;\n }\n const entries = value.split(',');\n for (const entry of entries) {\n const params = entry.split(';');\n for (const param of params) {\n const [rawKey, ...rest] = param.split('=');\n if (!rawKey) {\n continue;\n }\n if (rawKey.trim().toLowerCase() !== 'for') {\n continue;\n }\n const rawValue = rest.join('=').trim();\n const normalized = normalizeKnownAddress(rawValue, redactionReplacement);\n if (normalized) {\n return normalized;\n }\n }\n }\n }\n return undefined;\n}\n\nfunction xForwardedForClientAddress(\n values: string[],\n redactionReplacement?: string,\n): string | undefined {\n for (const value of values) {\n if (!value) {\n continue;\n }\n const entries = value.split(',');\n for (const entry of entries) {\n const normalized = normalizeKnownAddress(entry, redactionReplacement);\n if (normalized) {\n return normalized;\n }\n }\n }\n return undefined;\n}\n\nfunction xRealIpClientAddress(values: string[], redactionReplacement?: string): string | undefined {\n for (const value of values) {\n if (!value) {\n continue;\n }\n const normalized = normalizeKnownAddress(value, redactionReplacement);\n if (normalized) {\n return normalized;\n }\n }\n return undefined;\n}\n\nfunction normalizeKnownAddress(value: string, redactionReplacement?: string): string | undefined {\n const normalized = normalizeAddress(value, redactionReplacement);\n if (!normalized) {\n return undefined;\n }\n if (normalized.toLowerCase() === 'unknown') {\n return undefined;\n }\n return normalized;\n}\n\nfunction normalizeAddress(value: string, redactionReplacement?: string): string | undefined {\n if (!value) {\n return undefined;\n }\n let trimmed = value.trim();\n if (!trimmed) {\n return undefined;\n }\n if (redactionReplacement && trimmed === redactionReplacement) {\n return undefined;\n }\n if (trimmed.startsWith('\"') && trimmed.endsWith('\"') && trimmed.length > 1) {\n trimmed = trimmed.slice(1, -1).trim();\n }\n if (!trimmed) {\n return undefined;\n }\n if (trimmed.startsWith('[')) {\n const end = trimmed.indexOf(']');\n if (end !== -1) {\n return trimmed.slice(1, end);\n }\n }\n // If there's exactly one colon, treat it as host:port. More than one likely means IPv6.\n const colonCount = (trimmed.match(/:/g) ?? []).length;\n if (colonCount === 1) {\n const host = trimmed.split(':')[0];\n return host || undefined;\n }\n return trimmed;\n}\n\nfunction remoteAddrHost(value: string): string | undefined {\n return normalizeAddress(value);\n}\n\nfunction headerValues(\n headers: Record<string, string | string[]> | undefined,\n name: string,\n): string[] {\n if (!headers) {\n return [];\n }\n const target = name.toLowerCase();\n const values: string[] = [];\n for (const [key, value] of Object.entries(headers)) {\n if (key.toLowerCase() !== target) {\n continue;\n }\n if (Array.isArray(value)) {\n values.push(...value);\n } else {\n values.push(value);\n }\n }\n return values;\n}\n\nexport function setRequestBodyAttributes(span: Span, body: CapturedBody): void {\n if (!body.value) {\n return;\n }\n span.setAttribute(AttributeKeyRequestBody, body.value);\n span.setAttribute(AttributeKeyRequestBodyEncoding, body.encoding);\n if (body.truncated) {\n span.setAttribute(AttributeKeyRequestBodyTruncated, true);\n }\n}\n\nexport function setRequestBodySizeAttribute(span: Span, size: number): void {\n span.setAttribute(ATTR_HTTP_REQUEST_BODY_SIZE, size);\n}\n\nexport function setResponseBodyAttributes(span: Span, body: CapturedBody): void {\n if (!body.value) {\n return;\n }\n span.setAttribute(AttributeKeyResponseBody, body.value);\n span.setAttribute(AttributeKeyResponseBodyEncoding, body.encoding);\n if (body.truncated) {\n span.setAttribute(AttributeKeyResponseBodyTruncated, true);\n }\n}\n\nexport function setResponseBodySizeAttribute(span: Span, size: number): void {\n span.setAttribute(ATTR_HTTP_RESPONSE_BODY_SIZE, size);\n}\n\nexport function setResponseStatusAttribute(span: Span, statusCode: number): void {\n span.setAttribute(ATTR_HTTP_RESPONSE_STATUS_CODE, statusCode);\n}\n\nexport function setRouteAttribute(span: Span, route: string | undefined): void {\n if (route) {\n span.setAttribute(ATTR_HTTP_ROUTE, route);\n }\n}\n\nexport function setUserIdAttribute(span: Span, userId: string): void {\n span.setAttribute(ATTR_USER_ID, userId);\n}\n\nexport function setTenantIdAttribute(span: Span, tenantId: string): void {\n span.setAttribute(AttributeKeyTenantID, tenantId);\n}\n\nexport function setRequestIdAttribute(span: Span, requestId: string): void {\n span.setAttribute(AttributeKeyRequestID, requestId);\n}\n\n/**\n * JSON encode user-defined custom tags and add them as a span attribute.\n * Values that cannot be represented in JSON (e.g. BigInt) are silently dropped.\n */\nexport function setTagsAttribute(span: Span, tags: Record<string, AttributeValue>): void {\n const safe: Record<string, AttributeValue> = Object.create(null);\n for (const key of Object.keys(tags)) {\n const v = tags[key];\n if (isJSONSafe(v)) {\n safe[key] = v!;\n }\n }\n span.setAttribute(AttributeKeyTags, JSON.stringify(safe));\n}\n\n// JSON-safe values should only be settable via the type system, but in case raw\n// JS is in use, do a runtime check for safe JSON values to avoid an exception\n// and all tags being lost.\n//\n// The `seen` argument is used to avoid infinite recursion when checking for\n// circular references in arrays. No need to pass it for most invocations.\nfunction isJSONSafe(value: unknown, seen?: Set<unknown>): boolean {\n if (value === null || value === undefined) {\n return false;\n }\n const t = typeof value;\n if (t === 'string' || t === 'number' || t === 'boolean') {\n return true;\n }\n if (Array.isArray(value)) {\n if (!seen) {\n seen = new Set();\n }\n if (seen.has(value)) {\n return false;\n }\n seen.add(value);\n return value.every((el) => isJSONSafe(el, seen));\n }\n return false;\n}\n","export const AttributeKeyPrefixRequestHeader = 'http.request.header.';\nexport const AttributeKeyPrefixResponseHeader = 'http.response.header.';\nexport const AttributeKeyRequestBody = 'http.request.body';\nexport const AttributeKeyRequestBodyEncoding = 'http.request.body.encoding';\nexport const AttributeKeyRequestBodyTruncated = 'http.request.body.truncated';\nexport const AttributeKeyRequestID = 'http.request.id';\nexport const AttributeKeyResponseBody = 'http.response.body';\nexport const AttributeKeyResponseBodyEncoding = 'http.response.body.encoding';\nexport const AttributeKeyResponseBodyTruncated = 'http.response.body.truncated';\nexport const AttributeKeySpanDrop = 'stainlessxray.internal.drop';\nexport const AttributeKeyTags = 'stainlessxray.internal.tags';\nexport const AttributeKeyTenantID = 'stainlessxray.tenant.id';\nexport const AttributeKeyXrayCaptureErrorCode = 'xray.capture_error_code';\nexport const AttributeKeyXrayErrorThrown = 'xray.error_thrown';\nexport const AttributeKeyXrayHeadersTruncated = 'xray.headers_truncated';\nexport const AttributeKeyXrayInvalidResponse = 'xray.invalid_response';\nexport const AttributeKeyXrayRequestBodyCaptureFailed = 'xray.request_body_capture_failed';\nexport const AttributeKeyXrayRequestBodyTruncated = 'xray.request_body_truncated';\nexport const AttributeKeyXrayResponseBodyCaptureFailed = 'xray.response_body_capture_failed';\nexport const AttributeKeyXrayResponseBodyTruncated = 'xray.response_body_truncated';\n","import {\n diag,\n ROOT_CONTEXT,\n SpanKind,\n SpanStatusCode,\n type Context,\n type Span,\n type Tracer,\n} from '@opentelemetry/api';\nimport {\n AlwaysOnSampler,\n BasicTracerProvider,\n BatchSpanProcessor,\n type ReadableSpan,\n SimpleSpanProcessor,\n type Span as SDKSpan,\n type SpanExporter,\n type SpanProcessor,\n} from '@opentelemetry/sdk-trace-base';\nimport { resourceFromAttributes } from '@opentelemetry/resources';\nimport {\n ATTR_SERVICE_NAME,\n ATTR_TELEMETRY_SDK_LANGUAGE,\n ATTR_TELEMETRY_SDK_NAME,\n ATTR_TELEMETRY_SDK_VERSION,\n} from '@opentelemetry/semantic-conventions';\nimport { AttributeKeySpanDrop } from './attrkey';\nimport type { ResolvedXrayConfig } from './config';\n\nconst defaultAttributeCountLimit = 128;\n\nexport interface TracerProviderLike {\n forceFlush: () => Promise<void>;\n getTracer: (name: string, version?: string) => Tracer;\n shutdown: () => Promise<void>;\n}\n\nexport function createTracerProvider(\n config: ResolvedXrayConfig,\n exporter: SpanExporter,\n): TracerProviderLike {\n if (config.exporter.endpointUrl.startsWith('http://')) {\n diag.warn('xray: OTLP endpoint uses plaintext HTTP');\n }\n\n const attributeValueLengthLimit = Math.max(1, Math.ceil((config.capture.maxBodyBytes * 4) / 3));\n\n const resource = resourceFromAttributes({\n [ATTR_SERVICE_NAME]: config.serviceName,\n [ATTR_TELEMETRY_SDK_LANGUAGE]: isNodeRuntime() ? 'nodejs' : 'webjs',\n [ATTR_TELEMETRY_SDK_NAME]: 'stainless-xray',\n [ATTR_TELEMETRY_SDK_VERSION]: sdkVersion(),\n });\n\n const spanProcessor = createSpanProcessor(config.exporter.spanProcessor, exporter);\n const dropProcessor = new DropFilterSpanProcessor(spanProcessor);\n\n const provider = new BasicTracerProvider({\n forceFlushTimeoutMillis: 30_000,\n generalLimits: {\n attributeCountLimit: defaultAttributeCountLimit,\n attributeValueLengthLimit,\n },\n resource,\n sampler: new AlwaysOnSampler(),\n spanLimits: {\n attributeCountLimit: defaultAttributeCountLimit,\n attributePerEventCountLimit: defaultAttributeCountLimit,\n attributePerLinkCountLimit: defaultAttributeCountLimit,\n attributeValueLengthLimit,\n eventCountLimit: defaultAttributeCountLimit,\n linkCountLimit: defaultAttributeCountLimit,\n },\n spanProcessors: [dropProcessor],\n });\n\n return provider;\n}\n\nexport function tracerFromProvider(provider: TracerProviderLike): Tracer {\n return provider.getTracer('stainless-xray');\n}\n\nexport function spanFromTracer(tracer: Pick<Tracer, 'startSpan'>, name: string): Span {\n return tracer.startSpan(name, { kind: SpanKind.SERVER }, ROOT_CONTEXT);\n}\n\nexport function spanStatusFromError(span: Span, err: unknown): void {\n if (err instanceof Error) {\n span.recordException(err);\n } else if (typeof err === 'string') {\n span.recordException(err);\n } else {\n span.recordException({ message: String(err) });\n }\n span.setStatus({ code: SpanStatusCode.ERROR });\n}\n\nclass DropFilterSpanProcessor implements SpanProcessor {\n private readonly next: SpanProcessor;\n\n constructor(next: SpanProcessor) {\n this.next = next;\n }\n\n forceFlush(): Promise<void> {\n return this.next.forceFlush();\n }\n\n onEnd(span: ReadableSpan): void {\n if (span.attributes[AttributeKeySpanDrop] === true) {\n return;\n }\n this.next.onEnd(span);\n }\n\n onStart(span: SDKSpan, parentContext: Context): void {\n this.next.onStart(span, parentContext);\n }\n\n shutdown(): Promise<void> {\n return this.next.shutdown();\n }\n}\n\nfunction createSpanProcessor(mode: 'simple' | 'batch', exporter: SpanExporter): SpanProcessor {\n if (mode === 'simple') {\n return new SimpleSpanProcessor(exporter);\n }\n\n return new BatchSpanProcessor(exporter, {\n maxQueueSize: 2048,\n maxExportBatchSize: 512,\n scheduledDelayMillis: 5_000,\n exportTimeoutMillis: 30_000,\n });\n}\n\nfunction sdkVersion(): string {\n if (typeof __XRAY_VERSION__ !== 'undefined') {\n return __XRAY_VERSION__;\n }\n return 'unknown';\n}\n\nfunction isNodeRuntime(): boolean {\n const maybeProcess = (\n globalThis as typeof globalThis & {\n process?: { versions?: { node?: string } };\n }\n ).process;\n return !!maybeProcess?.versions?.node;\n}\n","import type { SpanExporter } from '@opentelemetry/sdk-trace-base';\nimport type { XrayConfig, ResolvedXrayConfig, CaptureConfig, RedactionConfig } from './config';\nimport { XrayConfigError, normalizeConfig } from './config';\nimport { logWithLevel } from './logger';\nimport { applyRedaction, redactHeaders } from './redaction';\nimport { makeCapturedBody, sanitizeHeaderValues, sanitizeLogString } from './request_log';\nimport {\n setHeaderAttributes,\n setRequestAttributes,\n setRequestBodyAttributes,\n setRequestBodySizeAttribute,\n setRequestIdAttribute,\n setResponseBodyAttributes,\n setResponseBodySizeAttribute,\n setResponseStatusAttribute,\n setRouteAttribute,\n setTagsAttribute,\n setTenantIdAttribute,\n setUserIdAttribute,\n} from './attributes';\nimport {\n createTracerProvider,\n spanFromTracer,\n spanStatusFromError,\n tracerFromProvider,\n} from './otel';\nimport { normalizeRoutePattern } from './route';\nimport { generateRequestId } from './uuid';\nimport { bindContext, getContextState, type RequestState } from './state';\nimport type {\n AttributeValue,\n NormalizedRequest,\n NormalizedResponse,\n RequestLog,\n XrayContext,\n XrayEmitter,\n} from './types';\n\n/**\n * Create a runtime-agnostic X-ray emitter with a provided SpanExporter.\n *\n * Most applications should use a runtime adapter (`/node`, `/fetch`,\n * or framework-specific entrypoints) unless they need custom transport logic.\n */\nexport function createEmitter(config: XrayConfig, exporter: SpanExporter): XrayEmitter {\n const resolved = normalizeConfig(config);\n if (!exporter) {\n throw new XrayConfigError(\n 'INVALID_CONFIG',\n 'exporter is required (use @stainlessdev/xray-node or @stainlessdev/xray-fetch)',\n );\n }\n logWithLevel(resolved.logger, 'info', resolved.logLevel, 'xray: emitter configured', {\n serviceName: resolved.serviceName,\n environment: resolved.environment,\n version: resolved.version,\n exporterEndpoint: resolved.exporter.endpointUrl,\n spanProcessor: resolved.exporter.spanProcessor,\n });\n const tracerProvider = createTracerProvider(resolved, exporter);\n const tracer = tracerFromProvider(tracerProvider);\n\n const emitter: XrayEmitter = {\n config: resolved,\n startRequest: (req) => startRequest(resolved, tracer, req),\n endRequest: (ctx, res, err) => endRequest(resolved, ctx, res, err),\n flush: () => tracerProvider.forceFlush(),\n shutdown: () => tracerProvider.shutdown(),\n };\n\n return emitter;\n}\n\nfunction startRequest(\n config: ResolvedXrayConfig,\n tracer: ReturnType<typeof tracerFromProvider>,\n req: NormalizedRequest,\n): XrayContext {\n const startTimeMs = Number.isFinite(req.startTimeMs) ? req.startTimeMs : Date.now();\n req.startTimeMs = startTimeMs;\n\n const explicitRequestId = normalizeRequestIdCandidate(req.requestId);\n req.requestId = explicitRequestId;\n\n if (req.route && config.route.normalize) {\n req.route = config.route.normalizer\n ? config.route.normalizer(req.route)\n : normalizeRoutePattern(req.route);\n }\n\n const span = spanFromTracer(tracer, spanNameFromRequest(req));\n const context: XrayContext = {\n requestId: explicitRequestId ?? '',\n traceId: span?.spanContext().traceId,\n spanId: span?.spanContext().spanId,\n setActor: (tenantId, userId) => {\n const state = getContextState(context);\n if (!state) {\n return;\n }\n state.tenantId = tenantId;\n state.userId = userId || undefined;\n if (span) {\n try {\n setTenantIdAttribute(span, tenantId);\n if (userId) {\n setUserIdAttribute(span, userId);\n }\n } catch (err) {\n logWithLevel(config.logger, 'error', config.logLevel, 'xray: setActor failed', {\n error: err instanceof Error ? err.message : String(err),\n });\n }\n }\n },\n // Deprecated compatibility alias; prefer setActor(tenantId, userId).\n setUserId: (id) => {\n const state = getContextState(context);\n if (!state) {\n return;\n }\n state.userId = id;\n if (span && id) {\n try {\n setUserIdAttribute(span, id);\n } catch (err) {\n logWithLevel(config.logger, 'error', config.logLevel, 'xray: setUserId failed', {\n error: err instanceof Error ? err.message : String(err),\n });\n }\n }\n },\n setSessionId: (id) => {\n const state = getContextState(context);\n if (!state) {\n return;\n }\n state.sessionId = id;\n },\n setTag: (key, value) => {\n const state = getContextState(context);\n if (!state) {\n return;\n }\n state.tags[key] = value;\n },\n addEvent: (name, attributes) => {\n const state = getContextState(context);\n if (!state) {\n return;\n }\n state.events.push({ name, attributes });\n if (span) {\n try {\n span.addEvent(name, attributes as Record<string, AttributeValue> | undefined);\n } catch {\n // Ignore span event errors.\n }\n }\n },\n setError: (err) => {\n const state = getContextState(context);\n if (!state) {\n return;\n }\n state.error = err;\n if (span) {\n try {\n spanStatusFromError(span, err);\n } catch {\n // Ignore span errors.\n }\n }\n },\n };\n\n const state: RequestState = {\n request: req,\n config,\n span,\n context,\n attributes: {},\n events: [],\n tags: Object.create(null) as Record<string, AttributeValue>,\n };\n\n bindContext(context, state);\n return context;\n}\n\nfunction endRequest(\n config: ResolvedXrayConfig,\n ctx: XrayContext,\n res: NormalizedResponse,\n err?: unknown,\n): RequestLog {\n const state = getContextState(ctx);\n const endTimeMs = Number.isFinite(res.endTimeMs) ? res.endTimeMs : Date.now();\n res.endTimeMs = endTimeMs;\n\n if (!state) {\n const resolvedRequestId = resolveFinalRequestId(config, ctx.requestId, res.headers);\n ctx.requestId = resolvedRequestId;\n const fallbackLog: RequestLog = {\n requestId: resolvedRequestId,\n serviceName: config.serviceName,\n method: res.statusCode ? 'UNKNOWN' : 'UNKNOWN',\n url: '',\n durationMs: 0,\n statusCode: res.statusCode,\n timestamp: new Date(endTimeMs).toISOString(),\n };\n return fallbackLog;\n }\n\n const request = state.request;\n const resolvedRequestId = resolveFinalRequestId(\n config,\n request.requestId || ctx.requestId,\n res.headers,\n );\n request.requestId = resolvedRequestId;\n ctx.requestId = resolvedRequestId;\n const capture = resolveCapture(config.capture, state.captureOverride);\n const redaction = resolveRedaction(config.redaction, state.redactionOverride);\n\n const route = request.route;\n const url = sanitizeLogString(request.url);\n const log: RequestLog = {\n requestId: resolvedRequestId,\n traceId: state.span?.spanContext().traceId,\n spanId: state.span?.spanContext().spanId,\n serviceName: config.serviceName,\n method: request.method,\n url: url,\n route: route,\n statusCode: res.statusCode,\n durationMs: Math.max(0, endTimeMs - request.startTimeMs),\n requestHeaders: capture.requestHeaders ? sanitizeHeaderValues(request.headers) : undefined,\n responseHeaders: capture.responseHeaders ? sanitizeHeaderValues(res.headers) : undefined,\n requestBody: capture.requestBody === 'none' ? undefined : request.body,\n responseBody: capture.responseBody === 'none' ? undefined : res.body,\n tenantId: state.tenantId ?? undefined,\n userId: state.userId ?? undefined,\n sessionId: state.sessionId ?? undefined,\n error: buildError(err ?? state.error),\n attributes: Object.keys(state.attributes).length > 0 ? { ...state.attributes } : undefined,\n tags: Object.keys(state.tags).length > 0 ? { ...state.tags } : undefined,\n timestamp: new Date(endTimeMs).toISOString(),\n };\n\n const redacted = applyRedaction(redaction, log);\n if (redacted.route && config.route.normalize) {\n const normalized = config.route.normalizer\n ? config.route.normalizer(redacted.route)\n : normalizeRoutePattern(redacted.route);\n redacted.route = normalized;\n }\n const span = state.span;\n if (span) {\n try {\n const clientAddressHeaders = redactHeaders(request.headers, redaction);\n setRequestAttributes(\n span,\n {\n ...request,\n headers: clientAddressHeaders,\n redactionReplacement: redaction.replacement,\n },\n redacted.url,\n );\n setRequestIdAttribute(span, redacted.requestId);\n span.setAttribute('service.name', config.serviceName);\n if (redacted.statusCode != null) {\n setResponseStatusAttribute(span, redacted.statusCode);\n }\n if (redacted.route) {\n setRouteAttribute(span, redacted.route);\n span.updateName(`${request.method} ${redacted.route}`);\n } else {\n span.updateName(spanNameFromRequest(request));\n }\n if (redacted.requestHeaders) {\n setHeaderAttributes(span, redacted.requestHeaders, 'http.request.header.');\n }\n if (redacted.responseHeaders) {\n setHeaderAttributes(span, redacted.responseHeaders, 'http.response.header.');\n }\n if (redacted.requestBody) {\n setRequestBodyAttributes(span, redacted.requestBody);\n setRequestBodySizeAttribute(span, redacted.requestBody.bytes);\n }\n if (redacted.responseBody) {\n setResponseBodyAttributes(span, redacted.responseBody);\n setResponseBodySizeAttribute(span, redacted.responseBody.bytes);\n }\n if (state.tenantId != null) {\n setTenantIdAttribute(span, state.tenantId);\n }\n if (state.userId) {\n setUserIdAttribute(span, state.userId);\n }\n if (Object.keys(state.tags).length > 0) {\n setTagsAttribute(span, state.tags);\n }\n if (err ?? state.error) {\n spanStatusFromError(span, err ?? state.error);\n }\n span.end();\n } catch (spanErr) {\n logWithLevel(config.logger, 'warn', config.logLevel, 'xray: span finalize failed', {\n error: spanErr instanceof Error ? spanErr.message : String(spanErr),\n });\n }\n }\n\n return redacted;\n}\n\nfunction resolveFinalRequestId(\n config: ResolvedXrayConfig,\n explicitRequestId: string | undefined,\n responseHeaders?: Record<string, string | string[]>,\n): string {\n const explicit = normalizeRequestIdCandidate(explicitRequestId);\n if (explicit) {\n return explicit;\n }\n const headerValue = resolveHeaderRequestId(config.requestId.header, responseHeaders);\n if (headerValue) {\n return headerValue;\n }\n return generateRequestId();\n}\n\nfunction resolveHeaderRequestId(\n headerName: string,\n headers?: Record<string, string | string[]>,\n): string | undefined {\n if (!headers) {\n return undefined;\n }\n const target = headerName.toLowerCase();\n for (const [name, value] of Object.entries(headers)) {\n if (name.toLowerCase() !== target) {\n continue;\n }\n const entry = Array.isArray(value) ? value[0] : value;\n const normalized = normalizeRequestIdCandidate(entry);\n if (normalized) {\n return normalized;\n }\n }\n return undefined;\n}\n\nfunction normalizeRequestIdCandidate(value: string | undefined): string | undefined {\n if (!value) {\n return undefined;\n }\n const trimmed = value.trim();\n return trimmed ? trimmed : undefined;\n}\n\nfunction resolveCapture(base: CaptureConfig, override?: Partial<CaptureConfig>): CaptureConfig {\n if (!override) {\n return base;\n }\n return {\n ...base,\n ...override,\n };\n}\n\nfunction resolveRedaction(\n base: RedactionConfig,\n override?: Partial<RedactionConfig>,\n): RedactionConfig {\n const merged: RedactionConfig = {\n ...base,\n ...override,\n };\n\n merged.headers = normalizeLowercaseList(merged.headers);\n merged.queryParams = normalizeLowercaseList(merged.queryParams);\n merged.bodyJsonPaths = normalizeList(merged.bodyJsonPaths);\n merged.replacement = merged.replacement || base.replacement;\n\n return merged;\n}\n\nfunction normalizeLowercaseList(values: string[] | undefined): string[] {\n if (!values) {\n return [];\n }\n return values.map((entry) => entry.trim().toLowerCase()).filter(Boolean);\n}\n\nfunction normalizeList(values: string[] | undefined): string[] {\n if (!values) {\n return [];\n }\n return values.map((entry) => entry.trim()).filter(Boolean);\n}\n\nfunction buildError(err?: unknown): RequestLog['error'] {\n if (!err) {\n return undefined;\n }\n if (err instanceof Error) {\n return {\n message: err.message || 'Error',\n type: err.name || 'Error',\n stack: err.stack,\n };\n }\n return {\n message: String(err),\n };\n}\n\nfunction spanNameFromRequest(req: NormalizedRequest): string {\n const method = req.method || 'GET';\n if (req.route) {\n return `${method} ${req.route}`;\n }\n const path = safePath(req.url);\n return `${method} ${path}`;\n}\n\nfunction safePath(url: string): string {\n try {\n const parsed = new URL(url);\n return parsed.pathname || '/';\n } catch {\n const rawPath = url.split('?')[0] || '/';\n return rawPath || '/';\n }\n}\n\nexport function captureBody(\n bytes: Uint8Array | undefined,\n totalBytes: number,\n truncated: boolean,\n mode: 'text' | 'base64' | 'none',\n): ReturnType<typeof makeCapturedBody> {\n if (mode === 'none') {\n return undefined;\n }\n return makeCapturedBody(bytes, totalBytes, truncated, mode === 'text' ? 'text' : 'base64');\n}\n\nexport function captureResponseBody(\n bytes: Uint8Array | undefined,\n totalBytes: number,\n truncated: boolean,\n mode: 'text' | 'base64' | 'none',\n): ReturnType<typeof makeCapturedBody> {\n if (mode === 'none') {\n return undefined;\n }\n return makeCapturedBody(bytes, totalBytes, truncated, mode === 'text' ? 'text' : 'base64');\n}\n"]}
@@ -2,7 +2,7 @@
2
2
 
3
3
 
4
4
 
5
- var _chunkDNBARLGBcjs = require('./chunk-DNBARLGB.cjs');
5
+ var _chunkEPQTFPT7cjs = require('./chunk-EPQTFPT7.cjs');
6
6
 
7
7
  // src/core/limited_buffer.ts
8
8
  var LimitedBuffer = class {
@@ -223,17 +223,17 @@ function headerHasTokenFetch(headers, name, token) {
223
223
 
224
224
  // src/core/internal.ts
225
225
  function bindContextToObject(target, ctx) {
226
- const state = _chunkDNBARLGBcjs.getContextState.call(void 0, ctx);
226
+ const state = _chunkEPQTFPT7cjs.getContextState.call(void 0, ctx);
227
227
  if (!state) {
228
228
  return;
229
229
  }
230
- _chunkDNBARLGBcjs.bindObject.call(void 0, target, state);
230
+ _chunkEPQTFPT7cjs.bindObject.call(void 0, target, state);
231
231
  }
232
232
  function getXrayContextFromObject(target) {
233
- return _chunkDNBARLGBcjs.getContextFromObject.call(void 0, target);
233
+ return _chunkEPQTFPT7cjs.getContextFromObject.call(void 0, target);
234
234
  }
235
235
  function setContextRoute(ctx, route) {
236
- const state = _chunkDNBARLGBcjs.getContextState.call(void 0, ctx);
236
+ const state = _chunkEPQTFPT7cjs.getContextState.call(void 0, ctx);
237
237
  if (!state) {
238
238
  return;
239
239
  }
@@ -241,7 +241,7 @@ function setContextRoute(ctx, route) {
241
241
  state.request.route = normalized;
242
242
  }
243
243
  function setContextRequestId(ctx, requestId) {
244
- const state = _chunkDNBARLGBcjs.getContextState.call(void 0, ctx);
244
+ const state = _chunkEPQTFPT7cjs.getContextState.call(void 0, ctx);
245
245
  if (!state) {
246
246
  return;
247
247
  }
@@ -249,14 +249,14 @@ function setContextRequestId(ctx, requestId) {
249
249
  state.context.requestId = requestId;
250
250
  }
251
251
  function setCaptureOverride(ctx, capture) {
252
- const state = _chunkDNBARLGBcjs.getContextState.call(void 0, ctx);
252
+ const state = _chunkEPQTFPT7cjs.getContextState.call(void 0, ctx);
253
253
  if (!state || !capture) {
254
254
  return;
255
255
  }
256
256
  state.captureOverride = capture;
257
257
  }
258
258
  function setRedactionOverride(ctx, redaction) {
259
- const state = _chunkDNBARLGBcjs.getContextState.call(void 0, ctx);
259
+ const state = _chunkEPQTFPT7cjs.getContextState.call(void 0, ctx);
260
260
  if (!state || !redaction) {
261
261
  return;
262
262
  }
@@ -278,4 +278,4 @@ function setRedactionOverride(ctx, redaction) {
278
278
 
279
279
 
280
280
  exports.LimitedBuffer = LimitedBuffer; exports.headerValuesFromNodeHeaders = headerValuesFromNodeHeaders; exports.headerValuesFromFetchHeaders = headerValuesFromFetchHeaders; exports.headerValuesFromFetchHeadersWithLimit = headerValuesFromFetchHeadersWithLimit; exports.headerTokenList = headerTokenList; exports.isWebsocketUpgrade = isWebsocketUpgrade; exports.isWebsocketUpgradeFetch = isWebsocketUpgradeFetch; exports.bindContextToObject = bindContextToObject; exports.getXrayContextFromObject = getXrayContextFromObject; exports.setContextRoute = setContextRoute; exports.setContextRequestId = setContextRequestId; exports.setCaptureOverride = setCaptureOverride; exports.setRedactionOverride = setRedactionOverride;
281
- //# sourceMappingURL=chunk-CPHFCOA5.cjs.map
281
+ //# sourceMappingURL=chunk-M6G4PEGF.cjs.map
@@ -1 +1 @@
1
- {"version":3,"sources":["/home/runner/work/xray-emitter-js/xray-emitter-js/dist/chunk-CPHFCOA5.cjs","../src/core/limited_buffer.ts","../src/core/headers.ts","../src/core/websocket.ts","../src/core/internal.ts"],"names":[],"mappings":"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","file":"/home/runner/work/xray-emitter-js/xray-emitter-js/dist/chunk-CPHFCOA5.cjs","sourcesContent":[null,"export class LimitedBuffer {\n private buffer: Uint8Array;\n private length: number;\n private readonly limit: number;\n private truncatedFlag: boolean;\n private total: number;\n\n constructor(limit: number) {\n const normalized = Number.isFinite(limit) ? Math.max(0, limit) : 0;\n const initialCap = Math.min(normalized, 32 * 1024);\n this.buffer = new Uint8Array(initialCap);\n this.length = 0;\n this.limit = normalized;\n this.truncatedFlag = false;\n this.total = 0;\n }\n\n bytes(): Uint8Array {\n return this.buffer.slice(0, this.length);\n }\n\n capturedBytes(): number {\n return this.length;\n }\n\n totalBytes(): number {\n return this.total;\n }\n\n truncated(): boolean {\n return this.truncatedFlag;\n }\n\n write(chunk: Uint8Array): void {\n if (!chunk || chunk.length === 0) {\n return;\n }\n\n this.total += chunk.length;\n if (this.limit <= 0) {\n this.truncatedFlag = true;\n return;\n }\n\n const remaining = this.limit - this.length;\n if (remaining <= 0) {\n this.truncatedFlag = true;\n return;\n }\n\n const toCopy = Math.min(remaining, chunk.length);\n this.ensureCapacity(this.length + toCopy);\n this.buffer.set(chunk.subarray(0, toCopy), this.length);\n this.length += toCopy;\n if (toCopy < chunk.length) {\n this.truncatedFlag = true;\n }\n }\n\n private ensureCapacity(size: number): void {\n if (this.buffer.length >= size) {\n return;\n }\n\n let nextSize = this.buffer.length;\n if (nextSize === 0) {\n nextSize = 1;\n }\n while (nextSize < size) {\n nextSize *= 2;\n }\n if (nextSize > this.limit) {\n nextSize = this.limit;\n }\n const next = new Uint8Array(nextSize);\n next.set(this.buffer.subarray(0, this.length));\n this.buffer = next;\n }\n}\n","export type HeaderCapture = {\n headers: Record<string, string | string[]>;\n truncated: boolean;\n};\n\nexport function headerValuesFromNodeHeaders(\n headers: Record<string, string | string[] | number | undefined>,\n): Record<string, string | string[]> {\n const result: Record<string, string | string[]> = {};\n for (const [key, value] of Object.entries(headers)) {\n if (value == null) {\n continue;\n }\n const name = key.trim();\n if (!name) {\n continue;\n }\n if (Array.isArray(value)) {\n const entries = value.map((item) => `${item}`);\n if (entries.length > 0) {\n result[name] = entries.length === 1 ? entries[0]! : entries;\n }\n } else {\n result[name] = `${value}`;\n }\n }\n return Object.keys(result).length === 0 ? {} : result;\n}\n\nexport function headerValuesFromFetchHeaders(headers: Headers): Record<string, string | string[]> {\n return headerValuesFromFetchHeadersWithLimit(headers, Number.POSITIVE_INFINITY).headers;\n}\n\nexport function headerValuesFromFetchHeadersWithLimit(\n headers: Headers,\n maxBytes: number,\n): HeaderCapture {\n const result: Record<string, string | string[]> = {};\n let truncated = false;\n let remaining = Number.isFinite(maxBytes) ? Math.max(0, maxBytes) : Number.POSITIVE_INFINITY;\n const setCookie = getSetCookie(headers);\n if (setCookie) {\n const values = takeHeaderValues('set-cookie', setCookie, remaining);\n remaining = values.remaining;\n if (values.truncated) {\n truncated = true;\n }\n if (values.values.length > 0) {\n result['set-cookie'] = values.values.length === 1 ? values.values[0]! : values.values;\n }\n }\n\n headers.forEach((value, key) => {\n const name = key.trim();\n if (!name) {\n return;\n }\n if (name.toLowerCase() === 'set-cookie' && setCookie) {\n return;\n }\n const values = takeHeaderValues(name, [value], remaining);\n remaining = values.remaining;\n if (values.truncated) {\n truncated = true;\n }\n if (values.values.length > 0) {\n result[name] = values.values.length === 1 ? values.values[0]! : values.values;\n }\n });\n\n return {\n headers: Object.keys(result).length === 0 ? {} : result,\n truncated,\n };\n}\n\nexport function headerTokenList(values: string[] | string | undefined): string[] {\n if (!values) {\n return [];\n }\n if (Array.isArray(values)) {\n return splitTokens(values);\n }\n return splitTokens([values]);\n}\n\nfunction splitTokens(values: string[]): string[] {\n const tokens: string[] = [];\n for (const value of values) {\n if (!value) {\n continue;\n }\n for (const part of value.split(',')) {\n const trimmed = part.trim();\n if (trimmed) {\n tokens.push(trimmed);\n }\n }\n }\n return tokens;\n}\n\nfunction getSetCookie(headers: Headers): string[] | null {\n const maybe = headers as Headers & { getSetCookie?: () => string[] };\n if (typeof maybe.getSetCookie === 'function') {\n const values = maybe.getSetCookie();\n return values.length > 0 ? values : null;\n }\n return null;\n}\n\nfunction takeHeaderValues(\n name: string,\n values: string[],\n remaining: number,\n): { values: string[]; remaining: number; truncated: boolean } {\n if (remaining <= 0) {\n return { remaining: 0, truncated: true, values: [] };\n }\n\n const taken: string[] = [];\n let used = 0;\n for (const value of values) {\n if (!value) {\n continue;\n }\n const size = name.length + value.length;\n if (used + size > remaining) {\n return { remaining: Math.max(0, remaining - used), truncated: true, values: taken };\n }\n used += size;\n taken.push(value);\n }\n\n return { remaining: Math.max(0, remaining - used), truncated: false, values: taken };\n}\n","import { headerTokenList } from './headers';\n\ntype HeaderValues = Record<string, string | string[]>;\n\nexport function isWebsocketUpgrade(\n statusCode: number,\n requestHeaders: HeaderValues | undefined,\n responseHeaders: HeaderValues | undefined,\n): boolean {\n if (statusCode !== 101) {\n return false;\n }\n\n if (headerHasToken(responseHeaders, 'upgrade', 'websocket')) {\n return true;\n }\n return headerHasToken(requestHeaders, 'upgrade', 'websocket');\n}\n\nexport function isWebsocketUpgradeFetch(\n statusCode: number,\n requestHeaders: Headers,\n responseHeaders: Headers,\n): boolean {\n if (statusCode !== 101) {\n return false;\n }\n\n if (headerHasTokenFetch(responseHeaders, 'upgrade', 'websocket')) {\n return true;\n }\n return headerHasTokenFetch(requestHeaders, 'upgrade', 'websocket');\n}\n\nfunction headerHasToken(headers: HeaderValues | undefined, name: string, token: string): boolean {\n if (!headers) {\n return false;\n }\n const values = headers[name] ?? headers[name.toLowerCase()] ?? headers[name.toUpperCase()];\n if (!values) {\n return false;\n }\n const tokens = headerTokenList(values);\n return tokens.some((value) => value.toLowerCase() === token.toLowerCase());\n}\n\nfunction headerHasTokenFetch(headers: Headers, name: string, token: string): boolean {\n const value = headers.get(name);\n if (!value) {\n return false;\n }\n return value.split(',').some((part) => part.trim().toLowerCase() === token.toLowerCase());\n}\n","import type { CaptureConfig, RedactionConfig } from './config';\nimport type { XrayContext } from './types';\nimport { bindObject, getContextFromObject, getContextState } from './state';\n\nexport { LimitedBuffer } from './limited_buffer';\nexport {\n headerValuesFromFetchHeaders,\n headerValuesFromFetchHeadersWithLimit,\n headerValuesFromNodeHeaders,\n headerTokenList,\n} from './headers';\nexport { isWebsocketUpgrade, isWebsocketUpgradeFetch } from './websocket';\nexport { makeCapturedBody } from './request_log';\nexport { logWithLevel } from './logger';\nexport { generateRequestId, uuidv7, uuidv7base48, uuidv7base62 } from './uuid';\n\nexport function bindContextToObject(target: object, ctx: XrayContext): void {\n const state = getContextState(ctx);\n if (!state) {\n return;\n }\n bindObject(target, state);\n}\n\nexport function getXrayContextFromObject(target: unknown): XrayContext | undefined {\n return getContextFromObject(target);\n}\n\nexport function setContextRoute(ctx: XrayContext, route: string): void {\n const state = getContextState(ctx);\n if (!state) {\n return;\n }\n const normalized =\n state.config.route.normalize && state.config.route.normalizer\n ? state.config.route.normalizer(route)\n : route;\n state.request.route = normalized;\n}\n\nexport function setContextRequestId(ctx: XrayContext, requestId: string): void {\n const state = getContextState(ctx);\n if (!state) {\n return;\n }\n state.request.requestId = requestId;\n state.context.requestId = requestId;\n}\n\nexport function setCaptureOverride(\n ctx: XrayContext,\n capture: Partial<CaptureConfig> | undefined,\n): void {\n const state = getContextState(ctx);\n if (!state || !capture) {\n return;\n }\n state.captureOverride = capture;\n}\n\nexport function setRedactionOverride(\n ctx: XrayContext,\n redaction: Partial<RedactionConfig> | undefined,\n): void {\n const state = getContextState(ctx);\n if (!state || !redaction) {\n return;\n }\n state.redactionOverride = redaction;\n}\n"]}
1
+ {"version":3,"sources":["/home/runner/work/xray-emitter-js/xray-emitter-js/dist/chunk-M6G4PEGF.cjs","../src/core/limited_buffer.ts","../src/core/headers.ts","../src/core/websocket.ts","../src/core/internal.ts"],"names":[],"mappings":"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","file":"/home/runner/work/xray-emitter-js/xray-emitter-js/dist/chunk-M6G4PEGF.cjs","sourcesContent":[null,"export class LimitedBuffer {\n private buffer: Uint8Array;\n private length: number;\n private readonly limit: number;\n private truncatedFlag: boolean;\n private total: number;\n\n constructor(limit: number) {\n const normalized = Number.isFinite(limit) ? Math.max(0, limit) : 0;\n const initialCap = Math.min(normalized, 32 * 1024);\n this.buffer = new Uint8Array(initialCap);\n this.length = 0;\n this.limit = normalized;\n this.truncatedFlag = false;\n this.total = 0;\n }\n\n bytes(): Uint8Array {\n return this.buffer.slice(0, this.length);\n }\n\n capturedBytes(): number {\n return this.length;\n }\n\n totalBytes(): number {\n return this.total;\n }\n\n truncated(): boolean {\n return this.truncatedFlag;\n }\n\n write(chunk: Uint8Array): void {\n if (!chunk || chunk.length === 0) {\n return;\n }\n\n this.total += chunk.length;\n if (this.limit <= 0) {\n this.truncatedFlag = true;\n return;\n }\n\n const remaining = this.limit - this.length;\n if (remaining <= 0) {\n this.truncatedFlag = true;\n return;\n }\n\n const toCopy = Math.min(remaining, chunk.length);\n this.ensureCapacity(this.length + toCopy);\n this.buffer.set(chunk.subarray(0, toCopy), this.length);\n this.length += toCopy;\n if (toCopy < chunk.length) {\n this.truncatedFlag = true;\n }\n }\n\n private ensureCapacity(size: number): void {\n if (this.buffer.length >= size) {\n return;\n }\n\n let nextSize = this.buffer.length;\n if (nextSize === 0) {\n nextSize = 1;\n }\n while (nextSize < size) {\n nextSize *= 2;\n }\n if (nextSize > this.limit) {\n nextSize = this.limit;\n }\n const next = new Uint8Array(nextSize);\n next.set(this.buffer.subarray(0, this.length));\n this.buffer = next;\n }\n}\n","export type HeaderCapture = {\n headers: Record<string, string | string[]>;\n truncated: boolean;\n};\n\nexport function headerValuesFromNodeHeaders(\n headers: Record<string, string | string[] | number | undefined>,\n): Record<string, string | string[]> {\n const result: Record<string, string | string[]> = {};\n for (const [key, value] of Object.entries(headers)) {\n if (value == null) {\n continue;\n }\n const name = key.trim();\n if (!name) {\n continue;\n }\n if (Array.isArray(value)) {\n const entries = value.map((item) => `${item}`);\n if (entries.length > 0) {\n result[name] = entries.length === 1 ? entries[0]! : entries;\n }\n } else {\n result[name] = `${value}`;\n }\n }\n return Object.keys(result).length === 0 ? {} : result;\n}\n\nexport function headerValuesFromFetchHeaders(headers: Headers): Record<string, string | string[]> {\n return headerValuesFromFetchHeadersWithLimit(headers, Number.POSITIVE_INFINITY).headers;\n}\n\nexport function headerValuesFromFetchHeadersWithLimit(\n headers: Headers,\n maxBytes: number,\n): HeaderCapture {\n const result: Record<string, string | string[]> = {};\n let truncated = false;\n let remaining = Number.isFinite(maxBytes) ? Math.max(0, maxBytes) : Number.POSITIVE_INFINITY;\n const setCookie = getSetCookie(headers);\n if (setCookie) {\n const values = takeHeaderValues('set-cookie', setCookie, remaining);\n remaining = values.remaining;\n if (values.truncated) {\n truncated = true;\n }\n if (values.values.length > 0) {\n result['set-cookie'] = values.values.length === 1 ? values.values[0]! : values.values;\n }\n }\n\n headers.forEach((value, key) => {\n const name = key.trim();\n if (!name) {\n return;\n }\n if (name.toLowerCase() === 'set-cookie' && setCookie) {\n return;\n }\n const values = takeHeaderValues(name, [value], remaining);\n remaining = values.remaining;\n if (values.truncated) {\n truncated = true;\n }\n if (values.values.length > 0) {\n result[name] = values.values.length === 1 ? values.values[0]! : values.values;\n }\n });\n\n return {\n headers: Object.keys(result).length === 0 ? {} : result,\n truncated,\n };\n}\n\nexport function headerTokenList(values: string[] | string | undefined): string[] {\n if (!values) {\n return [];\n }\n if (Array.isArray(values)) {\n return splitTokens(values);\n }\n return splitTokens([values]);\n}\n\nfunction splitTokens(values: string[]): string[] {\n const tokens: string[] = [];\n for (const value of values) {\n if (!value) {\n continue;\n }\n for (const part of value.split(',')) {\n const trimmed = part.trim();\n if (trimmed) {\n tokens.push(trimmed);\n }\n }\n }\n return tokens;\n}\n\nfunction getSetCookie(headers: Headers): string[] | null {\n const maybe = headers as Headers & { getSetCookie?: () => string[] };\n if (typeof maybe.getSetCookie === 'function') {\n const values = maybe.getSetCookie();\n return values.length > 0 ? values : null;\n }\n return null;\n}\n\nfunction takeHeaderValues(\n name: string,\n values: string[],\n remaining: number,\n): { values: string[]; remaining: number; truncated: boolean } {\n if (remaining <= 0) {\n return { remaining: 0, truncated: true, values: [] };\n }\n\n const taken: string[] = [];\n let used = 0;\n for (const value of values) {\n if (!value) {\n continue;\n }\n const size = name.length + value.length;\n if (used + size > remaining) {\n return { remaining: Math.max(0, remaining - used), truncated: true, values: taken };\n }\n used += size;\n taken.push(value);\n }\n\n return { remaining: Math.max(0, remaining - used), truncated: false, values: taken };\n}\n","import { headerTokenList } from './headers';\n\ntype HeaderValues = Record<string, string | string[]>;\n\nexport function isWebsocketUpgrade(\n statusCode: number,\n requestHeaders: HeaderValues | undefined,\n responseHeaders: HeaderValues | undefined,\n): boolean {\n if (statusCode !== 101) {\n return false;\n }\n\n if (headerHasToken(responseHeaders, 'upgrade', 'websocket')) {\n return true;\n }\n return headerHasToken(requestHeaders, 'upgrade', 'websocket');\n}\n\nexport function isWebsocketUpgradeFetch(\n statusCode: number,\n requestHeaders: Headers,\n responseHeaders: Headers,\n): boolean {\n if (statusCode !== 101) {\n return false;\n }\n\n if (headerHasTokenFetch(responseHeaders, 'upgrade', 'websocket')) {\n return true;\n }\n return headerHasTokenFetch(requestHeaders, 'upgrade', 'websocket');\n}\n\nfunction headerHasToken(headers: HeaderValues | undefined, name: string, token: string): boolean {\n if (!headers) {\n return false;\n }\n const values = headers[name] ?? headers[name.toLowerCase()] ?? headers[name.toUpperCase()];\n if (!values) {\n return false;\n }\n const tokens = headerTokenList(values);\n return tokens.some((value) => value.toLowerCase() === token.toLowerCase());\n}\n\nfunction headerHasTokenFetch(headers: Headers, name: string, token: string): boolean {\n const value = headers.get(name);\n if (!value) {\n return false;\n }\n return value.split(',').some((part) => part.trim().toLowerCase() === token.toLowerCase());\n}\n","import type { CaptureConfig, RedactionConfig } from './config';\nimport type { XrayContext } from './types';\nimport { bindObject, getContextFromObject, getContextState } from './state';\n\nexport { LimitedBuffer } from './limited_buffer';\nexport {\n headerValuesFromFetchHeaders,\n headerValuesFromFetchHeadersWithLimit,\n headerValuesFromNodeHeaders,\n headerTokenList,\n} from './headers';\nexport { isWebsocketUpgrade, isWebsocketUpgradeFetch } from './websocket';\nexport { makeCapturedBody } from './request_log';\nexport { logWithLevel } from './logger';\nexport { generateRequestId, uuidv7, uuidv7base48, uuidv7base62 } from './uuid';\n\nexport function bindContextToObject(target: object, ctx: XrayContext): void {\n const state = getContextState(ctx);\n if (!state) {\n return;\n }\n bindObject(target, state);\n}\n\nexport function getXrayContextFromObject(target: unknown): XrayContext | undefined {\n return getContextFromObject(target);\n}\n\nexport function setContextRoute(ctx: XrayContext, route: string): void {\n const state = getContextState(ctx);\n if (!state) {\n return;\n }\n const normalized =\n state.config.route.normalize && state.config.route.normalizer\n ? state.config.route.normalizer(route)\n : route;\n state.request.route = normalized;\n}\n\nexport function setContextRequestId(ctx: XrayContext, requestId: string): void {\n const state = getContextState(ctx);\n if (!state) {\n return;\n }\n state.request.requestId = requestId;\n state.context.requestId = requestId;\n}\n\nexport function setCaptureOverride(\n ctx: XrayContext,\n capture: Partial<CaptureConfig> | undefined,\n): void {\n const state = getContextState(ctx);\n if (!state || !capture) {\n return;\n }\n state.captureOverride = capture;\n}\n\nexport function setRedactionOverride(\n ctx: XrayContext,\n redaction: Partial<RedactionConfig> | undefined,\n): void {\n const state = getContextState(ctx);\n if (!state || !redaction) {\n return;\n }\n state.redactionOverride = redaction;\n}\n"]}