@squasher-ai/browser-logger 0.1.1 → 0.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (47) hide show
  1. package/LICENSE +21 -21
  2. package/README.md +1 -1
  3. package/dist/_vendor/result-runtime/attempt.d.ts +17 -0
  4. package/dist/_vendor/result-runtime/attempt.js +62 -0
  5. package/dist/_vendor/sdk-runtime/batching/index.d.ts +42 -0
  6. package/dist/_vendor/sdk-runtime/batching/index.js +48 -0
  7. package/dist/_vendor/sdk-runtime/errors/headers.d.ts +6 -0
  8. package/dist/_vendor/sdk-runtime/errors/headers.js +44 -0
  9. package/dist/_vendor/sdk-runtime/errors/index.d.ts +95 -0
  10. package/dist/_vendor/sdk-runtime/errors/index.js +157 -0
  11. package/dist/_vendor/sdk-runtime/headers.d.ts +48 -0
  12. package/dist/_vendor/sdk-runtime/headers.js +67 -0
  13. package/dist/_vendor/sdk-runtime/platform.d.ts +33 -0
  14. package/dist/_vendor/sdk-runtime/platform.js +173 -0
  15. package/dist/_vendor/sdk-runtime/retry.d.ts +50 -0
  16. package/dist/_vendor/sdk-runtime/retry.js +104 -0
  17. package/dist/_vendor/sdk-runtime/runtime/actionable-error.d.ts +37 -0
  18. package/dist/_vendor/sdk-runtime/runtime/actionable-error.js +123 -0
  19. package/dist/_vendor/sdk-runtime/runtime/environment.d.ts +18 -0
  20. package/dist/_vendor/sdk-runtime/runtime/environment.js +81 -0
  21. package/dist/_vendor/sdk-runtime/runtime/public-sdk-runtime.d.ts +12 -0
  22. package/dist/_vendor/sdk-runtime/runtime/public-sdk-runtime.js +38 -0
  23. package/dist/_vendor/sdk-runtime/runtime/redaction.d.ts +14 -0
  24. package/dist/_vendor/sdk-runtime/runtime/redaction.js +120 -0
  25. package/dist/_vendor/sdk-runtime/runtime/release.d.ts +35 -0
  26. package/dist/_vendor/sdk-runtime/runtime/release.js +120 -0
  27. package/dist/_vendor/sdk-runtime/sampling/index.d.ts +43 -0
  28. package/dist/_vendor/sdk-runtime/sampling/index.js +70 -0
  29. package/dist/browser-logger.d.ts +2 -3
  30. package/dist/browser-logger.js +5 -5
  31. package/dist/browser-logger.umd.js +598 -131
  32. package/dist/index.d.ts +4 -5
  33. package/dist/index.js +2 -2
  34. package/dist/serializer.d.ts +1 -2
  35. package/dist/serializer.js +62 -75
  36. package/dist/transport.d.ts +21 -5
  37. package/dist/transport.js +45 -42
  38. package/dist/types.d.ts +0 -1
  39. package/package.json +6 -6
  40. package/dist/browser-logger.d.ts.map +0 -1
  41. package/dist/global.d.ts +0 -14
  42. package/dist/global.d.ts.map +0 -1
  43. package/dist/global.js +0 -14
  44. package/dist/index.d.ts.map +0 -1
  45. package/dist/serializer.d.ts.map +0 -1
  46. package/dist/transport.d.ts.map +0 -1
  47. package/dist/types.d.ts.map +0 -1
@@ -3,60 +3,482 @@
3
3
  var __getOwnPropNames = Object.getOwnPropertyNames;
4
4
  var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
5
5
  var __hasOwnProp = Object.prototype.hasOwnProperty;
6
- var __moduleCache = /* @__PURE__ */ new WeakMap;
6
+ function __accessProp(key) {
7
+ return this[key];
8
+ }
7
9
  var __toCommonJS = (from) => {
8
- var entry = __moduleCache.get(from), desc;
10
+ var entry = (__moduleCache ??= new WeakMap).get(from), desc;
9
11
  if (entry)
10
12
  return entry;
11
13
  entry = __defProp({}, "__esModule", { value: true });
12
- if (from && typeof from === "object" || typeof from === "function")
13
- __getOwnPropNames(from).map((key) => !__hasOwnProp.call(entry, key) && __defProp(entry, key, {
14
- get: () => from[key],
15
- enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable
16
- }));
14
+ if (from && typeof from === "object" || typeof from === "function") {
15
+ for (var key of __getOwnPropNames(from))
16
+ if (!__hasOwnProp.call(entry, key))
17
+ __defProp(entry, key, {
18
+ get: __accessProp.bind(from, key),
19
+ enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable
20
+ });
21
+ }
17
22
  __moduleCache.set(from, entry);
18
23
  return entry;
19
24
  };
