@visulima/pail 4.0.0-alpha.1 → 4.0.0-alpha.11

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 (91) hide show
  1. package/CHANGELOG.md +204 -0
  2. package/LICENSE.md +434 -52
  3. package/README.md +323 -0
  4. package/dist/error.d.ts +104 -0
  5. package/dist/error.js +76 -0
  6. package/dist/index.browser.d.ts +3 -1
  7. package/dist/index.browser.js +1490 -3
  8. package/dist/index.server.d.ts +3 -5
  9. package/dist/index.server.js +2380 -110
  10. package/dist/middleware/elysia.d.ts +71 -0
  11. package/dist/middleware/elysia.js +70 -0
  12. package/dist/middleware/express.d.ts +86 -0
  13. package/dist/middleware/express.js +29 -0
  14. package/dist/middleware/fastify.d.ts +81 -0
  15. package/dist/middleware/fastify.js +46 -0
  16. package/dist/middleware/hono.d.ts +85 -0
  17. package/dist/middleware/hono.js +33 -0
  18. package/dist/middleware/next/handler.d.ts +36 -0
  19. package/dist/middleware/next/handler.js +53 -0
  20. package/dist/middleware/next/middleware.d.ts +59 -0
  21. package/dist/middleware/next/storage.d.ts +14 -0
  22. package/dist/middleware/shared/create-middleware-logger.d.ts +82 -0
  23. package/dist/middleware/shared/headers.d.ts +14 -0
  24. package/dist/middleware/shared/routes.d.ts +30 -0
  25. package/dist/middleware/shared/storage.d.ts +29 -0
  26. package/dist/middleware/sveltekit.d.ts +123 -0
  27. package/dist/middleware/sveltekit.js +43 -0
  28. package/dist/object-tree.d.ts +2 -2
  29. package/dist/object-tree.js +7 -7
  30. package/dist/packem_shared/{AbstractJsonReporter-BaZ33PlE.js → AbstractJsonReporter-BO8Calb4.js} +112 -32
  31. package/dist/packem_shared/AbstractJsonReporter-nOj0Ft1F.js +284 -0
  32. package/dist/packem_shared/{JsonReporter-BRw4skd5.js → JsonReporter-CCmj7oYL.js} +2 -2
  33. package/dist/packem_shared/{JsonReporter-VzgyLEYz.js → JsonReporter-Ck2PIAEw.js} +2 -2
  34. package/dist/packem_shared/PrettyReporter-BCvyNzXO.js +2720 -0
  35. package/dist/packem_shared/{PrettyReporter-DySIXBjQ.js → PrettyReporter-BtTr13Ha.js} +55 -11
  36. package/dist/packem_shared/abstract-pretty-reporter-CXAKYCb8.js +2635 -0
  37. package/dist/packem_shared/constants-B1RjD_ps.js +99 -0
  38. package/dist/packem_shared/createPailError-B_sgL0nF.js +76 -0
  39. package/dist/packem_shared/headers-BxHWM6KI.js +127 -0
  40. package/dist/packem_shared/{index-BomQ3E6J.js → index-Bx3-C0j9.js} +29 -21
  41. package/dist/packem_shared/pailMiddleware-Ci88geIF.js +24 -0
  42. package/dist/packem_shared/storage-D0vqz8OX.js +36 -0
  43. package/dist/packem_shared/{InteractiveStreamHook-DiSubbJ1.js → useLogger-D0rU3lcX.js} +13 -1
  44. package/dist/packem_shared/{write-console-log-based-on-level-DBmRYXpj.js → write-console-log-based-on-level-ree2lDPw.js} +5 -4
  45. package/dist/packem_shared/{write-stream-BG8fhcs3.js → write-stream-MDqyXmc_.js} +1 -1
  46. package/dist/pail.browser.d.ts +1 -1
  47. package/dist/pail.server.d.ts +1 -76
  48. package/dist/processor/caller/caller-processor.js +1 -1
  49. package/dist/processor/environment-processor.d.ts +124 -0
  50. package/dist/processor/environment-processor.js +89 -0
  51. package/dist/processor/message-formatter-processor.d.ts +2 -3
  52. package/dist/processor/message-formatter-processor.js +654 -5
  53. package/dist/processor/opentelemetry-processor.js +4 -4
  54. package/dist/processor/redact-processor.d.ts +1 -1
  55. package/dist/processor/redact-processor.js +2 -1
  56. package/dist/processor/sampling-processor.d.ts +111 -0
  57. package/dist/processor/sampling-processor.js +59 -0
  58. package/dist/reporter/file/json-file-reporter.js +1 -1
  59. package/dist/reporter/http/abstract-http-reporter.js +23 -26
  60. package/dist/reporter/http/http-reporter.edge-light.js +134 -57
  61. package/dist/reporter/json/abstract-json-reporter.d.ts +1 -1
  62. package/dist/reporter/json/index.browser.js +2 -2
  63. package/dist/reporter/json/index.js +2 -2
  64. package/dist/reporter/pretty/index.browser.js +1 -1
  65. package/dist/reporter/pretty/index.js +1 -1
  66. package/dist/reporter/pretty/pretty-reporter.server.d.ts +1 -1
  67. package/dist/reporter/raw/raw-reporter.server.d.ts +1 -1
  68. package/dist/reporter/simple/simple-reporter.server.d.ts +1 -1
  69. package/dist/reporter/simple/simple-reporter.server.js +8 -12
  70. package/dist/types.d.ts +4 -4
  71. package/dist/utils/write-console-log-based-on-level.d.ts +1 -1
  72. package/dist/wide-event.d.ts +300 -0
  73. package/dist/wide-event.js +284 -0
  74. package/package.json +73 -20
  75. package/dist/interactive/index.d.ts +0 -2
  76. package/dist/interactive/index.js +0 -2
  77. package/dist/interactive/interactive-manager.d.ts +0 -108
  78. package/dist/interactive/interactive-stream-hook.d.ts +0 -68
  79. package/dist/packem_shared/InteractiveManager-CZ85hGNW.js +0 -172
  80. package/dist/packem_shared/PrettyReporter-DgZB2eBG.js +0 -222
  81. package/dist/packem_shared/abstract-pretty-reporter-Di_sdm2r.js +0 -50
  82. package/dist/packem_shared/format-label-De49vNPd.js +0 -1193
  83. package/dist/packem_shared/get-longest-label-C9PWeyKq.js +0 -9
  84. package/dist/packem_shared/index-DqKWykfa.js +0 -1146
  85. package/dist/packem_shared/interactive-stream-hook-DG4BtN12.js +0 -141
  86. package/dist/packem_shared/pail.browser-u2CSR_af.js +0 -1427
  87. package/dist/progress-bar.d.ts +0 -136
  88. package/dist/progress-bar.js +0 -404
  89. package/dist/spinner.d.ts +0 -220
  90. package/dist/spinner.js +0 -2150
  91. package/dist/utils/ansi-escapes.d.ts +0 -4
