capacitor-gleap-plugin 18.1.0 → 19.0.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/CapacitorGleapPlugin.podspec +7 -2
- package/Package.swift +31 -0
- package/README.md +247 -759
- package/android/build.gradle +1 -1
- package/android/src/main/java/io/gleapplugins/capacitor/GleapPlugin.java +184 -37
- package/dist/docs.json +267 -3893
- package/dist/esm/definitions.d.ts +145 -3
- package/dist/esm/definitions.js.map +1 -1
- package/dist/esm/index.js +9 -1
- package/dist/esm/index.js.map +1 -1
- package/dist/esm/logs/body.d.ts +58 -0
- package/dist/esm/logs/body.js +303 -0
- package/dist/esm/logs/body.js.map +1 -0
- package/dist/esm/logs/consoleCapture.d.ts +29 -0
- package/dist/esm/logs/consoleCapture.js +189 -0
- package/dist/esm/logs/consoleCapture.js.map +1 -0
- package/dist/esm/logs/format.d.ts +16 -0
- package/dist/esm/logs/format.js +394 -0
- package/dist/esm/logs/format.js.map +1 -0
- package/dist/esm/logs/networkCapture.d.ts +65 -0
- package/dist/esm/logs/networkCapture.js +654 -0
- package/dist/esm/logs/networkCapture.js.map +1 -0
- package/dist/esm/logs/redaction.d.ts +54 -0
- package/dist/esm/logs/redaction.js +388 -0
- package/dist/esm/logs/redaction.js.map +1 -0
- package/dist/esm/logs/webViewLogs.d.ts +70 -0
- package/dist/esm/logs/webViewLogs.js +297 -0
- package/dist/esm/logs/webViewLogs.js.map +1 -0
- package/dist/esm/logs/zone.d.ts +5 -0
- package/dist/esm/logs/zone.js +15 -0
- package/dist/esm/logs/zone.js.map +1 -0
- package/dist/esm/web.d.ts +37 -2
- package/dist/esm/web.js +34 -0
- package/dist/esm/web.js.map +1 -1
- package/dist/plugin.cjs.js +2254 -1
- package/dist/plugin.cjs.js.map +1 -1
- package/dist/plugin.js +2254 -1
- package/dist/plugin.js.map +1 -1
- package/ios/{Plugin → Sources/GleapPlugin}/GleapPlugin.swift +195 -12
- package/package.json +18 -4
- package/ios/Plugin/GleapPlugin.h +0 -10
- package/ios/Plugin/GleapPlugin.m +0 -68
- package/ios/Plugin/Info.plist +0 -24
|
@@ -0,0 +1,394 @@
|
|
|
1
|
+
export const MAX_LOG_LENGTH = 1000;
|
|
2
|
+
export const MAX_ERROR_LOG_LENGTH = 5000;
|
|
3
|
+
export const TRUNCATED_SUFFIX = '… [truncated]';
|
|
4
|
+
const MAX_DEPTH = 5;
|
|
5
|
+
const MAX_KEYS = 50;
|
|
6
|
+
const MAX_ITEMS = 50;
|
|
7
|
+
/** Keeps the head of a log line so the result (incl. the suffix) fits max chars. */
|
|
8
|
+
export function truncateLog(text, max) {
|
|
9
|
+
if (text.length <= max) {
|
|
10
|
+
return text;
|
|
11
|
+
}
|
|
12
|
+
let end = Math.max(0, max - TRUNCATED_SUFFIX.length);
|
|
13
|
+
const last = text.charCodeAt(end - 1);
|
|
14
|
+
if (last >= 0xd800 && last <= 0xdbff) {
|
|
15
|
+
end--;
|
|
16
|
+
}
|
|
17
|
+
return text.slice(0, end) + TRUNCATED_SUFFIX;
|
|
18
|
+
}
|
|
19
|
+
/**
|
|
20
|
+
* Formats console arguments like the browser console does (printf-style %s %d %i %f %o %O %c in
|
|
21
|
+
* the first string), with objects as depth-limited JSON. Stops early once the text exceeds the
|
|
22
|
+
* budget, so logging a huge object stays cheap.
|
|
23
|
+
*/
|
|
24
|
+
export function formatConsoleArgs(args, budget) {
|
|
25
|
+
if (!args || args.length === 0) {
|
|
26
|
+
return '';
|
|
27
|
+
}
|
|
28
|
+
let out = '';
|
|
29
|
+
let index = 0;
|
|
30
|
+
const first = args[0];
|
|
31
|
+
if (typeof first === 'string' && first.indexOf('%') > -1 && args.length > 1) {
|
|
32
|
+
index = 1;
|
|
33
|
+
for (let i = 0; i < first.length && out.length <= budget; i++) {
|
|
34
|
+
const char = first[i];
|
|
35
|
+
if (char !== '%' || i + 1 >= first.length) {
|
|
36
|
+
out += char;
|
|
37
|
+
continue;
|
|
38
|
+
}
|
|
39
|
+
const specifier = first[i + 1];
|
|
40
|
+
if (specifier === '%') {
|
|
41
|
+
out += '%';
|
|
42
|
+
i++;
|
|
43
|
+
continue;
|
|
44
|
+
}
|
|
45
|
+
if ('sdifoOc'.indexOf(specifier) < 0 || index >= args.length) {
|
|
46
|
+
out += char;
|
|
47
|
+
continue;
|
|
48
|
+
}
|
|
49
|
+
const arg = args[index++];
|
|
50
|
+
i++;
|
|
51
|
+
switch (specifier) {
|
|
52
|
+
case 's':
|
|
53
|
+
out += typeof arg === 'string' ? arg : formatValue(arg, budget);
|
|
54
|
+
break;
|
|
55
|
+
case 'd':
|
|
56
|
+
case 'i':
|
|
57
|
+
out += formatInteger(arg);
|
|
58
|
+
break;
|
|
59
|
+
case 'f':
|
|
60
|
+
out += formatFloat(arg);
|
|
61
|
+
break;
|
|
62
|
+
case 'o':
|
|
63
|
+
case 'O':
|
|
64
|
+
out += formatValue(arg, budget);
|
|
65
|
+
break;
|
|
66
|
+
default:
|
|
67
|
+
// %c (CSS) consumes its argument and prints nothing.
|
|
68
|
+
break;
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
for (; index < args.length && out.length <= budget; index++) {
|
|
73
|
+
const arg = args[index];
|
|
74
|
+
const text = typeof arg === 'string' ? arg : formatValue(arg, budget);
|
|
75
|
+
out = out.length > 0 ? `${out} ${text}` : text;
|
|
76
|
+
}
|
|
77
|
+
return out;
|
|
78
|
+
}
|
|
79
|
+
function formatInteger(value) {
|
|
80
|
+
if (typeof value === 'number') {
|
|
81
|
+
return String(value < 0 ? Math.ceil(value) : Math.floor(value));
|
|
82
|
+
}
|
|
83
|
+
if (typeof value === 'bigint') {
|
|
84
|
+
return String(value);
|
|
85
|
+
}
|
|
86
|
+
if (typeof value === 'string') {
|
|
87
|
+
return String(parseInt(value, 10));
|
|
88
|
+
}
|
|
89
|
+
return 'NaN';
|
|
90
|
+
}
|
|
91
|
+
function formatFloat(value) {
|
|
92
|
+
if (typeof value === 'number') {
|
|
93
|
+
return String(value);
|
|
94
|
+
}
|
|
95
|
+
if (typeof value === 'string') {
|
|
96
|
+
return String(parseFloat(value));
|
|
97
|
+
}
|
|
98
|
+
return 'NaN';
|
|
99
|
+
}
|
|
100
|
+
/** A single value as text: strings as they are, errors with their stack, objects as JSON. */
|
|
101
|
+
export function formatValue(value, budget) {
|
|
102
|
+
try {
|
|
103
|
+
if (typeof value === 'string') {
|
|
104
|
+
return value;
|
|
105
|
+
}
|
|
106
|
+
if (isError(value)) {
|
|
107
|
+
return formatError(value);
|
|
108
|
+
}
|
|
109
|
+
if (value === null || (typeof value !== 'object' && typeof value !== 'function')) {
|
|
110
|
+
return formatPrimitive(value);
|
|
111
|
+
}
|
|
112
|
+
const serializer = new Serializer(budget);
|
|
113
|
+
serializer.write(value, 0);
|
|
114
|
+
return serializer.result();
|
|
115
|
+
}
|
|
116
|
+
catch (e) {
|
|
117
|
+
return '[unserializable value]';
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
/** "Name: message" followed by the stack (V8 stacks already start with that line). */
|
|
121
|
+
export function formatError(error) {
|
|
122
|
+
try {
|
|
123
|
+
const err = error;
|
|
124
|
+
const name = typeof err.name === 'string' && err.name ? err.name : 'Error';
|
|
125
|
+
const message = typeof err.message === 'string' ? err.message : '';
|
|
126
|
+
const head = message ? `${name}: ${message}` : name;
|
|
127
|
+
const stack = typeof err.stack === 'string' ? err.stack.trim() : '';
|
|
128
|
+
if (!stack) {
|
|
129
|
+
return head;
|
|
130
|
+
}
|
|
131
|
+
if (stack.indexOf(head) === 0) {
|
|
132
|
+
return stack;
|
|
133
|
+
}
|
|
134
|
+
return `${head}\n${stack}`;
|
|
135
|
+
}
|
|
136
|
+
catch (e) {
|
|
137
|
+
return 'Error';
|
|
138
|
+
}
|
|
139
|
+
}
|
|
140
|
+
export function isError(value) {
|
|
141
|
+
if (!value || typeof value !== 'object') {
|
|
142
|
+
return false;
|
|
143
|
+
}
|
|
144
|
+
if (typeof Error !== 'undefined' && value instanceof Error) {
|
|
145
|
+
return true;
|
|
146
|
+
}
|
|
147
|
+
const candidate = value;
|
|
148
|
+
return (typeof candidate.message === 'string' && typeof candidate.stack === 'string' && typeof candidate.name === 'string');
|
|
149
|
+
}
|
|
150
|
+
function formatPrimitive(value) {
|
|
151
|
+
if (typeof value === 'bigint') {
|
|
152
|
+
return `${value}n`;
|
|
153
|
+
}
|
|
154
|
+
if (typeof value === 'symbol') {
|
|
155
|
+
return value.toString();
|
|
156
|
+
}
|
|
157
|
+
return String(value);
|
|
158
|
+
}
|
|
159
|
+
function describeFunction(value) {
|
|
160
|
+
const name = value.name;
|
|
161
|
+
return `[Function: ${typeof name === 'string' && name ? name : 'anonymous'}]`;
|
|
162
|
+
}
|
|
163
|
+
function describeNode(value) {
|
|
164
|
+
if (typeof Node === 'undefined' || !(value instanceof Node)) {
|
|
165
|
+
return null;
|
|
166
|
+
}
|
|
167
|
+
if (typeof Element !== 'undefined' && value instanceof Element) {
|
|
168
|
+
let text = `<${value.tagName.toLowerCase()}`;
|
|
169
|
+
if (value.id) {
|
|
170
|
+
text += `#${value.id}`;
|
|
171
|
+
}
|
|
172
|
+
const className = value.getAttribute('class');
|
|
173
|
+
if (className) {
|
|
174
|
+
text += `.${className.trim().split(/\s+/).join('.')}`;
|
|
175
|
+
}
|
|
176
|
+
return `${text}>`;
|
|
177
|
+
}
|
|
178
|
+
return value.nodeName;
|
|
179
|
+
}
|
|
180
|
+
function constructorName(value) {
|
|
181
|
+
try {
|
|
182
|
+
const proto = Object.getPrototypeOf(value);
|
|
183
|
+
if (!proto) {
|
|
184
|
+
return '';
|
|
185
|
+
}
|
|
186
|
+
const ctor = proto.constructor;
|
|
187
|
+
const name = ctor && typeof ctor.name === 'string' ? ctor.name : '';
|
|
188
|
+
return name === 'Object' ? '' : name;
|
|
189
|
+
}
|
|
190
|
+
catch (e) {
|
|
191
|
+
return '';
|
|
192
|
+
}
|
|
193
|
+
}
|
|
194
|
+
/** JSON-like serialiser with depth, key and length limits and circular protection. */
|
|
195
|
+
class Serializer {
|
|
196
|
+
constructor(budget) {
|
|
197
|
+
this.budget = budget;
|
|
198
|
+
this.parts = [];
|
|
199
|
+
this.length = 0;
|
|
200
|
+
this.ancestors = [];
|
|
201
|
+
}
|
|
202
|
+
result() {
|
|
203
|
+
return this.parts.join('');
|
|
204
|
+
}
|
|
205
|
+
isFull() {
|
|
206
|
+
return this.length > this.budget;
|
|
207
|
+
}
|
|
208
|
+
push(text) {
|
|
209
|
+
if (this.isFull()) {
|
|
210
|
+
return;
|
|
211
|
+
}
|
|
212
|
+
this.parts.push(text);
|
|
213
|
+
this.length += text.length;
|
|
214
|
+
}
|
|
215
|
+
write(value, depth) {
|
|
216
|
+
if (this.isFull()) {
|
|
217
|
+
return;
|
|
218
|
+
}
|
|
219
|
+
if (value === null || value === undefined) {
|
|
220
|
+
this.push(String(value));
|
|
221
|
+
return;
|
|
222
|
+
}
|
|
223
|
+
switch (typeof value) {
|
|
224
|
+
case 'string':
|
|
225
|
+
this.push(JSON.stringify(value));
|
|
226
|
+
return;
|
|
227
|
+
case 'number':
|
|
228
|
+
case 'boolean':
|
|
229
|
+
case 'bigint':
|
|
230
|
+
case 'symbol':
|
|
231
|
+
this.push(formatPrimitive(value));
|
|
232
|
+
return;
|
|
233
|
+
case 'function':
|
|
234
|
+
this.push(describeFunction(value));
|
|
235
|
+
return;
|
|
236
|
+
default:
|
|
237
|
+
break;
|
|
238
|
+
}
|
|
239
|
+
this.writeObject(value, depth);
|
|
240
|
+
}
|
|
241
|
+
writeObject(value, depth) {
|
|
242
|
+
if (this.ancestors.indexOf(value) > -1) {
|
|
243
|
+
this.push('[Circular]');
|
|
244
|
+
return;
|
|
245
|
+
}
|
|
246
|
+
if (isError(value)) {
|
|
247
|
+
this.push(JSON.stringify(formatError(value).split('\n')[0]));
|
|
248
|
+
return;
|
|
249
|
+
}
|
|
250
|
+
if (value instanceof Date) {
|
|
251
|
+
this.push(isNaN(value.getTime()) ? '"Invalid Date"' : JSON.stringify(value.toISOString()));
|
|
252
|
+
return;
|
|
253
|
+
}
|
|
254
|
+
if (value instanceof RegExp) {
|
|
255
|
+
this.push(String(value));
|
|
256
|
+
return;
|
|
257
|
+
}
|
|
258
|
+
const node = describeNode(value);
|
|
259
|
+
if (node !== null) {
|
|
260
|
+
this.push(node);
|
|
261
|
+
return;
|
|
262
|
+
}
|
|
263
|
+
if (typeof window !== 'undefined' && value === window) {
|
|
264
|
+
this.push('[Window]');
|
|
265
|
+
return;
|
|
266
|
+
}
|
|
267
|
+
if (typeof ArrayBuffer !== 'undefined') {
|
|
268
|
+
if (value instanceof ArrayBuffer) {
|
|
269
|
+
this.push(`[ArrayBuffer(${value.byteLength})]`);
|
|
270
|
+
return;
|
|
271
|
+
}
|
|
272
|
+
if (ArrayBuffer.isView(value)) {
|
|
273
|
+
const length = value.length;
|
|
274
|
+
this.push(`[${constructorName(value) || 'ArrayBufferView'}(${typeof length === 'number' ? length : value.byteLength})]`);
|
|
275
|
+
return;
|
|
276
|
+
}
|
|
277
|
+
}
|
|
278
|
+
if (typeof Promise !== 'undefined' && value instanceof Promise) {
|
|
279
|
+
this.push('[Promise]');
|
|
280
|
+
return;
|
|
281
|
+
}
|
|
282
|
+
const isArray = Array.isArray(value);
|
|
283
|
+
if (depth >= MAX_DEPTH) {
|
|
284
|
+
this.push(isArray ? `[Array(${value.length})]` : '[Object]');
|
|
285
|
+
return;
|
|
286
|
+
}
|
|
287
|
+
this.ancestors.push(value);
|
|
288
|
+
try {
|
|
289
|
+
if (isArray) {
|
|
290
|
+
this.writeArray(value, depth);
|
|
291
|
+
}
|
|
292
|
+
else if (typeof Map !== 'undefined' && value instanceof Map) {
|
|
293
|
+
this.writeMap(value, depth);
|
|
294
|
+
}
|
|
295
|
+
else if (typeof Set !== 'undefined' && value instanceof Set) {
|
|
296
|
+
this.writeSet(value, depth);
|
|
297
|
+
}
|
|
298
|
+
else {
|
|
299
|
+
this.writePlainObject(value, depth);
|
|
300
|
+
}
|
|
301
|
+
}
|
|
302
|
+
finally {
|
|
303
|
+
this.ancestors.pop();
|
|
304
|
+
}
|
|
305
|
+
}
|
|
306
|
+
writeArray(value, depth) {
|
|
307
|
+
this.push('[');
|
|
308
|
+
const count = Math.min(value.length, MAX_ITEMS);
|
|
309
|
+
for (let i = 0; i < count && !this.isFull(); i++) {
|
|
310
|
+
if (i > 0) {
|
|
311
|
+
this.push(',');
|
|
312
|
+
}
|
|
313
|
+
this.write(value[i], depth + 1);
|
|
314
|
+
}
|
|
315
|
+
if (value.length > MAX_ITEMS) {
|
|
316
|
+
this.push(`,"… ${value.length - MAX_ITEMS} more"`);
|
|
317
|
+
}
|
|
318
|
+
this.push(']');
|
|
319
|
+
}
|
|
320
|
+
writeMap(value, depth) {
|
|
321
|
+
this.push(`Map(${value.size}) {`);
|
|
322
|
+
let count = 0;
|
|
323
|
+
value.forEach((item, key) => {
|
|
324
|
+
if (count >= MAX_ITEMS || this.isFull()) {
|
|
325
|
+
return;
|
|
326
|
+
}
|
|
327
|
+
if (count > 0) {
|
|
328
|
+
this.push(', ');
|
|
329
|
+
}
|
|
330
|
+
this.write(key, depth + 1);
|
|
331
|
+
this.push(' => ');
|
|
332
|
+
this.write(item, depth + 1);
|
|
333
|
+
count++;
|
|
334
|
+
});
|
|
335
|
+
this.push('}');
|
|
336
|
+
}
|
|
337
|
+
writeSet(value, depth) {
|
|
338
|
+
this.push(`Set(${value.size}) {`);
|
|
339
|
+
let count = 0;
|
|
340
|
+
value.forEach((item) => {
|
|
341
|
+
if (count >= MAX_ITEMS || this.isFull()) {
|
|
342
|
+
return;
|
|
343
|
+
}
|
|
344
|
+
if (count > 0) {
|
|
345
|
+
this.push(', ');
|
|
346
|
+
}
|
|
347
|
+
this.write(item, depth + 1);
|
|
348
|
+
count++;
|
|
349
|
+
});
|
|
350
|
+
this.push('}');
|
|
351
|
+
}
|
|
352
|
+
writePlainObject(value, depth) {
|
|
353
|
+
const record = value;
|
|
354
|
+
if (typeof record.toJSON === 'function') {
|
|
355
|
+
let converted;
|
|
356
|
+
try {
|
|
357
|
+
converted = record.toJSON();
|
|
358
|
+
}
|
|
359
|
+
catch (e) {
|
|
360
|
+
converted = undefined;
|
|
361
|
+
}
|
|
362
|
+
if (converted !== undefined && converted !== value) {
|
|
363
|
+
this.write(converted, depth + 1);
|
|
364
|
+
return;
|
|
365
|
+
}
|
|
366
|
+
}
|
|
367
|
+
const name = constructorName(value);
|
|
368
|
+
if (name) {
|
|
369
|
+
this.push(`${name} `);
|
|
370
|
+
}
|
|
371
|
+
this.push('{');
|
|
372
|
+
const keys = Object.keys(record);
|
|
373
|
+
const count = Math.min(keys.length, MAX_KEYS);
|
|
374
|
+
for (let i = 0; i < count && !this.isFull(); i++) {
|
|
375
|
+
if (i > 0) {
|
|
376
|
+
this.push(',');
|
|
377
|
+
}
|
|
378
|
+
this.push(`${JSON.stringify(keys[i])}:`);
|
|
379
|
+
let child;
|
|
380
|
+
try {
|
|
381
|
+
child = record[keys[i]];
|
|
382
|
+
}
|
|
383
|
+
catch (e) {
|
|
384
|
+
child = '[getter threw]';
|
|
385
|
+
}
|
|
386
|
+
this.write(child, depth + 1);
|
|
387
|
+
}
|
|
388
|
+
if (keys.length > MAX_KEYS) {
|
|
389
|
+
this.push(`,"…":"${keys.length - MAX_KEYS} more keys"`);
|
|
390
|
+
}
|
|
391
|
+
this.push('}');
|
|
392
|
+
}
|
|
393
|
+
}
|
|
394
|
+
//# sourceMappingURL=format.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"format.js","sourceRoot":"","sources":["../../../src/logs/format.ts"],"names":[],"mappings":"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","sourcesContent":["export const MAX_LOG_LENGTH = 1000;\nexport const MAX_ERROR_LOG_LENGTH = 5000;\nexport const TRUNCATED_SUFFIX = '… [truncated]';\n\nconst MAX_DEPTH = 5;\nconst MAX_KEYS = 50;\nconst MAX_ITEMS = 50;\n\n/** Keeps the head of a log line so the result (incl. the suffix) fits max chars. */\nexport function truncateLog(text: string, max: number): string {\n if (text.length <= max) {\n return text;\n }\n let end = Math.max(0, max - TRUNCATED_SUFFIX.length);\n const last = text.charCodeAt(end - 1);\n if (last >= 0xd800 && last <= 0xdbff) {\n end--;\n }\n return text.slice(0, end) + TRUNCATED_SUFFIX;\n}\n\n/**\n * Formats console arguments like the browser console does (printf-style %s %d %i %f %o %O %c in\n * the first string), with objects as depth-limited JSON. Stops early once the text exceeds the\n * budget, so logging a huge object stays cheap.\n */\nexport function formatConsoleArgs(args: ArrayLike<unknown>, budget: number): string {\n if (!args || args.length === 0) {\n return '';\n }\n let out = '';\n let index = 0;\n const first = args[0];\n if (typeof first === 'string' && first.indexOf('%') > -1 && args.length > 1) {\n index = 1;\n for (let i = 0; i < first.length && out.length <= budget; i++) {\n const char = first[i];\n if (char !== '%' || i + 1 >= first.length) {\n out += char;\n continue;\n }\n const specifier = first[i + 1];\n if (specifier === '%') {\n out += '%';\n i++;\n continue;\n }\n if ('sdifoOc'.indexOf(specifier) < 0 || index >= args.length) {\n out += char;\n continue;\n }\n const arg = args[index++];\n i++;\n switch (specifier) {\n case 's':\n out += typeof arg === 'string' ? arg : formatValue(arg, budget);\n break;\n case 'd':\n case 'i':\n out += formatInteger(arg);\n break;\n case 'f':\n out += formatFloat(arg);\n break;\n case 'o':\n case 'O':\n out += formatValue(arg, budget);\n break;\n default:\n // %c (CSS) consumes its argument and prints nothing.\n break;\n }\n }\n }\n for (; index < args.length && out.length <= budget; index++) {\n const arg = args[index];\n const text = typeof arg === 'string' ? arg : formatValue(arg, budget);\n out = out.length > 0 ? `${out} ${text}` : text;\n }\n return out;\n}\n\nfunction formatInteger(value: unknown): string {\n if (typeof value === 'number') {\n return String(value < 0 ? Math.ceil(value) : Math.floor(value));\n }\n if (typeof value === 'bigint') {\n return String(value);\n }\n if (typeof value === 'string') {\n return String(parseInt(value, 10));\n }\n return 'NaN';\n}\n\nfunction formatFloat(value: unknown): string {\n if (typeof value === 'number') {\n return String(value);\n }\n if (typeof value === 'string') {\n return String(parseFloat(value));\n }\n return 'NaN';\n}\n\n/** A single value as text: strings as they are, errors with their stack, objects as JSON. */\nexport function formatValue(value: unknown, budget: number): string {\n try {\n if (typeof value === 'string') {\n return value;\n }\n if (isError(value)) {\n return formatError(value);\n }\n if (value === null || (typeof value !== 'object' && typeof value !== 'function')) {\n return formatPrimitive(value);\n }\n const serializer = new Serializer(budget);\n serializer.write(value, 0);\n return serializer.result();\n } catch (e) {\n return '[unserializable value]';\n }\n}\n\n/** \"Name: message\" followed by the stack (V8 stacks already start with that line). */\nexport function formatError(error: unknown): string {\n try {\n const err = error as { name?: unknown; message?: unknown; stack?: unknown };\n const name = typeof err.name === 'string' && err.name ? err.name : 'Error';\n const message = typeof err.message === 'string' ? err.message : '';\n const head = message ? `${name}: ${message}` : name;\n const stack = typeof err.stack === 'string' ? err.stack.trim() : '';\n if (!stack) {\n return head;\n }\n if (stack.indexOf(head) === 0) {\n return stack;\n }\n return `${head}\\n${stack}`;\n } catch (e) {\n return 'Error';\n }\n}\n\nexport function isError(value: unknown): boolean {\n if (!value || typeof value !== 'object') {\n return false;\n }\n if (typeof Error !== 'undefined' && value instanceof Error) {\n return true;\n }\n const candidate = value as { name?: unknown; message?: unknown; stack?: unknown };\n return (\n typeof candidate.message === 'string' && typeof candidate.stack === 'string' && typeof candidate.name === 'string'\n );\n}\n\nfunction formatPrimitive(value: unknown): string {\n if (typeof value === 'bigint') {\n return `${value}n`;\n }\n if (typeof value === 'symbol') {\n return value.toString();\n }\n return String(value);\n}\n\nfunction describeFunction(value: unknown): string {\n const name = (value as { name?: unknown }).name;\n return `[Function: ${typeof name === 'string' && name ? name : 'anonymous'}]`;\n}\n\nfunction describeNode(value: unknown): string | null {\n if (typeof Node === 'undefined' || !(value instanceof Node)) {\n return null;\n }\n if (typeof Element !== 'undefined' && value instanceof Element) {\n let text = `<${value.tagName.toLowerCase()}`;\n if (value.id) {\n text += `#${value.id}`;\n }\n const className = value.getAttribute('class');\n if (className) {\n text += `.${className.trim().split(/\\s+/).join('.')}`;\n }\n return `${text}>`;\n }\n return value.nodeName;\n}\n\nfunction constructorName(value: object): string {\n try {\n const proto = Object.getPrototypeOf(value);\n if (!proto) {\n return '';\n }\n const ctor = proto.constructor;\n const name = ctor && typeof ctor.name === 'string' ? ctor.name : '';\n return name === 'Object' ? '' : name;\n } catch (e) {\n return '';\n }\n}\n\n/** JSON-like serialiser with depth, key and length limits and circular protection. */\nclass Serializer {\n private parts: string[] = [];\n private length = 0;\n private ancestors: unknown[] = [];\n\n constructor(private readonly budget: number) {}\n\n result(): string {\n return this.parts.join('');\n }\n\n private isFull(): boolean {\n return this.length > this.budget;\n }\n\n private push(text: string): void {\n if (this.isFull()) {\n return;\n }\n this.parts.push(text);\n this.length += text.length;\n }\n\n write(value: unknown, depth: number): void {\n if (this.isFull()) {\n return;\n }\n if (value === null || value === undefined) {\n this.push(String(value));\n return;\n }\n switch (typeof value) {\n case 'string':\n this.push(JSON.stringify(value));\n return;\n case 'number':\n case 'boolean':\n case 'bigint':\n case 'symbol':\n this.push(formatPrimitive(value));\n return;\n case 'function':\n this.push(describeFunction(value));\n return;\n default:\n break;\n }\n this.writeObject(value as object, depth);\n }\n\n private writeObject(value: object, depth: number): void {\n if (this.ancestors.indexOf(value) > -1) {\n this.push('[Circular]');\n return;\n }\n if (isError(value)) {\n this.push(JSON.stringify(formatError(value).split('\\n')[0]));\n return;\n }\n if (value instanceof Date) {\n this.push(isNaN(value.getTime()) ? '\"Invalid Date\"' : JSON.stringify(value.toISOString()));\n return;\n }\n if (value instanceof RegExp) {\n this.push(String(value));\n return;\n }\n const node = describeNode(value);\n if (node !== null) {\n this.push(node);\n return;\n }\n if (typeof window !== 'undefined' && value === window) {\n this.push('[Window]');\n return;\n }\n if (typeof ArrayBuffer !== 'undefined') {\n if (value instanceof ArrayBuffer) {\n this.push(`[ArrayBuffer(${value.byteLength})]`);\n return;\n }\n if (ArrayBuffer.isView(value)) {\n const length = (value as unknown as { length?: number }).length;\n this.push(\n `[${constructorName(value) || 'ArrayBufferView'}(${typeof length === 'number' ? length : value.byteLength})]`,\n );\n return;\n }\n }\n if (typeof Promise !== 'undefined' && value instanceof Promise) {\n this.push('[Promise]');\n return;\n }\n\n const isArray = Array.isArray(value);\n if (depth >= MAX_DEPTH) {\n this.push(isArray ? `[Array(${(value as unknown[]).length})]` : '[Object]');\n return;\n }\n\n this.ancestors.push(value);\n try {\n if (isArray) {\n this.writeArray(value as unknown[], depth);\n } else if (typeof Map !== 'undefined' && value instanceof Map) {\n this.writeMap(value, depth);\n } else if (typeof Set !== 'undefined' && value instanceof Set) {\n this.writeSet(value, depth);\n } else {\n this.writePlainObject(value, depth);\n }\n } finally {\n this.ancestors.pop();\n }\n }\n\n private writeArray(value: unknown[], depth: number): void {\n this.push('[');\n const count = Math.min(value.length, MAX_ITEMS);\n for (let i = 0; i < count && !this.isFull(); i++) {\n if (i > 0) {\n this.push(',');\n }\n this.write(value[i], depth + 1);\n }\n if (value.length > MAX_ITEMS) {\n this.push(`,\"… ${value.length - MAX_ITEMS} more\"`);\n }\n this.push(']');\n }\n\n private writeMap(value: Map<unknown, unknown>, depth: number): void {\n this.push(`Map(${value.size}) {`);\n let count = 0;\n value.forEach((item, key) => {\n if (count >= MAX_ITEMS || this.isFull()) {\n return;\n }\n if (count > 0) {\n this.push(', ');\n }\n this.write(key, depth + 1);\n this.push(' => ');\n this.write(item, depth + 1);\n count++;\n });\n this.push('}');\n }\n\n private writeSet(value: Set<unknown>, depth: number): void {\n this.push(`Set(${value.size}) {`);\n let count = 0;\n value.forEach((item) => {\n if (count >= MAX_ITEMS || this.isFull()) {\n return;\n }\n if (count > 0) {\n this.push(', ');\n }\n this.write(item, depth + 1);\n count++;\n });\n this.push('}');\n }\n\n private writePlainObject(value: object, depth: number): void {\n const record = value as { [key: string]: unknown; toJSON?: unknown };\n if (typeof record.toJSON === 'function') {\n let converted: unknown;\n try {\n converted = (record.toJSON as () => unknown)();\n } catch (e) {\n converted = undefined;\n }\n if (converted !== undefined && converted !== value) {\n this.write(converted, depth + 1);\n return;\n }\n }\n const name = constructorName(value);\n if (name) {\n this.push(`${name} `);\n }\n this.push('{');\n const keys = Object.keys(record);\n const count = Math.min(keys.length, MAX_KEYS);\n for (let i = 0; i < count && !this.isFull(); i++) {\n if (i > 0) {\n this.push(',');\n }\n this.push(`${JSON.stringify(keys[i])}:`);\n let child: unknown;\n try {\n child = record[keys[i]];\n } catch (e) {\n child = '[getter threw]';\n }\n this.write(child, depth + 1);\n }\n if (keys.length > MAX_KEYS) {\n this.push(`,\"…\":\"${keys.length - MAX_KEYS} more keys\"`);\n }\n this.push('}');\n }\n}\n"]}
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
import type { GleapNetworkLogEntry } from '../definitions';
|
|
2
|
+
export declare const MAX_NETWORK_ENTRIES = 30;
|
|
3
|
+
declare type HeaderMap = {
|
|
4
|
+
[name: string]: string;
|
|
5
|
+
};
|
|
6
|
+
export interface NetworkLogSnapshot {
|
|
7
|
+
id: number;
|
|
8
|
+
version: number;
|
|
9
|
+
entry: GleapNetworkLogEntry;
|
|
10
|
+
}
|
|
11
|
+
/**
|
|
12
|
+
* Records fetch and XMLHttpRequest calls made inside the WebView. The hooks never alter or delay the
|
|
13
|
+
* request: they only read what the app passes in and what comes back, and every hook is guarded so
|
|
14
|
+
* a logging failure cannot break the app's networking.
|
|
15
|
+
*/
|
|
16
|
+
export declare class NetworkCapture {
|
|
17
|
+
private readonly win;
|
|
18
|
+
private readonly onChange;
|
|
19
|
+
private records;
|
|
20
|
+
private nextId;
|
|
21
|
+
private active;
|
|
22
|
+
private isInstalled;
|
|
23
|
+
private xhrStates;
|
|
24
|
+
private xhrsWithListeners;
|
|
25
|
+
constructor(win: Window, onChange: () => void);
|
|
26
|
+
/** Installs the hooks inactive: nothing is recorded until setActive(true). */
|
|
27
|
+
install(): void;
|
|
28
|
+
/** Inactive: the hooks stay in place but only call through, and the buffer is dropped. */
|
|
29
|
+
setActive(active: boolean): void;
|
|
30
|
+
getSnapshots(): NetworkLogSnapshot[];
|
|
31
|
+
private patchFetch;
|
|
32
|
+
private startFetch;
|
|
33
|
+
/** The body of a Request object: read from a clone (made before fetch consumes it), head only. */
|
|
34
|
+
private requestObjectPayload;
|
|
35
|
+
private completeFetch;
|
|
36
|
+
/**
|
|
37
|
+
* Streaming and binary responses are never cloned. Text responses are cloned synchronously (before
|
|
38
|
+
* the app sees the response) and only the head of the clone is read, then the clone is cancelled.
|
|
39
|
+
*/
|
|
40
|
+
private fetchResponseBody;
|
|
41
|
+
private patchXhr;
|
|
42
|
+
private wrapXhrConstructor;
|
|
43
|
+
private hookXhrMethods;
|
|
44
|
+
private onXhrOpen;
|
|
45
|
+
private onXhrHeader;
|
|
46
|
+
private onXhrSend;
|
|
47
|
+
private listenToXhr;
|
|
48
|
+
private onXhrLoadEnd;
|
|
49
|
+
/** The response is already in memory; only a bounded part of it is turned into text. */
|
|
50
|
+
private xhrResponseBody;
|
|
51
|
+
private requestPayload;
|
|
52
|
+
private createRecord;
|
|
53
|
+
private setResponseText;
|
|
54
|
+
private fail;
|
|
55
|
+
private update;
|
|
56
|
+
private resolveUrl;
|
|
57
|
+
/**
|
|
58
|
+
* Only real network traffic: http(s) URLs that are not Gleap's own and not the app's bundled files
|
|
59
|
+
* served by Capacitor's local server (http(s)://localhost on Android; capacitor:// on iOS).
|
|
60
|
+
*/
|
|
61
|
+
private shouldCapture;
|
|
62
|
+
}
|
|
63
|
+
/** Headers | [name, value][] | record -> { lowercased name: value }, repeated names joined with ", ". */
|
|
64
|
+
export declare function normalizeHeaders(headers: unknown): HeaderMap;
|
|
65
|
+
export {};
|