25
+ var __moduleCache;
26
+ var __returnValue = (v) => v;
27
+ function __exportSetter(name, newValue) {
28
+ this[name] = __returnValue.bind(null, newValue);
29
+ }
20
30
  var __export = (target, all) => {
21
31
  for (var name in all)
22
32
  __defProp(target, name, {
23
33
  get: all[name],
24
34
  enumerable: true,
25
35
  configurable: true,
26
- set: (newValue) => all[name] = () => newValue
36
+ set: __exportSetter.bind(all, name)
27
37
  });
28
38
  };
29
39
 
30
40
  // src/global.ts
31
41
  var exports_global = {};
32
42
  __export(exports_global, {
33
- initBrowserLogger: () => initBrowserLogger,
34
- getBrowserLogger: () => getBrowserLogger,
35
- flushBrowserLogger: () => flushBrowserLogger,
36
- default: () => global_default,
43
+ BrowserLogger: () => BrowserLogger,
37
44
  closeBrowserLogger: () => closeBrowserLogger,
38
- BrowserLogger: () => BrowserLogger
45
+ default: () => global_default,
46
+ flushBrowserLogger: () => flushBrowserLogger,
47
+ getBrowserLogger: () => getBrowserLogger,
48
+ initBrowserLogger: () => initBrowserLogger
39
49
  });
40
50
 