@@ -9,7 +9,8 @@ class RedactProcessor {
9
9
  * @param options Additional redaction options
10
10
  */
11
11
  constructor(rules, options) {
12
- this.#redact = (input) => redact(input, rules || standardRules, options);
12
+ const effectiveRules = rules ?? standardRules;
13
+ this.#redact = (input) => redact(input, effectiveRules, options);
13
14
  }
14
15
  /**
15
16
  * Processes log metadata to redact sensitive information.
@@ -0,0 +1,111 @@
1
+ import type { Meta, Processor } from "../types.d.ts";
2
+ /**
3
+ * Head sampling configuration.
4
+ *
5
+ * Controls random sampling rates per log level. Each key is a log level name
6
+ * and the value is the percentage (0-100) of logs at that level to keep.
7
+ * Levels not listed default to 100 (keep all).
8
+ * @example
9
+ * ```typescript
10
+ * const headSampling: HeadSamplingConfig = {
11
+ * debug: 0, // Drop all debug logs
12
+ * informational: 10, // Keep 10% of info logs
13
+ * warning: 50, // Keep 50% of warning logs
14
+ * error: 100, // Keep all error logs
15
+ * };
16
+ * ```
17
+ */
18
+ type HeadSamplingConfig = Partial<Record<string, number>>;
19
+ /**
20
+ * Tail sampling condition function.
21
+ *
22
+ * A function that receives the log metadata and returns true if the log
23
+ * should be force-kept regardless of head sampling. This allows keeping
24
+ * important logs based on their content (e.g., errors, slow operations).
25
+ * @template L - The log level type
26
+ */
27
+ type TailSamplingCondition<L extends string = string> = (meta: Readonly<Meta<L>>) => boolean;
28
+ /**
29
+ * Sampling processor configuration options.
30
+ */
31
+ interface SamplingProcessorOptions<L extends string = string> {
32
+ /**
33
+ * Head sampling rates per log level.
34
+ *
35
+ * A map of log level to sampling percentage (0-100).
36
+ * Levels not specified default to 100 (keep all).
37
+ * Set to 0 to drop all logs at that level.
38
+ */
39
+ head?: HeadSamplingConfig;
40
+ /**
41
+ * Tail sampling conditions.
42
+ *
43
+ * An array of condition functions that can force-keep a log entry
44
+ * even if it was dropped by head sampling. If any condition returns true,
45
+ * the log is kept.
46
+ */
47
+ tail?: TailSamplingCondition<L>[];
48
+ }
49
+ /**
50
+ * Sampling Processor.
51
+ *
52
+ * Inspired by evlog's production sampling strategy, this processor implements
53
+ * both head sampling (random per-level) and tail sampling (force-keep based
54
+ * on conditions) to control log volume in production environments.
55
+ *
56
+ * **Head sampling** randomly drops a percentage of logs per level. This is
57
+ * evaluated first and provides broad volume control.
58
+ *
59
+ * **Tail sampling** can override head sampling to force-keep important logs
60
+ * based on their content. For example, you might drop 90% of info logs but
61
+ * force-keep any that contain error information or relate to slow operations.
62
+ *
63
+ * When a log is dropped by sampling, the processor sets a `__dropped: true`
64
+ * boolean flag on the meta object. Reporters should check for this flag and
65
+ * skip entries where `__dropped` is `true`.
66
+ * @template L - The log level type
67
+ * @example
68
+ * ```typescript
69
+ * import { createPail } from "@visulima/pail";
70
+ * import SamplingProcessor from "@visulima/pail/processor/sampling";
71
+ *
72
+ * const logger = createPail({
73
+ * processors: [
74
+ * new SamplingProcessor({
75
+ * head: {
76
+ * debug: 0, // Drop all debug logs
77
+ * informational: 10, // Keep 10% of info logs
78
+ * warning: 50, // Keep 50% of warnings
79
+ * error: 100, // Keep all errors
80
+ * },
81
+ * tail: [
82
+ * // Force-keep logs with errors regardless of head sampling
83
+ * (meta) => meta.error !== undefined,
84
+ * // Force-keep logs from critical scopes
85
+ * (meta) => meta.scope?.includes("payment") ?? false,
86
+ * ],
87
+ * }),
88
+ * ],
89
+ * });
90
+ * ```
91
+ */
92
+ declare class SamplingProcessor<L extends string = string> implements Processor<L> {
93
+ #private;
94
+ /**
95
+ * Creates a new SamplingProcessor instance.
96
+ * @param options Sampling configuration options
97
+ */
98
+ constructor(options?: SamplingProcessorOptions<L>);
99
+ /**
100
+ * Processes log metadata to apply sampling rules.
101
+ *
102
+ * First evaluates head sampling (random per-level), then checks tail
103
+ * sampling conditions. If a log is dropped, the meta is marked with
104
+ * `__dropped: true` so reporters can skip it.
105
+ * @param meta The log metadata to process
106
+ * @returns The processed metadata, potentially marked as dropped
107
+ */
108
+ process(meta: Meta<L>): Meta<L>;
109
+ }
110
+ export default SamplingProcessor;
111
+ export type { HeadSamplingConfig, SamplingProcessorOptions, TailSamplingCondition };
@@ -0,0 +1,59 @@
1
+ class SamplingProcessor {
2
+ #headRates;
3
+ #tailConditions;
4
+ /**
5
+ * Creates a new SamplingProcessor instance.
6
+ * @param options Sampling configuration options
7
+ */
8
+ constructor(options = {}) {
9
+ this.#headRates = options.head ?? {};
10
+ this.#tailConditions = options.tail ?? [];
11
+ }
12
+ /**
13
+ * Processes log metadata to apply sampling rules.
14
+ *
15
+ * First evaluates head sampling (random per-level), then checks tail
16
+ * sampling conditions. If a log is dropped, the meta is marked with
17
+ * `__dropped: true` so reporters can skip it.
18
+ * @param meta The log metadata to process
19
+ * @returns The processed metadata, potentially marked as dropped
20
+ */
21
+ process(meta) {
22
+ const level = meta.type.level;
23
+ if (this.#shouldDrop(level) && !this.#shouldForceKeep(meta)) {
24
+ return { ...meta, dropped: true };
25
+ }
26
+ return meta;
27
+ }
28
+ /**
29
+ * Evaluates head sampling for the given log level.
30
+ * @returns true if the log should be dropped
31
+ */
32
+ #shouldDrop(level) {
33
+ const rate = this.#headRates[level];
34
+ if (rate === void 0) {
35
+ return false;
36
+ }
37
+ if (rate <= 0) {
38
+ return true;
39
+ }
40
+ if (rate >= 100) {
41
+ return false;
42
+ }
43
+ return Math.random() * 100 >= rate;
44
+ }
45
+ /**
46
+ * Evaluates tail sampling conditions.
47
+ * @returns true if any condition forces keeping the log
48
+ */
49
+ #shouldForceKeep(meta) {
50
+ for (let i = 0; i < this.#tailConditions.length; i += 1) {
51
+ if (this.#tailConditions[i](meta)) {
52
+ return true;
53
+ }
54
+ }
55
+ return false;
56
+ }
57
+ }
58
+
59
+ export { SamplingProcessor as default };
@@ -1,4 +1,4 @@
1
- import { AbstractJsonReporter } from '../../packem_shared/AbstractJsonReporter-BaZ33PlE.js';
1
+ import { AbstractJsonReporter } from '../../packem_shared/AbstractJsonReporter-nOj0Ft1F.js';
2
2
 
