@squasher-ai/browser-logger 0.1.0 → 0.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -21
- package/dist/browser-logger.d.ts +2 -2
- package/dist/browser-logger.d.ts.map +1 -1
- package/dist/browser-logger.js +5 -5
- package/dist/browser-logger.umd.js +597 -130
- package/dist/global.d.ts +1 -1
- package/dist/global.d.ts.map +1 -1
- package/dist/global.js +7 -2
- package/dist/index.d.ts +4 -4
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +2 -2
- package/dist/serializer.d.ts +1 -1
- package/dist/serializer.d.ts.map +1 -1
- package/dist/serializer.js +61 -74
- package/dist/transport.d.ts +21 -4
- package/dist/transport.d.ts.map +1 -1
- package/dist/transport.js +45 -42
- package/package.json +11 -7
|
@@ -3,60 +3,482 @@
|
|
|
3
3
|
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
4
4
|
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
5
5
|
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
6
|
-
|
|
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
|
-
|
|
14
|
-
|
|
15
|
-
|
|
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: (
|
|
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
|
-
|
|
34
|
-
getBrowserLogger: () => getBrowserLogger,
|
|
35
|
-
flushBrowserLogger: () => flushBrowserLogger,
|
|
36
|
-
default: () => global_default,
|
|
43
|
+
BrowserLogger: () => BrowserLogger,
|
|
37
44
|
closeBrowserLogger: () => closeBrowserLogger,
|
|
38
|
-
|
|
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
460
|
var SDK_VERSION = "0.1.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 =
|
|
47
|
-
const userAgent =
|
|
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:
|
|
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
|
|
73
|
-
if (args.length === 0)
|
|
494
|
+
function buildMessage2(args, error) {
|
|
495
|
+
if (args.length === 0)
|
|
74
496
|
return "console.error";
|
|
75
|
-
|
|
76
|
-
|
|
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 (
|
|
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
|
-
|
|
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 (
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
553
|
+
const tag = valueTag(nestedValue);
|
|
554
|
+
if (tag === BIGINT_TAG || tag === SYMBOL_TAG)
|
|
159
555
|
return String(nestedValue);
|
|
160
|
-
|
|
161
|
-
|
|
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 (
|
|
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 (
|
|
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 ??
|
|
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
|
-
|
|
266
|
-
|
|
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
|
-
|
|
275
|
-
|
|
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
|
-
|
|
284
|
-
|
|
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
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
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
|
-
|
|
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 ??
|
|
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
|
|
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
|
})();
|