51
+ // ../sdk-core/dist/batching/index.js
52
+ var BODY_ENCODER = new TextEncoder;
53
+ // ../sdk-core/dist/errors/headers.js
54
+ function readHeader(headers, name) {
55
+ if (!headers)
56
+ return;
57
+ const get = readProperty(headers, "get");
58
+ if (isHeaderGetter(get)) {
59
+ try {
60
+ const value = get.call(headers, name);
61
+ return Object.prototype.toString.call(value) === "[object String]" ? String(value) : undefined;
62
+ } catch {
63
+ return;
64
+ }
65
+ }
66
+ const normalizedName = name.toLowerCase();
67
+ for (const [key, value] of Object.entries(Object(headers))) {
68
+ if (key.toLowerCase() === normalizedName && Object.prototype.toString.call(value) === "[object String]") {
69
+ return String(value);
70
+ }
71
+ }
72
+ return;
73
+ }
74
+ function isHeaderGetter(value) {
75
+ return Object.prototype.toString.call(value) === "[object Function]";
76
+ }
77
+ function readProperty(owner, key) {
78
+ try {
79
+ const target = Object(owner);
80
+ let cursor = target;
81
+ while (cursor) {
82
+ const descriptor = Object.getOwnPropertyDescriptor(cursor, key);
83
+ if (descriptor) {
84
+ return "value" in descriptor ? descriptor.value : descriptor.get?.call(target);
85
+ }
86
+ cursor = Object.getPrototypeOf(cursor);
87
+ }
88
+ return;
89
+ } catch {
90
+ return;
91
+ }
92
+ }
93
+
94
+ // ../sdk-core/dist/errors/index.js
95
+ class SquasherError extends Error {
96
+ constructor(message) {
97
+ super(message);
98
+ this.name = "SquasherError";
99
+ }
100
+ }
101
+
102
+ class SquasherApiError extends SquasherError {
103
+ status;
104
+ body;
105
+ requestId;
106
+ constructor(status, body, message, headers) {
107
+ super(buildMessage(body, message));
108
+ this.name = "SquasherApiError";
109
+ this.status = status;
110
+ this.body = body;
111
+ this.requestId = readHeader(headers, "x-request-id");
112
+ }
113
+ static generate(status, body, fallbackMessage, headers) {
114
+ if (status === 400)
115
+ return new BadRequestError(body, fallbackMessage, headers);
116
+ if (status === 401)
117
+ return new AuthenticationError(body, fallbackMessage, headers);
118
+ if (status === 403)
119
+ return new PermissionDeniedError(body, fallbackMessage, headers);
120
+ if (status === 404)
121
+ return new NotFoundError(body, fallbackMessage, headers);
122
+ if (status === 409)
123
+ return new ConflictError(body, fallbackMessage, headers);
124
+ if (status === 422)
125
+ return new UnprocessableEntityError(body, fallbackMessage, headers);
126
+ if (status === 429)
127
+ return new RateLimitError(body, fallbackMessage, headers);
128
+ if (status >= 500)
129
+ return new InternalServerError(status, body, fallbackMessage, headers);
130
+ return new SquasherApiError(status, body, fallbackMessage, headers);
131
+ }
132
+ }
133
+ function buildMessage(body, fallback) {
134
+ if (body?.error)
135
+ return body.error;
136
+ if (body?.message)
137
+ return body.message;
138
+ return fallback;
139
+ }
140
+
141
+ class BadRequestError extends SquasherApiError {
142
+ status = 400;
143
+ constructor(body, message, headers) {
144
+ super(400, body, message, headers);
145
+ this.name = "BadRequestError";
146
+ }
147
+ }
148
+
149
+ class AuthenticationError extends SquasherApiError {
150
+ status = 401;
151
+ constructor(body, message, headers) {
152
+ super(401, body, message, headers);
153
+ this.name = "AuthenticationError";
154
+ }
155
+ }
156
+
157
+ class PermissionDeniedError extends SquasherApiError {
158
+ status = 403;
159
+ constructor(body, message, headers) {
160
+ super(403, body, message, headers);
161
+ this.name = "PermissionDeniedError";
162
+ }
163
+ }
164
+
165
+ class NotFoundError extends SquasherApiError {
166
+ status = 404;
167
+ constructor(body, message, headers) {
168
+ super(404, body, message, headers);
169
+ this.name = "NotFoundError";
170
+ }
171
+ }
172
+
173
+ class ConflictError extends SquasherApiError {
174
+ status = 409;
175
+ constructor(body, message, headers) {
176
+ super(409, body, message, headers);
177
+ this.name = "ConflictError";
178
+ }
179
+ }
180
+
181
+ class UnprocessableEntityError extends SquasherApiError {
182
+ status = 422;
183
+ constructor(body, message, headers) {
184
+ super(422, body, message, headers);
185
+ this.name = "UnprocessableEntityError";
186
+ }
187
+ }
188
+
189
+ class RateLimitError extends SquasherApiError {
190
+ status = 429;
191
+ constructor(body, message, headers) {
192
+ super(429, body, message, headers);
193
+ this.name = "RateLimitError";
194
+ }
195
+ }
196
+
197
+ class InternalServerError extends SquasherApiError {
198
+ constructor(status, body, message, headers) {
199
+ super(status, body, message, headers);
200
+ this.name = "InternalServerError";
201
+ }
202
+ }
203
+ // ../sdk-core/dist/retry.js
204
+ var RETRYABLE_STATUSES = new Set([408, 429]);
205
+ // ../sdk-core/dist/runtime/release.js
206
+ var JUNK_VALUES = new Set([
207
+ "",
208
+ "undefined",
209
+ "null",
210
+ "nan",
211
+ "latest",
212
+ "unknown",
213
+ "(none)",
214
+ "n/a",
215
+ "none"
216
+ ]);
217
+ // ../sdk-core/dist/streaming/index.js
218
+ function findNewline(buffer, startIndex) {
219
+ for (let i = startIndex ?? 0;i < buffer.length; i++) {
220
+ if (buffer[i] === 10)
221
+ return { preceding: i, index: i + 1, carriage: false };
222
+ if (buffer[i] === 13)
223
+ return { preceding: i, index: i + 1, carriage: true };
224
+ }
225
+ return null;
226
+ }
227
+
228
+ class LineDecoder {
229
+ buffer = new Uint8Array;
230
+ carriageReturnIndex = null;
231
+ decoder = new TextDecoder("utf-8");
232
+ decode(chunk) {
233
+ const next = new Uint8Array(this.buffer.length + chunk.length);
234
+ next.set(this.buffer);
235
+ next.set(chunk, this.buffer.length);
236
+ this.buffer = next;
237
+ const lines = [];
238
+ let pat;
239
+ while ((pat = findNewline(this.buffer, this.carriageReturnIndex)) !== null) {
240
+ if (pat.carriage && this.carriageReturnIndex == null) {
241
+ this.carriageReturnIndex = pat.index;
242
+ continue;
243
+ }
244
+ if (this.carriageReturnIndex != null && (pat.index !== this.carriageReturnIndex + 1 || pat.carriage)) {
245
+ lines.push(this.decoder.decode(this.buffer.subarray(0, this.carriageReturnIndex - 1)));
246
+ this.buffer = this.buffer.subarray(this.carriageReturnIndex);
247
+ this.carriageReturnIndex = null;
248
+ continue;
249
+ }
250
+ const endIndex = this.carriageReturnIndex !== null ? pat.preceding - 1 : pat.preceding;
251
+ lines.push(this.decoder.decode(this.buffer.subarray(0, endIndex)));
252
+ this.buffer = this.buffer.subarray(pat.index);
253
+ this.carriageReturnIndex = null;
254
+ }
255
+ return lines;
256
+ }
257
+ flush() {
258
+ if (!this.buffer.length)
259
+ return [];
260
+ return this.decode(new Uint8Array([10]));
261
+ }
262
+ }
263
+
264
+ class SSEDecoder {
265
+ event = null;
266
+ data = [];
267
+ chunks = [];
268
+ decode(line) {
269
+ const stripped = line.endsWith("\r") ? line.slice(0, -1) : line;
270
+ if (!stripped) {
271
+ if (!this.event && this.data.length === 0)
272
+ return null;
273
+ const ev = {
274
+ event: this.event,
275
+ data: this.data.join(`
276
+ `),
277
+ raw: this.chunks
278
+ };
279
+ this.event = null;
280
+ this.data = [];
281
+ this.chunks = [];
282
+ return ev;
283
+ }
284
+ this.chunks.push(stripped);
285
+ if (stripped.startsWith(":"))
286
+ return null;
287
+ const colon = stripped.indexOf(":");
288
+ const fieldname = colon === -1 ? stripped : stripped.slice(0, colon);
289
+ let value = colon === -1 ? "" : stripped.slice(colon + 1);
290
+ if (value.startsWith(" "))
291
+ value = value.slice(1);
292
+ if (fieldname === "event")
293
+ this.event = value;
294
+ else if (fieldname === "data")
295
+ this.data.push(value);
296
+ return null;
297
+ }
298
+ }
299
+ async function* iterSSEChunks(body) {
300
+ const lineDecoder = new LineDecoder;
301
+ const sseDecoder = new SSEDecoder;
302
+ const reader = body.getReader();
303
+ try {
304
+ for (;; ) {
305
+ const { value, done } = await reader.read();
306
+ if (done)
307
+ break;
308
+ for (const line of lineDecoder.decode(value)) {
309
+ const ev = sseDecoder.decode(line);
310
+ if (ev)
311
+ yield ev;
312
+ }
313
+ }
314
+ for (const line of lineDecoder.flush()) {
315
+ const ev = sseDecoder.decode(line);
316
+ if (ev)
317
+ yield ev;
318
+ }
319
+ } finally {
320
+ try {
321
+ reader.releaseLock();
322
+ } catch {}
323
+ }
324
+ }
325
+ function isAbortError(e) {
326
+ return e.name === "AbortError" || e.name === "SquasherUserAbortError";
327
+ }
328
+ function coerceErrorBody(value) {
329
+ if (Object.prototype.toString.call(value) === "[object String]") {
330
+ return { error: String(value) };
331
+ }
332
+ if (isSSEDataObject(value)) {
333
+ const out = {};
334
+ if (Object.prototype.toString.call(value.error) === "[object String]") {
335
+ out.error = String(value.error);
336
+ }
337
+ if (Object.prototype.toString.call(value.message) === "[object String]") {
338
+ out.message = String(value.message);
339
+ }
340
+ if (Object.prototype.toString.call(value.code) === "[object String]") {
341
+ out.code = String(value.code);
342
+ }
343
+ return out;
344
+ }
345
+ return null;
346
+ }
347
+ function isSSEDataObject(value) {
348
+ return value instanceof Object && !Array.isArray(value);
349
+ }
350
+
351
+ class Stream {
352
+ controller;
353
+ iteratorFactory;
354
+ constructor(iteratorFactory, controller) {
355
+ this.controller = controller;
356
+ this.iteratorFactory = iteratorFactory;
357
+ }
358
+ static fromSSEResponse(response, controller, parse) {
359
+ let consumed = false;
360
+ async function* iterator() {
361
+ if (consumed) {
362
+ throw new Error("Cannot iterate over a consumed stream, use `.tee()` to split the stream.");
363
+ }
364
+ consumed = true;
365
+ if (!response.body) {
366
+ controller.abort();
367
+ throw new Error("Attempted to iterate over a response with no body");
368
+ }
369
+ let done = false;
370
+ try {
371
+ for await (const sse of iterSSEChunks(response.body)) {
372
+ if (done)
373
+ continue;
374
+ if (sse.data.startsWith("[DONE]")) {
375
+ done = true;
376
+ continue;
377
+ }
378
+ const parsed = JSON.parse(sse.data);
379
+ if (isSSEDataObject(parsed) && "error" in parsed) {
380
+ const body = coerceErrorBody(parsed.error);
381
+ throw SquasherApiError.generate(response.status, body, body?.error ?? body?.message ?? "stream error", response.headers);
382
+ }
383
+ yield parse ? parse(parsed) : parsed;
384
+ }
385
+ done = true;
386
+ } catch (e) {
387
+ if (e instanceof Error && isAbortError(e))
388
+ return;
389
+ throw e;
390
+ } finally {
391
+ if (!done)
392
+ controller.abort();
393
+ }
394
+ }
395
+ return new Stream(iterator, controller);
396
+ }
397
+ [Symbol.asyncIterator]() {
398
+ return this.iteratorFactory();
399
+ }
400
+ tee() {
401
+ const left = [];
402
+ const right = [];
403
+ const iterator = this.iteratorFactory();
404
+ const teeIterator = (queue) => ({
405
+ next: () => {
406
+ if (queue.length === 0) {
407
+ const result = Promise.resolve(iterator.next());
408
+ left.push(result);
409
+ right.push(result);
410
+ }
411
+ const queued = queue.shift();
412
+ if (!queued)
413
+ throw new Error("Stream tee queue was empty");
414
+ return queued;
415
+ }
416
+ });
417
+ return [
418
+ new Stream(() => teeIterator(left), this.controller),
419
+ new Stream(() => teeIterator(right), this.controller)
420
+ ];
421
+ }
422
+ toReadableStream() {
423
+ const factory = this.iteratorFactory;
424
+ let iter = null;
425
+ const encoder = new TextEncoder;
426
+ return new ReadableStream({
427
+ start() {
428
+ iter = factory();
429
+ },
430
+ async pull(ctrl) {
431
+ try {
432
+ if (!iter) {
433
+ ctrl.close();
434
+ return;
435
+ }
436
+ const { value, done } = await iter.next();
437
+ if (done) {
438
+ ctrl.close();
439
+ return;
440
+ }
441
+ ctrl.enqueue(encoder.encode(JSON.stringify(value) + `
442
+ `));
443
+ } catch (err) {
444
+ ctrl.error(err);
445
+ }
446
+ },
447
+ async cancel() {
448
+ await iter?.return?.();
449
+ }
450
+ });
451
+ }
452
+ }
453
+
454
+ // ../sdk-core/dist/index.js
455
+ var DEFAULT_INGEST_ENDPOINT = "https://ingest.squasher.ai";
456
+ var TRUTHY = new Set(["1", "true", "yes", "on"]);
457
+
41
458
  // src/serializer.ts