3
3
  class SafeStreamHandler {
4
4
  #ready = true;
@@ -20,7 +20,7 @@ const __cjs_getBuiltinModule = (module) => {
20
20
  const {
21
21
  Buffer
22
22
  } = __cjs_getBuiltinModule("node:buffer");
23
- import { AbstractJsonReporter } from '../../packem_shared/AbstractJsonReporter-BaZ33PlE.js';
23
+ import { AbstractJsonReporter } from '../../packem_shared/AbstractJsonReporter-nOj0Ft1F.js';
24
24
  const {
25
25
  gzipSync
26
26
  } = __cjs_getBuiltinModule("node:zlib");
@@ -33,24 +33,25 @@ const compressData = async (data) => {
33
33
  const reader = stream.readable.getReader();
34
34
  const encoder = new TextEncoder();
35
35
  const chunks = [];
36
- writer.write(encoder.encode(data));
37
- writer.close();
36
+ await writer.write(encoder.encode(data));
37
+ await writer.close();
38
38
  let done = false;
39
39
  while (!done) {
40
- const result2 = await reader.read();
41
- done = result2.done ?? false;
42
- if (result2.value) {
43
- chunks.push(result2.value);
40
+ const result = await reader.read();
41
+ done = result.done;
42
+ if (result.value) {
43
+ chunks.push(result.value);
44
44
  }
45
45
  }
46
46
  const totalLength = chunks.reduce((accumulator, chunk) => accumulator + chunk.length, 0);
47
- const result = new Uint8Array(totalLength);
47
+ const resultBuffer = new Uint8Array(totalLength);
48
48
  let offset = 0;
49
- for (const chunk of chunks) {
50
- result.set(chunk, offset);
49
+ for (let i = 0; i < chunks.length; i += 1) {
50
+ const chunk = chunks[i];
51
+ resultBuffer.set(chunk, offset);
51
52
  offset += chunk.length;
52
53
  }
53
- return result;
54
+ return resultBuffer;
54
55
  }
55
56
  return gzipSync(data);
56
57
  };
@@ -125,7 +126,7 @@ const processResponse = async (response, url, method, headers, body, onDebugRequ
125
126
  return false;
126
127
  }
127
128
  if (response.status < 500 && response.status !== 429) {
128
- const error = new Error(`HTTP ${response.status}: ${response.statusText}`);
129
+ const error = new Error(`HTTP ${String(response.status)}: ${response.statusText}`);
129
130
  if (onError) {
130
131
  onError(error);
131
132
  }
@@ -185,7 +186,7 @@ const sendWithRetry = async (url, method, headers, body, maxRetries, retryDelay,
185
186
  continue;
186
187
  }
187
188
  if (!response.ok) {
188
- const error = new Error(`HTTP ${response.status}: ${response.statusText}`);
189
+ const error = new Error(`HTTP ${String(response.status)}: ${response.statusText}`);
189
190
  if (onError) {
190
191
  onError(error);
191
192
  }
@@ -298,7 +299,7 @@ class AbstractHttpReporter extends AbstractJsonReporter {
298
299
  const logEntrySize = this.edgeCompat || typeof TextEncoder === "undefined" ? Buffer.byteLength(payload, "utf8") : new TextEncoder().encode(payload).length;
299
300
  if (logEntrySize > this.maxLogSize) {
300
301
  const error = new LogSizeError(
301
- `Log entry exceeds maximum size of ${this.maxLogSize} bytes. Size: ${logEntrySize} bytes`,
302
+ `Log entry exceeds maximum size of ${String(this.maxLogSize)} bytes. Size: ${String(logEntrySize)} bytes`,
302
303
  { data: payloadTemplate.data, logLevel: logLevelString, message: messageString },
303
304
  logEntrySize,
304
305
  this.maxLogSize
@@ -330,17 +331,15 @@ class AbstractHttpReporter extends AbstractJsonReporter {
330
331
  const payloadSizeWithEntry = this.currentBatchSize + logEntrySize + this.batchSendDelimiter.length;
331
332
  const payloadSizeThreshold = this.maxPayloadSize * 0.9;
332
333
  if (payloadSizeWithEntry > payloadSizeThreshold && this.batchQueue.length > 0) {
333
- this.processBatch();
334
+ void this.processBatch();
334
335
  }
335
336
  this.batchQueue.push(payload);
336
337
  this.currentBatchSize += logEntrySize + this.batchSendDelimiter.length;
337
- if (!this.batchTimeout) {
338
- this.batchTimeout = setTimeout(() => {
339
- this.processBatch();
340
- }, this.batchSendTimeout);
341
- }
338
+ this.batchTimeout ??= setTimeout(() => {
339
+ void this.processBatch();
340
+ }, this.batchSendTimeout);
342
341
  if (this.batchQueue.length >= this.batchSize) {
343
- this.processBatch();
342
+ void this.processBatch();
344
343
  }
345
344
  }
346
345
  /**
@@ -371,7 +370,7 @@ class AbstractHttpReporter extends AbstractJsonReporter {
371
370
  } finally {
372
371
  this.isProcessingBatch = false;
373
372
  if (this.batchQueue.length > 0) {
374
- this.processBatch();
373
+ void this.processBatch();
375
374
  }
376
375
  }
377
376
  }
@@ -404,9 +403,7 @@ class AbstractHttpReporter extends AbstractJsonReporter {
404
403
  */
405
404
  async sendPayload(payload, contentType) {
406
405
  const headers = typeof this.headers === "function" ? this.headers() : { ...this.headers };
407
- if (!headers["content-type"]) {
408
- headers["content-type"] = contentType ?? this.contentType;
409
- }
406
+ headers["content-type"] ??= contentType ?? this.contentType;
410
407
  let finalPayload = payload;
411
408
  if (this.compression && !this.edgeCompat) {
412
409
  try {
@@ -414,7 +411,7 @@ class AbstractHttpReporter extends AbstractJsonReporter {
414
411
  headers["content-encoding"] = "gzip";
415
412
  } catch (error) {
416
413
  if (this.onError) {
417
- this.onError(new Error(`Compression failed: ${error}`));
414
+ this.onError(new Error(`Compression failed: ${String(error)}`));
418
415
  }
419
416
  }
420
417
  }
@@ -36,7 +36,7 @@ const ErrorProto = Object.create(
36
36
  {},
37
37
  {
38
38
  cause: {
39
- enumerable: true,
39
+ enumerable: false,
40
40
  value: void 0,
41
41
  writable: true
42
42
  },
@@ -46,62 +46,89 @@ const ErrorProto = Object.create(
46
46
  writable: true
47
47
  },
48
48
  errors: {
49
- enumerable: true,
49
+ enumerable: false,
50
50
  value: void 0,
51
51
  writable: true
52
52
  },
53
53
  message: {
54
- enumerable: true,
54
+ enumerable: false,
55
55
  value: void 0,
56
56
  writable: true
57
57
  },
58
58
  name: {
59
- enumerable: true,
59
+ enumerable: false,
60
60
  value: void 0,
61
61
  writable: true
62
62
  },
63
63
  stack: {
64
- enumerable: true,
64
+ enumerable: false,
65
65
  value: void 0,
66
66
  writable: true
67
67
  }
68
68
  }
69
69
  );
70
70
  const toJsonWasCalled = /* @__PURE__ */ new WeakSet();
71
+ const makePropertiesEnumerable = (object) => {
72
+ const props = Object.getOwnPropertyNames(object);
73
+ for (const prop of props) {
74
+ const descriptor = Object.getOwnPropertyDescriptor(object, prop);
75
+ if (descriptor) {
76
+ if (!descriptor.enumerable) {
77
+ Object.defineProperty(object, prop, {
78
+ ...descriptor,
79
+ enumerable: true
80
+ });
81
+ }
82
+ if (descriptor.value && typeof descriptor.value === "object" && !Array.isArray(descriptor.value) && (Object.getPrototypeOf(descriptor.value) === Object.prototype || Object.getPrototypeOf(descriptor.value) === null)) {
83
+ makePropertiesEnumerable(descriptor.value);
84
+ }
85
+ }
86
+ }
87
+ };
71
88
  const toJSON = (from) => {
72
89
  toJsonWasCalled.add(from);
73
90
  const json = from.toJSON();
74
91
  toJsonWasCalled.delete(from);
92
+ if (
93
+ // Only make properties enumerable if the object is extensible
94
+ // Non-extensible objects (like when toJSON returns 'this') should preserve original enumerability
95
+ Object.isExtensible(json)
96
+ ) {
97
+ makePropertiesEnumerable(json);
98
+ }
75
99
  return json;
76
100
  };
77
101
  const serializeValue = (value, seen, depth, options) => {
78
102
  if (value && value instanceof Uint8Array && value.constructor.name === "Buffer") {
79
103
  return "[object Buffer]";
80
104
  }
81
- if (value !== null && typeof value === "object" && typeof value.pipe === "function") {
105
+ if (value !== null && typeof value === "object" && "pipe" in value && typeof value.pipe === "function") {
82
106
  return "[object Stream]";
83
107
  }
84
108
  if (value instanceof Error) {
85
- if (seen.includes(value)) {
109
+ if (seen.has(value)) {
86
110
  return "[Circular]";
87
111
  }
88
112
  depth += 1;
89
113
  return _serialize(value, options, seen, depth);
90
114
  }
91
- if (options.useToJSON && typeof value.toJSON === "function") {
115
+ if (options.useToJSON && value !== null && typeof value === "object" && "toJSON" in value && typeof value.toJSON === "function") {
92
116
  return value.toJSON();
93
117
  }
94
- if (typeof value === "object" && value instanceof Date) {
118
+ if (value instanceof Date) {
95
119
  return value.toISOString();
96
120
  }
97
121
  if (typeof value === "function") {
98
122
  return `[Function: ${value.name || "anonymous"}]`;
99
123
  }
124
+ if (typeof value === "bigint") {
125
+ return `${String(value)}n`;
126
+ }
100
127
  if (isPlainObject(value)) {
101
- depth += 1;
102
- if (options.maxDepth && depth >= options.maxDepth) {
128
+ if (options.maxDepth !== void 0 && options.maxDepth !== Number.POSITIVE_INFINITY && depth + 1 >= options.maxDepth) {
103
129
  return {};
104
130
  }
131
+ depth += 1;
105
132
  const plainObject = {};
106
133
  for (const key in value) {
107
134
  plainObject[key] = serializeValue(value[key], seen, depth, options);
@@ -115,7 +142,7 @@ const serializeValue = (value, seen, depth, options) => {
115
142
  }
116
143
  };
117
144
  const _serialize = (error, options, seen, depth) => {
118
- seen.push(error);
145
+ seen.add(error);
119
146
  if (options.maxDepth === 0) {
120
147
  return {};
121
148
  }
@@ -123,31 +150,88 @@ const _serialize = (error, options, seen, depth) => {
123
150
  return toJSON(error);
124
151
  }
125
152
  const protoError = Object.create(ErrorProto);
126
- protoError.name = Object.prototype.toString.call(error.constructor) === "[object Function]" ? error.constructor.name : error.name;
127
- protoError.message = error.message;
128
- protoError.stack = error.stack;
153
+ Object.defineProperty(protoError, "name", {
154
+ configurable: true,
155
+ enumerable: true,
156
+ value: Object.prototype.toString.call(error.constructor) === "[object Function]" ? error.constructor.name : error.name,
157
+ writable: true
158
+ });
159
+ Object.defineProperty(protoError, "message", {
160
+ configurable: true,
161
+ enumerable: true,
162
+ value: error.message,
163
+ writable: true
164
+ });
165
+ Object.defineProperty(protoError, "stack", {
166
+ configurable: true,
167
+ enumerable: true,
168
+ value: error.stack,
169
+ writable: true
170
+ });
129
171
  if (Array.isArray(error.errors)) {
130
172
  const aggregateErrors = [];
131
173
  for (const aggregateError of error.errors) {
132
174
  if (!(aggregateError instanceof Error)) {
133
175
  throw new TypeError("All errors in the 'errors' property must be instances of Error");
134
176
  }
135
- if (seen.includes(aggregateError)) {
136
- protoError.errors = [];
177
+ if (seen.has(aggregateError)) {
178
+ Object.defineProperty(protoError, "errors", {
179
+ configurable: true,
180
+ enumerable: true,
181
+ value: [],
182
+ writable: true
183
+ });
137
184
  return protoError;
138
185
  }
139
186
  aggregateErrors.push(_serialize(aggregateError, options, seen, depth));
140
187
  }
141
- protoError.errors = aggregateErrors;
188
+ Object.defineProperty(protoError, "errors", {
189
+ configurable: true,
190
+ enumerable: true,
191
+ value: aggregateErrors,
192
+ writable: true
193
+ });
142
194
  }
143
- if (error.cause instanceof Error && !seen.includes(error.cause)) {
144
- protoError.cause = _serialize(error.cause, options, seen, depth);
195
+ const causeValue = error.cause;
196
+ if (causeValue !== void 0 && causeValue !== null) {
197
+ if (causeValue instanceof Error) {
198
+ if (seen.has(causeValue)) {
199
+ Object.defineProperty(protoError, "cause", {
200
+ configurable: true,
201
+ enumerable: true,
202
+ value: "[Circular]",
203
+ writable: true
204
+ });
205
+ } else {
206
+ Object.defineProperty(protoError, "cause", {
207
+ configurable: true,
208
+ enumerable: true,
209
+ value: _serialize(causeValue, options, seen, depth),
210
+ writable: true
211
+ });
212
+ }
213
+ } else {
214
+ const serializedCause = serializeValue(causeValue, seen, depth, options);
215
+ Object.defineProperty(protoError, "cause", {
216
+ configurable: true,
217
+ enumerable: true,
218
+ value: serializedCause,
219
+ writable: true
220
+ });
221
+ }
145
222
  }
146
223
  for (const key in error) {
147
- if (protoError[key] === void 0) {
148
- const value = error[key];
149
- protoError[key] = serializeValue(value, seen, depth, options);
224
+ if (key === "name" || key === "message" || key === "stack" || key === "cause" || key === "errors") {
225
+ continue;
150
226
  }
227
+ const value = error[key];
228
+ const serializedValue = serializeValue(value, seen, depth, options);
229
+ Object.defineProperty(protoError, key, {
230
+ configurable: true,
231
+ enumerable: true,
232
+ value: serializedValue,
233
+ writable: true
234
+ });
151
235
  }
152
236
  if (Array.isArray(options.exclude) && options.exclude.length > 0) {
153
237
  for (const key of options.exclude) {
@@ -166,7 +250,7 @@ const serialize = (error, options = {}) => _serialize(
166
250
  maxDepth: options.maxDepth ?? Number.POSITIVE_INFINITY,
167
251
  useToJSON: options.useToJSON ?? false
168
252
  },
169
- [],
253
+ /* @__PURE__ */ new Set(),
170
254
  0
171
255
  );
172
256
 
@@ -188,7 +272,6 @@ class AbstractJsonReporter {
188
272
  * Sets a custom stringify function for object serialization.
189
273
  * @param function_ The stringify function to use for serialization
190
274
  */
191
- // eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-explicit-any
192
275
  setStringify(function_) {
193
276
  this.stringify = function_;
194
277
  }
@@ -199,19 +282,16 @@ class AbstractJsonReporter {
199
282
  rest.label = rest.label.trim();
200
283
  }
201
284
  if (file) {
202
- rest.file = `${file.name}:${file.line}${file.column ? `:${file.column}` : ""}`;
203
- }
204
- if (message === EMPTY_SYMBOL) {
205
- rest.message = void 0;
206
- } else {
207
- rest.message = message;
285
+ rest.file = `${file.name ?? ""}:${String(file.line)}${file.column ? `:${String(file.column)}` : ""}`;
208
286
  }
287
+ rest.message = message === EMPTY_SYMBOL ? void 0 : message;
209
288
  if (error) {
210
289
  rest.error = serialize(error, this.errorOptions);
211
290
  }
212
291
  if (context) {
213
292
  const newContext = [];
214
- for (const item of context) {
293
+ for (let i = 0; i < context.length; i += 1) {
294
+ const item = context[i];
215
295
  if (item === EMPTY_SYMBOL) {
216
296
  continue;
217
297
  }
@@ -235,24 +315,25 @@ const compressData = async (data) => {
235
315
  const reader = stream.readable.getReader();
236
316
  const encoder = new TextEncoder();
237
317
  const chunks = [];
238
- writer.write(encoder.encode(data));
239
- writer.close();
318
+ await writer.write(encoder.encode(data));
319
+ await writer.close();
240
320
  let done = false;
241
321
  while (!done) {
242
- const result2 = await reader.read();
243
- done = result2.done ?? false;
244
- if (result2.value) {
245
- chunks.push(result2.value);
322
+ const result = await reader.read();
323
+ done = result.done;
324
+ if (result.value) {
325
+ chunks.push(result.value);
246
326
  }
247
327
  }
248
328
  const totalLength = chunks.reduce((accumulator, chunk) => accumulator + chunk.length, 0);
249
- const result = new Uint8Array(totalLength);
329
+ const resultBuffer = new Uint8Array(totalLength);
250
330
  let offset = 0;
251
- for (const chunk of chunks) {
252
- result.set(chunk, offset);
331
+ for (let i = 0; i < chunks.length; i += 1) {
332
+ const chunk = chunks[i];
333
+ resultBuffer.set(chunk, offset);
253
334
  offset += chunk.length;
254
335
  }
255
- return result;
336
+ return resultBuffer;
256
337
  }
257
338
  return gzipSync(data);
258
339
  };
@@ -327,7 +408,7 @@ const processResponse = async (response, url, method, headers, body, onDebugRequ
327
408
  return false;
328
409
  }
329
410
  if (response.status < 500 && response.status !== 429) {
330
- const error = new Error(`HTTP ${response.status}: ${response.statusText}`);
411
+ const error = new Error(`HTTP ${String(response.status)}: ${response.statusText}`);
331
412
  if (onError) {
332
413
  onError(error);
333
414
  }
@@ -387,7 +468,7 @@ const sendWithRetry = async (url, method, headers, body, maxRetries, retryDelay,
387
468
  continue;
388
469
  }
389
470
  if (!response.ok) {
390
- const error = new Error(`HTTP ${response.status}: ${response.statusText}`);
471
+ const error = new Error(`HTTP ${String(response.status)}: ${response.statusText}`);
391
472
  if (onError) {
392
473
  onError(error);
393
474
  }
@@ -500,7 +581,7 @@ class AbstractHttpReporter extends AbstractJsonReporter {
500
581
  const logEntrySize = this.edgeCompat || typeof TextEncoder === "undefined" ? Buffer.byteLength(payload, "utf8") : new TextEncoder().encode(payload).length;
501
582
  if (logEntrySize > this.maxLogSize) {
502
583
  const error = new LogSizeError(
503
- `Log entry exceeds maximum size of ${this.maxLogSize} bytes. Size: ${logEntrySize} bytes`,
584
+ `Log entry exceeds maximum size of ${String(this.maxLogSize)} bytes. Size: ${String(logEntrySize)} bytes`,
504
585
  { data: payloadTemplate.data, logLevel: logLevelString, message: messageString },
505
586
  logEntrySize,
506
587
  this.maxLogSize
@@ -532,17 +613,15 @@ class AbstractHttpReporter extends AbstractJsonReporter {
532
613
  const payloadSizeWithEntry = this.currentBatchSize + logEntrySize + this.batchSendDelimiter.length;
533
614
  const payloadSizeThreshold = this.maxPayloadSize * 0.9;
534
615
  if (payloadSizeWithEntry > payloadSizeThreshold && this.batchQueue.length > 0) {
535
- this.processBatch();
616
+ void this.processBatch();
536
617
  }
537
618
  this.batchQueue.push(payload);
538
619
  this.currentBatchSize += logEntrySize + this.batchSendDelimiter.length;
539
- if (!this.batchTimeout) {
540
- this.batchTimeout = setTimeout(() => {
541
- this.processBatch();
542
- }, this.batchSendTimeout);
543
- }
620
+ this.batchTimeout ??= setTimeout(() => {
621
+ void this.processBatch();
622
+ }, this.batchSendTimeout);
544
623
  if (this.batchQueue.length >= this.batchSize) {
545
- this.processBatch();
624
+ void this.processBatch();
546
625
  }
547
626
  }
548
627
  /**
@@ -573,7 +652,7 @@ class AbstractHttpReporter extends AbstractJsonReporter {
573
652
  } finally {
574
653
  this.isProcessingBatch = false;
575
654
  if (this.batchQueue.length > 0) {
576
- this.processBatch();
655
+ void this.processBatch();
577
656
  }
578
657
  }
579
658
  }
@@ -606,9 +685,7 @@ class AbstractHttpReporter extends AbstractJsonReporter {
606
685
  */
607
686
  async sendPayload(payload, contentType) {
608
687
  const headers = typeof this.headers === "function" ? this.headers() : { ...this.headers };
609
- if (!headers["content-type"]) {
610
- headers["content-type"] = contentType ?? this.contentType;
611
- }
688
+ headers["content-type"] ??= contentType ?? this.contentType;
612
689
  let finalPayload = payload;
613
690
  if (this.compression && !this.edgeCompat) {
614
691
  try {
@@ -616,7 +693,7 @@ class AbstractHttpReporter extends AbstractJsonReporter {
616
693
  headers["content-encoding"] = "gzip";
617
694
  } catch (error) {
618
695
  if (this.onError) {
619
- this.onError(new Error(`Compression failed: ${error}`));
696
+ this.onError(new Error(`Compression failed: ${String(error)}`));
620
697
  }
621
698
  }
622
699
  }