42
459
  var SDK_NAME = "@squasher-ai/browser-logger";
43
- var SDK_VERSION = "0.1.0";
460
+ var SDK_VERSION = "0.3.0";
461
+ var BOOLEAN_TAG = "[object Boolean]";
462
+ var FUNCTION_TAG = "[object Function]";
463
+ var NUMBER_TAG = "[object Number]";
464
+ var STRING_TAG = "[object String]";
465
+ var BIGINT_TAG = "[object BigInt]";
466
+ var SYMBOL_TAG = "[object Symbol]";
467
+ var UNDEFINED_TAG = "[object Undefined]";
44
468
  function buildConsoleEvent(args, level) {
45
469
  const error = findError(args);
46
- const pageUrl = getPageUrl();
47
- const userAgent = getUserAgent();
470
+ const pageUrl = globalThis.location?.href;
471
+ const userAgent = globalThis.navigator?.userAgent;
48
472
  const extra = {
49
473
  console_arguments: Array.from(args, (arg) => toJsonValue(arg)),
50
474
  console_method: level === "warning" ? "warn" : "error"
51
475
  };
52
- if (pageUrl) {
476
+ if (pageUrl)
53
477
  extra.page_url = pageUrl;
54
- }
55
- if (userAgent) {
478
+ if (userAgent)
56
479
  extra.user_agent = userAgent;
57
- }
58
480
  return {
59
- message: buildMessage(args, error),
481
+ message: buildMessage2(args, error),
60
482
  type: error?.name,
61
483
  stack: error?.stack,
62
484
  level,
@@ -69,128 +491,167 @@
69
491
  extra
70
492
  };
71
493
  }
72
- function buildMessage(args, error) {
73
- if (args.length === 0) {
494
+ function buildMessage2(args, error) {
495
+ if (args.length === 0)
74
496
  return "console.error";
75
- }
76
- const parts = Array.from(args, (arg) => formatMessagePart(arg)).filter((part) => part.length > 0);
77
- if (parts.length > 0) {
497
+ const parts = Array.from(args, formatMessagePart).filter((part) => part.length > 0);
498
+ if (parts.length > 0)
78
499
  return parts.join(" ");
79
- }
80
- if (error?.message) {
81
- return error.message;
82
- }
83
- return "console.error";
500
+ return error?.message || "console.error";
84
501
  }
85
502
  function formatMessagePart(value) {
86
- if (value instanceof Error) {
503
+ if (value instanceof Error)
87
504
  return value.message || value.name || "Error";
88
- }
89
- if (typeof value === "string") {
90
- return value;
91
- }
92
- if (typeof value === "number" || typeof value === "boolean" || typeof value === "bigint" || typeof value === "symbol") {
93
- return String(value);
94
- }
95
- if (value === null) {
505
+ if (value === null)
96
506
  return "null";
97
- }
98
- if (typeof value === "undefined") {
507
+ const tag = valueTag(value);
508
+ if (tag === UNDEFINED_TAG)
99
509
  return "undefined";
510
+ if (tag === STRING_TAG || tag === NUMBER_TAG || tag === BOOLEAN_TAG || tag === BIGINT_TAG || tag === SYMBOL_TAG) {
511
+ return String(value);
100
512
  }
101
513
  return stringifyJsonValue(toJsonValue(value));
102
514
  }
103
515
  function findError(args) {
104
516
  return Array.from(args).find((arg) => arg instanceof Error);
105
517
  }
106
- function getPageUrl() {
107
- if (typeof location === "undefined") {
108
- return;
109
- }
110
- return location.href;
111
- }
112
- function getUserAgent() {
113
- if (typeof navigator === "undefined") {
114
- return;
115
- }
116
- return navigator.userAgent;
117
- }
118
518
  function stringifyJsonValue(value) {
119
- if (typeof value === "string") {
120
- return value;
121
- }
122
- return JSON.stringify(value);
519
+ return valueTag(value) === STRING_TAG ? String(value) : JSON.stringify(value);
123
520
  }
124
521
  function toJsonValue(value) {
125
- if (value === null) {
522
+ if (value === null)
126
523
  return null;
127
- }
128
- if (typeof value === "string" || typeof value === "number" || typeof value === "boolean") {
129
- return value;
130
- }
131
- if (typeof value === "bigint" || typeof value === "symbol") {
524
+ const tag = valueTag(value);
525
+ if (tag === STRING_TAG)
132
526
  return String(value);
133
- }
134
- if (typeof value === "undefined") {
527
+ if (tag === NUMBER_TAG)
528
+ return Number(value);
529
+ if (tag === BOOLEAN_TAG)
530
+ return Boolean(value);
531
+ if (tag === BIGINT_TAG || tag === SYMBOL_TAG)
532
+ return String(value);
533
+ if (tag === UNDEFINED_TAG)
135
534
  return "undefined";
136
- }
137
- if (typeof value === "function") {
138
- return `[Function ${value.name || "anonymous"}]`;
139
- }
535
+ if (tag === FUNCTION_TAG)
536
+ return functionLabel(value);
140
537
  if (value instanceof Error) {
141
538
  const serializedError = {
142
539
  name: value.name,
143
540
  message: value.message
144
541
  };
145
- if (value.stack) {
542
+ if (value.stack)
146
543
  serializedError.stack = value.stack;
147
- }
148
544
  return serializedError;
149
545
  }
150
- if (Array.isArray(value)) {
546
+ if (Array.isArray(value))
151
547
  return value.map((item) => toJsonValue(item));
152
- }
153
548
  return serializeObject(value);
154
549
  }
155
550
  function serializeObject(value) {
156
551
  const seen = new WeakSet;
157
552
  const json = JSON.stringify(value, (_key, nestedValue) => {
158
- if (typeof nestedValue === "bigint" || typeof nestedValue === "symbol") {
553
+ const tag = valueTag(nestedValue);
554
+ if (tag === BIGINT_TAG || tag === SYMBOL_TAG)
159
555
  return String(nestedValue);
160
- }
161
- if (typeof nestedValue === "function") {
162
- return `[Function ${nestedValue.name || "anonymous"}]`;
163
- }
556
+ if (tag === FUNCTION_TAG)
557
+ return functionLabel(nestedValue);
164
558
  if (nestedValue instanceof Error) {
165
559
  const serializedError = {
166
560
  name: nestedValue.name,
167
561
  message: nestedValue.message
168
562
  };
169
- if (nestedValue.stack) {
563
+ if (nestedValue.stack)
170
564
  serializedError.stack = nestedValue.stack;
171
- }
172
565
  return serializedError;
173
566
  }
174
- if (typeof nestedValue === "object" && nestedValue !== null) {
175
- if (seen.has(nestedValue)) {
567
+ if (isReferenceTag(tag) && nestedValue !== null) {
568
+ if (seen.has(nestedValue))
176
569
  return "[Circular]";
177
- }
178
570
  seen.add(nestedValue);
179
571
  }
180
572
  return nestedValue;
181
573
  });
182
- if (!json) {
574
+ if (!json)
183
575
  return String(value);
576
+ const parsed = JSON.parse(json);
577
+ return parsed;
578
+ }
579
+ function valueTag(value) {
580
+ return Object.prototype.toString.call(value);
581
+ }
582
+ function isReferenceTag(tag) {
583
+ return ![BIGINT_TAG, BOOLEAN_TAG, NUMBER_TAG, STRING_TAG, SYMBOL_TAG, UNDEFINED_TAG].includes(tag);
584
+ }
585
+ function functionLabel(value) {
586
+ const source = String(value);
587
+ const match = source.match(/^(?:async\s+)?function\s*([^\s(]*)/);
588
+ return `[Function ${match?.[1] || "anonymous"}]`;
589
+ }
590
+
591
+ // ../result-utils/dist/index.js
592
+ function toError(cause, fallbackMessage = "Unexpected error") {
593
+ if (cause instanceof Error) {
594
+ return cause;
595
+ }
596
+ const nestedError = readProperty2(cause, "error");
597
+ if (nestedError instanceof Error)
598
+ return nestedError;
599
+ const messageValue = readProperty2(cause, "message");
600
+ if (Object.prototype.toString.call(messageValue) === "[object String]") {
601
+ const message = String(messageValue);
602
+ if (message.length > 0)
603
+ return new Error(message);
604
+ }
605
+ if (Object.prototype.toString.call(cause) === "[object String]") {
606
+ const message = String(cause);
607
+ if (message.length > 0)
608
+ return new Error(message);
609
+ }
610
+ return new Error(fallbackMessage, { cause });
611
+ }
612
+ function readProperty2(owner, key) {
613
+ try {
614
+ const target = Object(owner);
615
+ let cursor = target;
616
+ while (cursor) {
617
+ const descriptor = Object.getOwnPropertyDescriptor(cursor, key);
618
+ if (descriptor) {
619
+ return "value" in descriptor ? descriptor.value : descriptor.get?.call(target);
620
+ }
621
+ cursor = Object.getPrototypeOf(cursor);
622
+ }
623
+ return;
624
+ } catch {
625
+ return;
626
+ }
627
+ }
628
+ function attempt(options) {
629
+ try {
630
+ return options.try();
631
+ } catch (cause) {
632
+ const preservedCause = cause;
633
+ return options.catch({ cause: preservedCause, error: toError(preservedCause) });
634
+ } finally {
635
+ options.finally?.();
636
+ }
637
+ }
638
+ async function attemptAsync(options) {
639
+ try {
640
+ return await options.try();
641
+ } catch (cause) {
642
+ const preservedCause = cause;
643
+ return await options.catch({ cause: preservedCause, error: toError(preservedCause) });
644
+ } finally {
645
+ await options.finally?.();
184
646
  }
185
- return JSON.parse(json);
186
647
  }
187
648
 
188
649
  // src/transport.ts
189
- var DEFAULT_ENDPOINT = "https://ingest.squasher.ai";
190
650
  var DEFAULT_BATCH_SIZE = 10;
191
651
  var DEFAULT_FLUSH_INTERVAL_MS = 5000;
192
652
 
193
653
  class BrowserLoggerTransport {
654
+ runtime;
194
655
  apiKey;
195
656
  projectId;
196
657
  endpoint;
@@ -201,14 +662,15 @@
201
662
  this.flushOnPageHide();
202
663
  };
203
664
  handleVisibilityChange = () => {
204
- if (typeof document !== "undefined" && document.visibilityState === "hidden") {
665
+ if (this.runtime.document?.visibilityState === "hidden") {
205
666
  this.flushOnPageHide();
206
667
  }
207
668
  };
208
- constructor(config) {
669
+ constructor(config, runtime = defaultBrowserLoggerRuntime()) {
670
+ this.runtime = runtime;
209
671
  this.apiKey = config.apiKey;
210
672
  this.projectId = config.projectId;
211
- this.endpoint = normalizeEndpoint(config.endpoint ?? DEFAULT_ENDPOINT);
673
+ this.endpoint = normalizeEndpoint(config.endpoint ?? DEFAULT_INGEST_ENDPOINT);
212
674
  this.flushTimer = setInterval(() => {
213
675
  this.flush();
214
676
  }, DEFAULT_FLUSH_INTERVAL_MS);
@@ -262,49 +724,43 @@
262
724
  });
263
725
  }
264
726
  installListeners() {
265
- if (typeof document !== "undefined") {
266
- document.addEventListener("visibilitychange", this.handleVisibilityChange);
267
- }
268
- if (typeof window !== "undefined") {
269
- window.addEventListener("pagehide", this.handlePageHide);
270
- window.addEventListener("beforeunload", this.handlePageHide);
271
- }
727
+ this.runtime.document?.addEventListener("visibilitychange", this.handleVisibilityChange);
728
+ this.runtime.window?.addEventListener("pagehide", this.handlePageHide);
729
+ this.runtime.window?.addEventListener("beforeunload", this.handlePageHide);
272
730
  }
273
731
  removeListeners() {
274
- if (typeof document !== "undefined") {
275
- document.removeEventListener("visibilitychange", this.handleVisibilityChange);
276
- }
277
- if (typeof window !== "undefined") {
278
- window.removeEventListener("pagehide", this.handlePageHide);
279
- window.removeEventListener("beforeunload", this.handlePageHide);
280
- }
732
+ this.runtime.document?.removeEventListener("visibilitychange", this.handleVisibilityChange);
733
+ this.runtime.window?.removeEventListener("pagehide", this.handlePageHide);
734
+ this.runtime.window?.removeEventListener("beforeunload", this.handlePageHide);
281
735
  }
282
736
  trySendBeacon(body) {
283
- if (typeof navigator === "undefined" || typeof navigator.sendBeacon !== "function") {
284
- return false;
285
- }
286
- try {
287
- const blob = new Blob([body], { type: "application/json" });
288
- return navigator.sendBeacon(this.getBeaconUrl(), blob);
289
- } catch {
737
+ const sendBeacon = this.runtime.navigator?.sendBeacon;
738
+ if (!sendBeacon)
290
739
  return false;
291
- }
740
+ return attempt({
741
+ try: () => {
742
+ const blob = new Blob([body], { type: "application/json" });
743
+ return sendBeacon.call(this.runtime.navigator, this.getBeaconUrl(), blob);
744
+ },
745
+ catch: () => false
746
+ });
292
747
  }
293
748
  async sendFetch(body) {
294
- try {
295
- const response = await fetch(this.getIngestUrl(), {
296
- method: "POST",
297
- headers: {
298
- "Content-Type": "application/json",
299
- "x-squasher-key": this.apiKey
300
- },
301
- body,
302
- keepalive: true
303
- });
304
- return response.ok;
305
- } catch {
306
- return false;
307
- }
749
+ return attemptAsync({
750
+ try: async () => {
751
+ const response = await this.runtime.fetcher(this.getIngestUrl(), {
752
+ method: "POST",
753
+ headers: {
754
+ "Content-Type": "application/json",
755
+ "x-squasher-key": this.apiKey
756
+ },
757
+ body,
758
+ keepalive: true
759
+ });
760
+ return response.ok;
761
+ },
762
+ catch: () => false
763
+ });
308
764
  }
309
765
  getIngestUrl() {
310
766
  return `${this.endpoint}/v1/ingest/${this.projectId}`;
@@ -313,6 +769,14 @@
313
769
  return `${this.getIngestUrl()}?key=${encodeURIComponent(this.apiKey)}`;
314
770
  }
315
771
  }
772
+ function defaultBrowserLoggerRuntime() {
773
+ return {
774
+ document: globalThis.document,
775
+ fetcher: (...args) => fetch(...args),
776
+ navigator: globalThis.navigator,
777
+ window: globalThis.window
778
+ };
779
+ }
316
780
  function normalizeEndpoint(endpoint) {
317
781
  return endpoint.replace(/\/+$/, "");
318
782
  }
@@ -322,8 +786,6 @@
322
786
  }
323
787
 
324
788
  // src/browser-logger.ts
325
- var DEFAULT_ENDPOINT2 = "https://ingest.squasher.ai";
326
-
327
789
  class BrowserLogger {
328
790
  config;
329
791
  transport;
@@ -356,7 +818,7 @@
356
818
  }
357
819
  const originalConsoleError = this.originalConsoleError;
358
820
  console.error = (...args) => {
359
- Reflect.apply(originalConsoleError, console, args);
821
+ originalConsoleError.call(console, ...args);
360
822
  this.transport.enqueue(buildConsoleEvent(args, "error"));
361
823
  };
362
824
  this.installed = true;
@@ -373,7 +835,7 @@
373
835
  return {
374
836
  apiKey: config.apiKey,
375
837
  projectId: config.projectId,
376
- endpoint: config.endpoint ?? DEFAULT_ENDPOINT2,
838
+ endpoint: config.endpoint ?? DEFAULT_INGEST_ENDPOINT,
377
839
  captureConsoleErrors: config.captureConsoleErrors ?? true
378
840
  };
379
841
  }
@@ -415,6 +877,11 @@
415
877
  init: initBrowserLogger,
416
878
  initBrowserLogger
417
879
  };
418
- globalThis.SquasherBrowserLogger = browserLoggerGlobal;
880
+ Object.defineProperty(globalThis, "SquasherBrowserLogger", {
881
+ configurable: true,
882
+ enumerable: true,
883
+ value: browserLoggerGlobal,
884
+ writable: true
885
+ });
419
886
  var global_default = browserLoggerGlobal;
420
887
  })();