@ansight/capacitor 1.3.0-preview.9 → 1.4.0-preview.1
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/AnsightCapacitor.podspec +1 -1
- package/Package.swift +1 -1
- package/README.md +116 -29
- package/android/build.gradle +2 -2
- package/android/src/main/kotlin/ai/ansight/capacitor/AnsightCapacitorPlugin.kt +74 -22
- package/dist/esm/definitions.d.ts +73 -10
- package/dist/esm/definitions.d.ts.map +1 -1
- package/dist/esm/dom.d.ts +11 -0
- package/dist/esm/dom.d.ts.map +1 -1
- package/dist/esm/dom.js +73 -23
- package/dist/esm/dom.js.map +1 -1
- package/dist/esm/index.d.ts +10 -1
- package/dist/esm/index.d.ts.map +1 -1
- package/dist/esm/index.js +113 -5
- package/dist/esm/index.js.map +1 -1
- package/dist/esm/network.d.ts +6 -0
- package/dist/esm/network.d.ts.map +1 -0
- package/dist/esm/network.js +742 -0
- package/dist/esm/network.js.map +1 -0
- package/dist/esm/options.d.ts +7 -1
- package/dist/esm/options.d.ts.map +1 -1
- package/dist/esm/options.js +44 -0
- package/dist/esm/options.js.map +1 -1
- package/dist/esm/session-properties.d.ts +16 -0
- package/dist/esm/session-properties.d.ts.map +1 -0
- package/dist/esm/session-properties.js +123 -0
- package/dist/esm/session-properties.js.map +1 -0
- package/dist/esm/standalone-options.d.ts +3 -0
- package/dist/esm/standalone-options.d.ts.map +1 -0
- package/dist/esm/standalone-options.js +15 -0
- package/dist/esm/standalone-options.js.map +1 -0
- package/dist/esm/standalone.d.ts.map +1 -1
- package/dist/esm/standalone.js +2 -11
- package/dist/esm/standalone.js.map +1 -1
- package/dist/plugin.cjs.js +1096 -28
- package/dist/plugin.cjs.js.map +1 -1
- package/dist/plugin.js +1096 -28
- package/dist/plugin.js.map +1 -1
- package/dist/standalone.js +1099 -31
- package/dist/standalone.js.map +1 -1
- package/ios/Sources/AnsightCapacitorPlugin/AnsightCapacitorPlugin.swift +75 -21
- package/package.json +1 -1
package/dist/plugin.js
CHANGED
|
@@ -59,6 +59,19 @@ var capacitorAnsight = (function (exports, core) {
|
|
|
59
59
|
element.id ??
|
|
60
60
|
undefined)?.trim() || undefined);
|
|
61
61
|
}
|
|
62
|
+
const tapRoles = new Set([
|
|
63
|
+
"button",
|
|
64
|
+
"checkbox",
|
|
65
|
+
"combobox",
|
|
66
|
+
"link",
|
|
67
|
+
"menuitem",
|
|
68
|
+
"menuitemcheckbox",
|
|
69
|
+
"menuitemradio",
|
|
70
|
+
"option",
|
|
71
|
+
"radio",
|
|
72
|
+
"switch",
|
|
73
|
+
"tab",
|
|
74
|
+
]);
|
|
62
75
|
function semanticRole(element) {
|
|
63
76
|
const declared = element.getAttribute("role")?.trim().toLowerCase();
|
|
64
77
|
if (declared)
|
|
@@ -90,24 +103,54 @@ var capacitorAnsight = (function (exports, core) {
|
|
|
90
103
|
if (!allowActions)
|
|
91
104
|
return [];
|
|
92
105
|
const actions = [];
|
|
106
|
+
const htmlElement = element;
|
|
107
|
+
const role = semanticRole(element);
|
|
93
108
|
if (["A", "BUTTON", "SUMMARY"].includes(element.tagName) ||
|
|
94
|
-
element instanceof HTMLInputElement
|
|
109
|
+
element instanceof HTMLInputElement ||
|
|
110
|
+
tapRoles.has(role) ||
|
|
111
|
+
element.hasAttribute("onclick") ||
|
|
112
|
+
typeof htmlElement.onclick === "function") {
|
|
95
113
|
actions.push("tap");
|
|
96
114
|
}
|
|
97
115
|
if (element instanceof HTMLInputElement ||
|
|
98
116
|
element instanceof HTMLTextAreaElement ||
|
|
99
|
-
element instanceof HTMLSelectElement
|
|
117
|
+
element instanceof HTMLSelectElement ||
|
|
118
|
+
htmlElement.isContentEditable) {
|
|
100
119
|
actions.push("typeText", "focus");
|
|
101
120
|
}
|
|
102
|
-
else if (
|
|
121
|
+
else if (htmlElement.tabIndex >= 0) {
|
|
103
122
|
actions.push("focus");
|
|
104
123
|
}
|
|
105
|
-
if (
|
|
106
|
-
|
|
124
|
+
if (htmlElement.scrollHeight > htmlElement.clientHeight ||
|
|
125
|
+
htmlElement.scrollWidth > htmlElement.clientWidth) {
|
|
107
126
|
actions.push("scroll", "swipe");
|
|
108
127
|
}
|
|
109
128
|
return [...new Set(actions)];
|
|
110
129
|
}
|
|
130
|
+
function positiveFinite(value) {
|
|
131
|
+
const parsed = Number(value);
|
|
132
|
+
return Number.isFinite(parsed) && parsed > 0 ? parsed : undefined;
|
|
133
|
+
}
|
|
134
|
+
function createDomCoordinateSpace(browserWindow = typeof window === "undefined"
|
|
135
|
+
? undefined
|
|
136
|
+
: window, documentElement = typeof document === "undefined"
|
|
137
|
+
? null
|
|
138
|
+
: document.documentElement) {
|
|
139
|
+
const width = positiveFinite(browserWindow?.innerWidth) ??
|
|
140
|
+
positiveFinite(documentElement?.clientWidth);
|
|
141
|
+
const height = positiveFinite(browserWindow?.innerHeight) ??
|
|
142
|
+
positiveFinite(documentElement?.clientHeight);
|
|
143
|
+
if (width === undefined || height === undefined)
|
|
144
|
+
return undefined;
|
|
145
|
+
return { x: 0, y: 0, width, height, source: "dom.viewport" };
|
|
146
|
+
}
|
|
147
|
+
function normalizeDomAction(action) {
|
|
148
|
+
if (action === "tap")
|
|
149
|
+
return "click";
|
|
150
|
+
if (action === "typeText")
|
|
151
|
+
return "setValue";
|
|
152
|
+
return String(action ?? "");
|
|
153
|
+
}
|
|
111
154
|
function computedColorToArgbHex(value) {
|
|
112
155
|
const normalized = value.trim().toLowerCase();
|
|
113
156
|
if (!normalized)
|
|
@@ -256,8 +299,7 @@ var capacitorAnsight = (function (exports, core) {
|
|
|
256
299
|
name: "Get DOM document",
|
|
257
300
|
description: "Returns the accessible HTML DOM tree rendered inside the Capacitor WebView.",
|
|
258
301
|
category: "UI",
|
|
259
|
-
|
|
260
|
-
security: { level: "low", summary: "Reads the current app DOM." },
|
|
302
|
+
policy: "read",
|
|
261
303
|
}, async () => {
|
|
262
304
|
const root = document.documentElement;
|
|
263
305
|
const limits = {
|
|
@@ -272,6 +314,7 @@ var capacitorAnsight = (function (exports, core) {
|
|
|
272
314
|
platform: "web",
|
|
273
315
|
source: options.source,
|
|
274
316
|
adapter: "@ansight/capacitor",
|
|
317
|
+
coordinateSpace: createDomCoordinateSpace(),
|
|
275
318
|
capturedAtUtc: new Date().toISOString(),
|
|
276
319
|
types: typeRegistry.types,
|
|
277
320
|
truncated: limits.count >= limits.maxNodes,
|
|
@@ -283,7 +326,7 @@ var capacitorAnsight = (function (exports, core) {
|
|
|
283
326
|
name: "Inspect DOM node",
|
|
284
327
|
description: "Returns the current state of a DOM node captured by dom.get_document.",
|
|
285
328
|
category: "UI",
|
|
286
|
-
|
|
329
|
+
policy: "read",
|
|
287
330
|
argumentsSchema: {
|
|
288
331
|
type: "object",
|
|
289
332
|
required: ["nodeId"],
|
|
@@ -306,6 +349,7 @@ var capacitorAnsight = (function (exports, core) {
|
|
|
306
349
|
platform: "web",
|
|
307
350
|
source: options.source,
|
|
308
351
|
adapter: "@ansight/capacitor",
|
|
352
|
+
coordinateSpace: createDomCoordinateSpace(),
|
|
309
353
|
capturedAtUtc: new Date().toISOString(),
|
|
310
354
|
types: typeRegistry.types,
|
|
311
355
|
node,
|
|
@@ -316,7 +360,7 @@ var capacitorAnsight = (function (exports, core) {
|
|
|
316
360
|
name: "Query DOM",
|
|
317
361
|
description: "Finds DOM nodes using a CSS selector.",
|
|
318
362
|
category: "UI",
|
|
319
|
-
|
|
363
|
+
policy: "read",
|
|
320
364
|
argumentsSchema: {
|
|
321
365
|
type: "object",
|
|
322
366
|
required: ["selector"],
|
|
@@ -344,22 +388,21 @@ var capacitorAnsight = (function (exports, core) {
|
|
|
344
388
|
registrations.push(registerTool({
|
|
345
389
|
id: "dom.invoke_action",
|
|
346
390
|
name: "Invoke DOM action",
|
|
347
|
-
description: "
|
|
391
|
+
description: "Taps, focuses, blurs, or enters text in a DOM node.",
|
|
348
392
|
category: "UI",
|
|
349
|
-
|
|
393
|
+
policy: "write",
|
|
350
394
|
argumentsSchema: {
|
|
351
395
|
type: "object",
|
|
352
396
|
required: ["nodeId", "action"],
|
|
353
397
|
properties: {
|
|
354
398
|
nodeId: { type: "string" },
|
|
355
|
-
action: {
|
|
399
|
+
action: {
|
|
400
|
+
type: "string",
|
|
401
|
+
enum: ["tap", "typeText", "click", "focus", "blur", "setValue"],
|
|
402
|
+
},
|
|
356
403
|
value: { type: "string" },
|
|
357
404
|
},
|
|
358
405
|
},
|
|
359
|
-
security: {
|
|
360
|
-
level: "high",
|
|
361
|
-
summary: "Can interact with controls inside the app WebView.",
|
|
362
|
-
},
|
|
363
406
|
}, ({ nodeId: id, action, value }) => {
|
|
364
407
|
const element = findElement(id);
|
|
365
408
|
if (!element) {
|
|
@@ -369,17 +412,24 @@ var capacitorAnsight = (function (exports, core) {
|
|
|
369
412
|
errorCode: "dom_node_not_found",
|
|
370
413
|
};
|
|
371
414
|
}
|
|
372
|
-
|
|
415
|
+
const normalizedAction = normalizeDomAction(action);
|
|
416
|
+
if (normalizedAction === "click")
|
|
373
417
|
element.click();
|
|
374
|
-
else if (
|
|
418
|
+
else if (normalizedAction === "focus")
|
|
375
419
|
element.focus();
|
|
376
|
-
else if (
|
|
420
|
+
else if (normalizedAction === "blur")
|
|
377
421
|
element.blur();
|
|
378
|
-
else if (
|
|
422
|
+
else if (normalizedAction === "setValue" &&
|
|
379
423
|
(element instanceof HTMLInputElement ||
|
|
380
424
|
element instanceof HTMLTextAreaElement ||
|
|
381
|
-
element instanceof HTMLSelectElement
|
|
382
|
-
|
|
425
|
+
element instanceof HTMLSelectElement ||
|
|
426
|
+
element.isContentEditable)) {
|
|
427
|
+
if (element.isContentEditable) {
|
|
428
|
+
element.textContent = value ?? "";
|
|
429
|
+
}
|
|
430
|
+
else {
|
|
431
|
+
element.value = value ?? "";
|
|
432
|
+
}
|
|
383
433
|
element.dispatchEvent(new Event("input", { bubbles: true }));
|
|
384
434
|
element.dispatchEvent(new Event("change", { bubbles: true }));
|
|
385
435
|
}
|
|
@@ -390,7 +440,7 @@ var capacitorAnsight = (function (exports, core) {
|
|
|
390
440
|
errorCode: "dom_action_unsupported",
|
|
391
441
|
};
|
|
392
442
|
}
|
|
393
|
-
return successful({ nodeId: id, action }, `DOM action '${action}' invoked.`);
|
|
443
|
+
return successful({ nodeId: id, action, performedAction: normalizedAction }, `DOM action '${action}' invoked.`);
|
|
394
444
|
}));
|
|
395
445
|
}
|
|
396
446
|
return {
|
|
@@ -562,6 +612,50 @@ var capacitorAnsight = (function (exports, core) {
|
|
|
562
612
|
};
|
|
563
613
|
return this;
|
|
564
614
|
}
|
|
615
|
+
withNetworkCapture(options = {}) {
|
|
616
|
+
this.options.networkCapture = { ...options };
|
|
617
|
+
return this;
|
|
618
|
+
}
|
|
619
|
+
withNetworkRequestBodies(maximumBodyBytes) {
|
|
620
|
+
if (typeof this.options.networkCapture !== "object")
|
|
621
|
+
return this;
|
|
622
|
+
const current = this.options.networkCapture;
|
|
623
|
+
this.options.networkCapture = {
|
|
624
|
+
...current,
|
|
625
|
+
captureRequestBody: true,
|
|
626
|
+
...(maximumBodyBytes == null ? {} : { maximumBodyBytes }),
|
|
627
|
+
};
|
|
628
|
+
return this;
|
|
629
|
+
}
|
|
630
|
+
withoutNetworkRequestBodies() {
|
|
631
|
+
if (typeof this.options.networkCapture !== "object")
|
|
632
|
+
return this;
|
|
633
|
+
const current = this.options.networkCapture;
|
|
634
|
+
this.options.networkCapture = { ...current, captureRequestBody: false };
|
|
635
|
+
return this;
|
|
636
|
+
}
|
|
637
|
+
withNetworkResponseBodies(maximumBodyBytes) {
|
|
638
|
+
if (typeof this.options.networkCapture !== "object")
|
|
639
|
+
return this;
|
|
640
|
+
const current = this.options.networkCapture;
|
|
641
|
+
this.options.networkCapture = {
|
|
642
|
+
...current,
|
|
643
|
+
captureResponseBody: true,
|
|
644
|
+
...(maximumBodyBytes == null ? {} : { maximumBodyBytes }),
|
|
645
|
+
};
|
|
646
|
+
return this;
|
|
647
|
+
}
|
|
648
|
+
withoutNetworkResponseBodies() {
|
|
649
|
+
if (typeof this.options.networkCapture !== "object")
|
|
650
|
+
return this;
|
|
651
|
+
const current = this.options.networkCapture;
|
|
652
|
+
this.options.networkCapture = { ...current, captureResponseBody: false };
|
|
653
|
+
return this;
|
|
654
|
+
}
|
|
655
|
+
withoutNetworkCapture() {
|
|
656
|
+
this.options.networkCapture = false;
|
|
657
|
+
return this;
|
|
658
|
+
}
|
|
565
659
|
withToolGuard(toolGuard) {
|
|
566
660
|
this.options.toolGuard = toolGuard;
|
|
567
661
|
return this;
|
|
@@ -729,6 +823,871 @@ var capacitorAnsight = (function (exports, core) {
|
|
|
729
823
|
return new AnsightOptionsBuilder(options);
|
|
730
824
|
}
|
|
731
825
|
|
|
826
|
+
const networkRequestSchema = "ansight.network-request.v1";
|
|
827
|
+
const redactedNetworkValue = "<redacted>";
|
|
828
|
+
const maximumHeaderCount = 128;
|
|
829
|
+
const maximumHeaderValueLength = 4096;
|
|
830
|
+
const maximumErrorMessageLength = 4096;
|
|
831
|
+
const maximumUrlLength = 16384;
|
|
832
|
+
const defaultMaximumBodyBytes = 64 * 1024;
|
|
833
|
+
const sensitiveHeaderNames = new Set([
|
|
834
|
+
"authorization",
|
|
835
|
+
"cookie",
|
|
836
|
+
"proxy-authorization",
|
|
837
|
+
"set-cookie",
|
|
838
|
+
"x-api-key",
|
|
839
|
+
"x-auth-token",
|
|
840
|
+
]);
|
|
841
|
+
const sensitiveQueryNames = new Set([
|
|
842
|
+
"access_token",
|
|
843
|
+
"accesskey",
|
|
844
|
+
"access_key",
|
|
845
|
+
"api_key",
|
|
846
|
+
"apikey",
|
|
847
|
+
"auth",
|
|
848
|
+
"authorization",
|
|
849
|
+
"client_secret",
|
|
850
|
+
"code",
|
|
851
|
+
"credential",
|
|
852
|
+
"credentials",
|
|
853
|
+
"id_token",
|
|
854
|
+
"jwt",
|
|
855
|
+
"key",
|
|
856
|
+
"password",
|
|
857
|
+
"passwd",
|
|
858
|
+
"refresh_token",
|
|
859
|
+
"sas",
|
|
860
|
+
"sastoken",
|
|
861
|
+
"secret",
|
|
862
|
+
"secret_key",
|
|
863
|
+
"security_token",
|
|
864
|
+
"session_token",
|
|
865
|
+
"sig",
|
|
866
|
+
"signature",
|
|
867
|
+
"token",
|
|
868
|
+
]);
|
|
869
|
+
const azureSasFingerprintNames = new Set([
|
|
870
|
+
"se",
|
|
871
|
+
"skoid",
|
|
872
|
+
"sp",
|
|
873
|
+
"sr",
|
|
874
|
+
"srt",
|
|
875
|
+
"ss",
|
|
876
|
+
"sv",
|
|
877
|
+
]);
|
|
878
|
+
const azureSasQueryNames = new Set([
|
|
879
|
+
"epk",
|
|
880
|
+
"erk",
|
|
881
|
+
"rscc",
|
|
882
|
+
"rscd",
|
|
883
|
+
"rsce",
|
|
884
|
+
"rscl",
|
|
885
|
+
"rsct",
|
|
886
|
+
"saoid",
|
|
887
|
+
"scid",
|
|
888
|
+
"se",
|
|
889
|
+
"sig",
|
|
890
|
+
"si",
|
|
891
|
+
"sip",
|
|
892
|
+
"ske",
|
|
893
|
+
"skoid",
|
|
894
|
+
"sks",
|
|
895
|
+
"skt",
|
|
896
|
+
"sktid",
|
|
897
|
+
"skv",
|
|
898
|
+
"snapshot",
|
|
899
|
+
"sp",
|
|
900
|
+
"spk",
|
|
901
|
+
"spr",
|
|
902
|
+
"sr",
|
|
903
|
+
"srk",
|
|
904
|
+
"srt",
|
|
905
|
+
"ss",
|
|
906
|
+
"st",
|
|
907
|
+
"suoid",
|
|
908
|
+
"tn",
|
|
909
|
+
"versionid",
|
|
910
|
+
"sv",
|
|
911
|
+
]);
|
|
912
|
+
function truncate(value, maximumLength) {
|
|
913
|
+
const text = String(value);
|
|
914
|
+
return text.length <= maximumLength
|
|
915
|
+
? text
|
|
916
|
+
: `${text.slice(0, maximumLength)}…`;
|
|
917
|
+
}
|
|
918
|
+
function normalizeRequired(value, fallback, maximumLength) {
|
|
919
|
+
const normalized = value == null ? "" : String(value).trim();
|
|
920
|
+
return truncate(normalized || fallback, maximumLength);
|
|
921
|
+
}
|
|
922
|
+
function normalizeOptional(value, maximumLength) {
|
|
923
|
+
if (value == null)
|
|
924
|
+
return undefined;
|
|
925
|
+
const normalized = String(value).trim();
|
|
926
|
+
return normalized ? truncate(normalized, maximumLength) : undefined;
|
|
927
|
+
}
|
|
928
|
+
function lowercaseSet(values) {
|
|
929
|
+
return new Set((values ?? []).map((value) => value.toLowerCase()));
|
|
930
|
+
}
|
|
931
|
+
function isSensitiveHeader(name, options) {
|
|
932
|
+
const lowered = name.toLowerCase();
|
|
933
|
+
if (sensitiveHeaderNames.has(lowered) ||
|
|
934
|
+
lowercaseSet(options.additionalSensitiveHeaderNames).has(lowered)) {
|
|
935
|
+
return true;
|
|
936
|
+
}
|
|
937
|
+
const compact = lowered.replaceAll("-", "");
|
|
938
|
+
return (compact.includes("token") ||
|
|
939
|
+
compact.includes("secret") ||
|
|
940
|
+
compact.includes("apikey"));
|
|
941
|
+
}
|
|
942
|
+
function headerEntries(headers) {
|
|
943
|
+
if (!headers)
|
|
944
|
+
return [];
|
|
945
|
+
if (Array.isArray(headers)) {
|
|
946
|
+
return headers.flatMap((header) => {
|
|
947
|
+
if (Array.isArray(header))
|
|
948
|
+
return [[header[0], header[1]]];
|
|
949
|
+
if (header && typeof header === "object") {
|
|
950
|
+
const value = header;
|
|
951
|
+
return [[value.name, value.value]];
|
|
952
|
+
}
|
|
953
|
+
return [];
|
|
954
|
+
});
|
|
955
|
+
}
|
|
956
|
+
if (typeof headers.forEach === "function") {
|
|
957
|
+
const entries = [];
|
|
958
|
+
headers.forEach((value, name) => entries.push([name, value]));
|
|
959
|
+
return entries;
|
|
960
|
+
}
|
|
961
|
+
return typeof headers === "object" ? Object.entries(headers) : [];
|
|
962
|
+
}
|
|
963
|
+
function sanitizeHeaders(headers, options) {
|
|
964
|
+
return headerEntries(headers)
|
|
965
|
+
.filter(([name]) => name != null && String(name).trim())
|
|
966
|
+
.slice(0, maximumHeaderCount)
|
|
967
|
+
.map(([rawName, rawValue]) => {
|
|
968
|
+
const name = normalizeRequired(rawName, "Header", 256);
|
|
969
|
+
return {
|
|
970
|
+
name,
|
|
971
|
+
value: isSensitiveHeader(name, options)
|
|
972
|
+
? redactedNetworkValue
|
|
973
|
+
: normalizeRequired(rawValue, "", maximumHeaderValueLength),
|
|
974
|
+
};
|
|
975
|
+
});
|
|
976
|
+
}
|
|
977
|
+
function sanitizeQuery(query, options) {
|
|
978
|
+
const appSensitive = lowercaseSet(options.additionalSensitiveQueryParameterNames);
|
|
979
|
+
const pairs = query.split("&");
|
|
980
|
+
const decodedNames = new Set(pairs.map((pair) => decodeQueryName(pair).toLowerCase()));
|
|
981
|
+
const hasAzureSas = decodedNames.has("sig") &&
|
|
982
|
+
[...azureSasFingerprintNames].some((name) => decodedNames.has(name));
|
|
983
|
+
const hasAwsSignature = decodedNames.has("x-amz-signature");
|
|
984
|
+
const hasGoogleSignature = decodedNames.has("x-goog-signature");
|
|
985
|
+
const hasCloudFrontSignature = decodedNames.has("signature") &&
|
|
986
|
+
["key-pair-id", "policy", "expires"].some((name) => decodedNames.has(name));
|
|
987
|
+
const hasLegacyGoogleSignature = decodedNames.has("signature") && decodedNames.has("googleaccessid");
|
|
988
|
+
const hasAlibabaSignature = (decodedNames.has("signature") && decodedNames.has("ossaccesskeyid")) ||
|
|
989
|
+
decodedNames.has("x-oss-signature");
|
|
990
|
+
return pairs
|
|
991
|
+
.map((pair) => {
|
|
992
|
+
const equalsIndex = pair.indexOf("=");
|
|
993
|
+
const encodedName = equalsIndex < 0 ? pair : pair.slice(0, equalsIndex);
|
|
994
|
+
const decodedName = decodeQueryName(pair);
|
|
995
|
+
const lowered = decodedName.toLowerCase();
|
|
996
|
+
const providerSensitive = (hasAzureSas && azureSasQueryNames.has(lowered)) ||
|
|
997
|
+
(hasAwsSignature && lowered.startsWith("x-amz-")) ||
|
|
998
|
+
(hasGoogleSignature && lowered.startsWith("x-goog-")) ||
|
|
999
|
+
(hasCloudFrontSignature &&
|
|
1000
|
+
[
|
|
1001
|
+
"signature",
|
|
1002
|
+
"key-pair-id",
|
|
1003
|
+
"policy",
|
|
1004
|
+
"expires",
|
|
1005
|
+
"hash-algorithm",
|
|
1006
|
+
].includes(lowered)) ||
|
|
1007
|
+
(hasLegacyGoogleSignature &&
|
|
1008
|
+
["signature", "googleaccessid", "expires"].includes(lowered)) ||
|
|
1009
|
+
(hasAlibabaSignature &&
|
|
1010
|
+
(lowered.startsWith("x-oss-") ||
|
|
1011
|
+
["signature", "ossaccesskeyid", "security-token"].includes(lowered)));
|
|
1012
|
+
return providerSensitive ||
|
|
1013
|
+
sensitiveQueryNames.has(lowered) ||
|
|
1014
|
+
appSensitive.has(lowered)
|
|
1015
|
+
? `${encodedName}=${encodeURIComponent(redactedNetworkValue)}`
|
|
1016
|
+
: pair;
|
|
1017
|
+
})
|
|
1018
|
+
.join("&");
|
|
1019
|
+
}
|
|
1020
|
+
function decodeQueryName(pair) {
|
|
1021
|
+
const equalsIndex = pair.indexOf("=");
|
|
1022
|
+
const encodedName = equalsIndex < 0 ? pair : pair.slice(0, equalsIndex);
|
|
1023
|
+
try {
|
|
1024
|
+
return decodeURIComponent(encodedName.replaceAll("+", " "));
|
|
1025
|
+
}
|
|
1026
|
+
catch {
|
|
1027
|
+
return encodedName;
|
|
1028
|
+
}
|
|
1029
|
+
}
|
|
1030
|
+
function sanitizeUrl(value, options) {
|
|
1031
|
+
let normalized = normalizeRequired(value, "<unknown>", maximumUrlLength);
|
|
1032
|
+
normalized = normalized.replace(/^(https?:\/\/)[^/@]+@/i, `$1${redactedNetworkValue}@`);
|
|
1033
|
+
const queryIndex = normalized.indexOf("?");
|
|
1034
|
+
if (queryIndex < 0)
|
|
1035
|
+
return truncate(normalized, maximumUrlLength);
|
|
1036
|
+
const fragmentIndex = normalized.indexOf("#", queryIndex);
|
|
1037
|
+
if (options.includeQueryString === false) {
|
|
1038
|
+
return truncate(normalized.slice(0, queryIndex) +
|
|
1039
|
+
(fragmentIndex < 0 ? "" : normalized.slice(fragmentIndex)), maximumUrlLength);
|
|
1040
|
+
}
|
|
1041
|
+
const queryEnd = fragmentIndex < 0 ? normalized.length : fragmentIndex;
|
|
1042
|
+
return truncate(normalized.slice(0, queryIndex + 1) +
|
|
1043
|
+
sanitizeQuery(normalized.slice(queryIndex + 1, queryEnd), options) +
|
|
1044
|
+
(fragmentIndex < 0 ? "" : normalized.slice(fragmentIndex)), maximumUrlLength);
|
|
1045
|
+
}
|
|
1046
|
+
function sanitizeErrorMessage(value, options) {
|
|
1047
|
+
const normalized = normalizeOptional(value, maximumErrorMessageLength);
|
|
1048
|
+
if (!normalized)
|
|
1049
|
+
return undefined;
|
|
1050
|
+
return truncate(normalized
|
|
1051
|
+
.replace(/(access_token|api_key|apikey|auth|authorization|code|key|password|passwd|secret|signature|token)(\s*=\s*)([^&\s,;]+)/gi, `$1$2${redactedNetworkValue}`)
|
|
1052
|
+
.replace(/https?:\/\/[^\s"'<>]+/gi, (url) => sanitizeUrl(url, options)), maximumErrorMessageLength);
|
|
1053
|
+
}
|
|
1054
|
+
function normalizeTimestamp(value, fallback) {
|
|
1055
|
+
const date = new Date(value == null ? fallback : String(value));
|
|
1056
|
+
return Number.isFinite(date.valueOf()) ? date.toISOString() : fallback;
|
|
1057
|
+
}
|
|
1058
|
+
function generateId(globalObject) {
|
|
1059
|
+
if (typeof globalObject.crypto?.randomUUID === "function") {
|
|
1060
|
+
return globalObject.crypto.randomUUID().replaceAll("-", "");
|
|
1061
|
+
}
|
|
1062
|
+
return `${Date.now().toString(36)}${Math.random().toString(36).slice(2)}`;
|
|
1063
|
+
}
|
|
1064
|
+
function normalizeSize(value) {
|
|
1065
|
+
const number = Number(value);
|
|
1066
|
+
return Number.isFinite(number) && number >= 0
|
|
1067
|
+
? Math.round(number)
|
|
1068
|
+
: undefined;
|
|
1069
|
+
}
|
|
1070
|
+
function maximumBodyBytes(options) {
|
|
1071
|
+
const configured = Number(options.maximumBodyBytes);
|
|
1072
|
+
const value = Number.isFinite(configured)
|
|
1073
|
+
? Math.round(configured)
|
|
1074
|
+
: defaultMaximumBodyBytes;
|
|
1075
|
+
return Math.max(0, value);
|
|
1076
|
+
}
|
|
1077
|
+
function sanitizeSensitiveText(value, options) {
|
|
1078
|
+
return value
|
|
1079
|
+
.replace(/(access_token|accesskey|access_key|api_key|apikey|auth|authorization|client_secret|code|credential|credentials|id_token|jwt|key|password|passwd|refresh_token|sas|sastoken|secret|secret_key|security_token|session_token|sig|signature|token)(["']?\s*[:=]\s*["']?)([^&\s,;}"']+)/gi, `$1$2${redactedNetworkValue}`)
|
|
1080
|
+
.replace(/https?:\/\/[^\s"'<>]+/gi, (url) => sanitizeUrl(url, options));
|
|
1081
|
+
}
|
|
1082
|
+
function truncateUtf8(bytes, maximum) {
|
|
1083
|
+
let length = Math.min(bytes.length, maximum);
|
|
1084
|
+
const decoder = new TextDecoder("utf-8", { fatal: true });
|
|
1085
|
+
while (length > 0) {
|
|
1086
|
+
try {
|
|
1087
|
+
decoder.decode(bytes.slice(0, length));
|
|
1088
|
+
return bytes.slice(0, length);
|
|
1089
|
+
}
|
|
1090
|
+
catch {
|
|
1091
|
+
length -= 1;
|
|
1092
|
+
}
|
|
1093
|
+
}
|
|
1094
|
+
return new Uint8Array();
|
|
1095
|
+
}
|
|
1096
|
+
function bytesToBase64$1(bytes) {
|
|
1097
|
+
let binary = "";
|
|
1098
|
+
for (const byte of bytes)
|
|
1099
|
+
binary += String.fromCharCode(byte);
|
|
1100
|
+
return btoa(binary);
|
|
1101
|
+
}
|
|
1102
|
+
function base64ToBytes(value) {
|
|
1103
|
+
const binary = atob(value);
|
|
1104
|
+
return Uint8Array.from(binary, (character) => character.charCodeAt(0));
|
|
1105
|
+
}
|
|
1106
|
+
function normalizeBody(body, options) {
|
|
1107
|
+
const maximum = maximumBodyBytes(options);
|
|
1108
|
+
if (!body || maximum <= 0)
|
|
1109
|
+
return undefined;
|
|
1110
|
+
const encoding = body.encoding?.toLowerCase();
|
|
1111
|
+
let bytes;
|
|
1112
|
+
try {
|
|
1113
|
+
if (encoding === "utf8") {
|
|
1114
|
+
bytes = new TextEncoder().encode(sanitizeSensitiveText(body.data, options));
|
|
1115
|
+
}
|
|
1116
|
+
else if (encoding === "base64" && options.captureBinaryBodies === true) {
|
|
1117
|
+
bytes = base64ToBytes(body.data);
|
|
1118
|
+
}
|
|
1119
|
+
else {
|
|
1120
|
+
return undefined;
|
|
1121
|
+
}
|
|
1122
|
+
}
|
|
1123
|
+
catch {
|
|
1124
|
+
return undefined;
|
|
1125
|
+
}
|
|
1126
|
+
const originalLength = bytes.length;
|
|
1127
|
+
const captured = encoding === "utf8"
|
|
1128
|
+
? truncateUtf8(bytes, maximum)
|
|
1129
|
+
: bytes.slice(0, maximum);
|
|
1130
|
+
const totalBytes = normalizeSize(body.totalBytes);
|
|
1131
|
+
return {
|
|
1132
|
+
contentType: normalizeOptional(body.contentType, 512),
|
|
1133
|
+
encoding,
|
|
1134
|
+
data: encoding === "base64"
|
|
1135
|
+
? bytesToBase64$1(captured)
|
|
1136
|
+
: new TextDecoder().decode(captured),
|
|
1137
|
+
capturedBytes: captured.length,
|
|
1138
|
+
totalBytes,
|
|
1139
|
+
truncated: body.truncated ||
|
|
1140
|
+
originalLength > captured.length ||
|
|
1141
|
+
(totalBytes != null && totalBytes > captured.length),
|
|
1142
|
+
};
|
|
1143
|
+
}
|
|
1144
|
+
function normalizeRecord(input, options, globalObject) {
|
|
1145
|
+
const now = new Date().toISOString();
|
|
1146
|
+
const startedAtUtc = normalizeTimestamp(input.startedAtUtc, now);
|
|
1147
|
+
const completedAtUtc = normalizeTimestamp(input.completedAtUtc, startedAtUtc);
|
|
1148
|
+
const duration = Number(input.durationMilliseconds);
|
|
1149
|
+
return {
|
|
1150
|
+
schema: networkRequestSchema,
|
|
1151
|
+
id: normalizeRequired(input.id, generateId(globalObject), 128),
|
|
1152
|
+
source: normalizeRequired(input.source, "unknown", 128),
|
|
1153
|
+
startedAtUtc,
|
|
1154
|
+
completedAtUtc: completedAtUtc < startedAtUtc ? startedAtUtc : completedAtUtc,
|
|
1155
|
+
durationMilliseconds: Number.isFinite(duration) && duration >= 0 ? duration : 0,
|
|
1156
|
+
method: normalizeRequired(input.method, "GET", 32).toUpperCase(),
|
|
1157
|
+
url: sanitizeUrl(input.url, options),
|
|
1158
|
+
protocol: normalizeOptional(input.protocol, 64),
|
|
1159
|
+
requestHeaders: options.includeRequestHeaders === false
|
|
1160
|
+
? []
|
|
1161
|
+
: sanitizeHeaders(input.requestHeaders, options),
|
|
1162
|
+
requestBodySizeBytes: options.includeBodySizes === false
|
|
1163
|
+
? undefined
|
|
1164
|
+
: normalizeSize(input.requestBodySizeBytes),
|
|
1165
|
+
requestBody: options.captureRequestBody !== false
|
|
1166
|
+
? normalizeBody(input.requestBody, options)
|
|
1167
|
+
: undefined,
|
|
1168
|
+
statusCode: Number.isInteger(Number(input.statusCode)) &&
|
|
1169
|
+
Number(input.statusCode) >= 100 &&
|
|
1170
|
+
Number(input.statusCode) <= 999
|
|
1171
|
+
? Number(input.statusCode)
|
|
1172
|
+
: undefined,
|
|
1173
|
+
reasonPhrase: normalizeOptional(input.reasonPhrase, 512),
|
|
1174
|
+
responseHeaders: options.includeResponseHeaders === false
|
|
1175
|
+
? []
|
|
1176
|
+
: sanitizeHeaders(input.responseHeaders, options),
|
|
1177
|
+
responseBodySizeBytes: options.includeBodySizes === false
|
|
1178
|
+
? undefined
|
|
1179
|
+
: normalizeSize(input.responseBodySizeBytes),
|
|
1180
|
+
responseBody: options.captureResponseBody !== false
|
|
1181
|
+
? normalizeBody(input.responseBody, options)
|
|
1182
|
+
: undefined,
|
|
1183
|
+
errorType: normalizeOptional(input.errorType, 512),
|
|
1184
|
+
errorMessage: sanitizeErrorMessage(input.errorMessage, options),
|
|
1185
|
+
};
|
|
1186
|
+
}
|
|
1187
|
+
function sanitizeNetworkRequest(input, options = {}, globalObject = globalThis) {
|
|
1188
|
+
try {
|
|
1189
|
+
let normalized = normalizeRecord(input, options, globalObject);
|
|
1190
|
+
if (options.urlSanitizer) {
|
|
1191
|
+
normalized = normalizeRecord({ ...normalized, url: options.urlSanitizer(normalized.url) }, options, globalObject);
|
|
1192
|
+
}
|
|
1193
|
+
if (options.requestSanitizer) {
|
|
1194
|
+
const transformed = options.requestSanitizer(normalized);
|
|
1195
|
+
if (transformed == null)
|
|
1196
|
+
return null;
|
|
1197
|
+
normalized = normalizeRecord(transformed, options, globalObject);
|
|
1198
|
+
}
|
|
1199
|
+
return normalized;
|
|
1200
|
+
}
|
|
1201
|
+
catch {
|
|
1202
|
+
return null;
|
|
1203
|
+
}
|
|
1204
|
+
}
|
|
1205
|
+
function parseContentLength(headers) {
|
|
1206
|
+
const entry = headerEntries(headers).find(([name]) => String(name).toLowerCase() === "content-length");
|
|
1207
|
+
return entry ? normalizeSize(entry[1]) : undefined;
|
|
1208
|
+
}
|
|
1209
|
+
function headerValue(headers, wantedName) {
|
|
1210
|
+
const entry = headerEntries(headers).find(([name]) => String(name).toLowerCase() === wantedName);
|
|
1211
|
+
return entry == null ? undefined : String(entry[1]);
|
|
1212
|
+
}
|
|
1213
|
+
function isTextContentType(contentType) {
|
|
1214
|
+
if (!contentType)
|
|
1215
|
+
return true;
|
|
1216
|
+
const mediaType = contentType.split(";", 1)[0].trim().toLowerCase();
|
|
1217
|
+
return (mediaType.startsWith("text/") ||
|
|
1218
|
+
mediaType.endsWith("+json") ||
|
|
1219
|
+
mediaType.endsWith("+xml") ||
|
|
1220
|
+
[
|
|
1221
|
+
"application/json",
|
|
1222
|
+
"application/xml",
|
|
1223
|
+
"application/graphql",
|
|
1224
|
+
"application/javascript",
|
|
1225
|
+
"application/x-www-form-urlencoded",
|
|
1226
|
+
].includes(mediaType));
|
|
1227
|
+
}
|
|
1228
|
+
function bodyFromBytes(bytes, totalBytes, contentType, options) {
|
|
1229
|
+
const binary = !isTextContentType(contentType);
|
|
1230
|
+
if (binary && options.captureBinaryBodies !== true)
|
|
1231
|
+
return undefined;
|
|
1232
|
+
const maximum = maximumBodyBytes(options);
|
|
1233
|
+
if (maximum <= 0)
|
|
1234
|
+
return undefined;
|
|
1235
|
+
const captured = binary
|
|
1236
|
+
? bytes.slice(0, maximum)
|
|
1237
|
+
: truncateUtf8(bytes, maximum);
|
|
1238
|
+
return {
|
|
1239
|
+
contentType,
|
|
1240
|
+
encoding: binary ? "base64" : "utf8",
|
|
1241
|
+
data: binary ? bytesToBase64$1(captured) : new TextDecoder().decode(captured),
|
|
1242
|
+
capturedBytes: captured.length,
|
|
1243
|
+
totalBytes,
|
|
1244
|
+
truncated: bytes.length > captured.length ||
|
|
1245
|
+
(totalBytes != null && totalBytes > captured.length),
|
|
1246
|
+
};
|
|
1247
|
+
}
|
|
1248
|
+
function bodyFromValue(value, headers, options) {
|
|
1249
|
+
if (value == null || options.captureRequestBody === false)
|
|
1250
|
+
return undefined;
|
|
1251
|
+
const contentType = headerValue(headers, "content-type");
|
|
1252
|
+
if (typeof value === "string" || value instanceof URLSearchParams) {
|
|
1253
|
+
const bytes = new TextEncoder().encode(String(value));
|
|
1254
|
+
return bodyFromBytes(bytes, bytes.length, contentType ||
|
|
1255
|
+
(value instanceof URLSearchParams
|
|
1256
|
+
? "application/x-www-form-urlencoded"
|
|
1257
|
+
: undefined), options);
|
|
1258
|
+
}
|
|
1259
|
+
if (value instanceof ArrayBuffer) {
|
|
1260
|
+
const bytes = new Uint8Array(value);
|
|
1261
|
+
return bodyFromBytes(bytes, bytes.length, contentType, options);
|
|
1262
|
+
}
|
|
1263
|
+
if (ArrayBuffer.isView(value)) {
|
|
1264
|
+
const bytes = new Uint8Array(value.buffer, value.byteOffset, value.byteLength);
|
|
1265
|
+
return bodyFromBytes(bytes, bytes.length, contentType, options);
|
|
1266
|
+
}
|
|
1267
|
+
return undefined;
|
|
1268
|
+
}
|
|
1269
|
+
async function bodyFromFetchResponse(response, headers, options, shouldContinue = () => true) {
|
|
1270
|
+
if (!shouldContinue() || options.captureResponseBody === false)
|
|
1271
|
+
return undefined;
|
|
1272
|
+
const contentType = headerValue(headers, "content-type");
|
|
1273
|
+
if (!isTextContentType(contentType) && options.captureBinaryBodies !== true) {
|
|
1274
|
+
return undefined;
|
|
1275
|
+
}
|
|
1276
|
+
const totalBytes = parseContentLength(headers);
|
|
1277
|
+
const maximum = maximumBodyBytes(options);
|
|
1278
|
+
if (maximum <= 0)
|
|
1279
|
+
return undefined;
|
|
1280
|
+
const clone = response.clone();
|
|
1281
|
+
if (clone.body) {
|
|
1282
|
+
const reader = clone.body.getReader();
|
|
1283
|
+
const chunks = [];
|
|
1284
|
+
let capturedLength = 0;
|
|
1285
|
+
let observedLength = 0;
|
|
1286
|
+
try {
|
|
1287
|
+
while (capturedLength <= maximum) {
|
|
1288
|
+
if (!shouldContinue()) {
|
|
1289
|
+
await reader.cancel().catch(() => undefined);
|
|
1290
|
+
return undefined;
|
|
1291
|
+
}
|
|
1292
|
+
const result = await reader.read();
|
|
1293
|
+
if (!shouldContinue()) {
|
|
1294
|
+
await reader.cancel().catch(() => undefined);
|
|
1295
|
+
return undefined;
|
|
1296
|
+
}
|
|
1297
|
+
if (result.done)
|
|
1298
|
+
break;
|
|
1299
|
+
const chunk = result.value;
|
|
1300
|
+
observedLength += chunk.length;
|
|
1301
|
+
const remaining = maximum - capturedLength;
|
|
1302
|
+
if (remaining > 0) {
|
|
1303
|
+
const kept = chunk.slice(0, remaining);
|
|
1304
|
+
chunks.push(kept);
|
|
1305
|
+
capturedLength += kept.length;
|
|
1306
|
+
}
|
|
1307
|
+
if (observedLength > maximum) {
|
|
1308
|
+
await reader.cancel().catch(() => undefined);
|
|
1309
|
+
break;
|
|
1310
|
+
}
|
|
1311
|
+
}
|
|
1312
|
+
}
|
|
1313
|
+
finally {
|
|
1314
|
+
reader.releaseLock();
|
|
1315
|
+
}
|
|
1316
|
+
const joined = new Uint8Array(capturedLength);
|
|
1317
|
+
let offset = 0;
|
|
1318
|
+
for (const chunk of chunks) {
|
|
1319
|
+
joined.set(chunk, offset);
|
|
1320
|
+
offset += chunk.length;
|
|
1321
|
+
}
|
|
1322
|
+
return bodyFromBytes(joined, totalBytes ?? observedLength, contentType, options);
|
|
1323
|
+
}
|
|
1324
|
+
if (totalBytes == null || totalBytes > maximum)
|
|
1325
|
+
return undefined;
|
|
1326
|
+
const bytes = new Uint8Array(await clone.arrayBuffer());
|
|
1327
|
+
if (!shouldContinue())
|
|
1328
|
+
return undefined;
|
|
1329
|
+
return bodyFromBytes(bytes, totalBytes, contentType, options);
|
|
1330
|
+
}
|
|
1331
|
+
function parseXhrResponseHeaders(value) {
|
|
1332
|
+
return value
|
|
1333
|
+
.trim()
|
|
1334
|
+
.split(/[\r\n]+/)
|
|
1335
|
+
.flatMap((line) => {
|
|
1336
|
+
const separator = line.indexOf(":");
|
|
1337
|
+
return separator < 0
|
|
1338
|
+
? []
|
|
1339
|
+
: [
|
|
1340
|
+
{
|
|
1341
|
+
name: line.slice(0, separator),
|
|
1342
|
+
value: line.slice(separator + 1),
|
|
1343
|
+
},
|
|
1344
|
+
];
|
|
1345
|
+
});
|
|
1346
|
+
}
|
|
1347
|
+
function monotonicNow(globalObject) {
|
|
1348
|
+
return typeof globalObject.performance?.now === "function"
|
|
1349
|
+
? globalObject.performance.now()
|
|
1350
|
+
: Date.now();
|
|
1351
|
+
}
|
|
1352
|
+
function installBrowserNetworkCapture(capture, options = {}, sourcePrefix = "capacitor", globalObject = globalThis) {
|
|
1353
|
+
const cleanups = [];
|
|
1354
|
+
let active = true;
|
|
1355
|
+
let fetchInvocationDepth = 0;
|
|
1356
|
+
if (options.captureFetch !== false &&
|
|
1357
|
+
typeof globalObject.fetch === "function") {
|
|
1358
|
+
const originalFetch = globalObject.fetch;
|
|
1359
|
+
const wrappedFetch = function (input, init) {
|
|
1360
|
+
const startedAtUtc = new Date().toISOString();
|
|
1361
|
+
const started = monotonicNow(globalObject);
|
|
1362
|
+
const inputRequest = typeof input === "object" && "headers" in input && "method" in input
|
|
1363
|
+
? input
|
|
1364
|
+
: undefined;
|
|
1365
|
+
const requestHeaders = headerEntries(inputRequest?.headers).concat(headerEntries(init?.headers));
|
|
1366
|
+
const requestBody = bodyFromValue(init?.body, requestHeaders, options);
|
|
1367
|
+
const method = init?.method || inputRequest?.method || "GET";
|
|
1368
|
+
const url = typeof input === "string" ? input : inputRequest?.url || String(input);
|
|
1369
|
+
let promise;
|
|
1370
|
+
fetchInvocationDepth += 1;
|
|
1371
|
+
try {
|
|
1372
|
+
promise = originalFetch(input, init);
|
|
1373
|
+
}
|
|
1374
|
+
catch (error) {
|
|
1375
|
+
fetchInvocationDepth -= 1;
|
|
1376
|
+
const request = sanitizeNetworkRequest({
|
|
1377
|
+
source: `${sourcePrefix}.fetch`,
|
|
1378
|
+
startedAtUtc,
|
|
1379
|
+
completedAtUtc: new Date().toISOString(),
|
|
1380
|
+
durationMilliseconds: monotonicNow(globalObject) - started,
|
|
1381
|
+
method,
|
|
1382
|
+
url,
|
|
1383
|
+
requestHeaders: sanitizeHeaders(requestHeaders, {}),
|
|
1384
|
+
requestBodySizeBytes: parseContentLength(requestHeaders) ?? requestBody?.totalBytes,
|
|
1385
|
+
requestBody,
|
|
1386
|
+
errorType: error instanceof Error ? error.name : "Error",
|
|
1387
|
+
errorMessage: error instanceof Error ? error.message : String(error),
|
|
1388
|
+
}, options, globalObject);
|
|
1389
|
+
if (active && request)
|
|
1390
|
+
Promise.resolve(capture(request)).catch(() => undefined);
|
|
1391
|
+
throw error;
|
|
1392
|
+
}
|
|
1393
|
+
fetchInvocationDepth -= 1;
|
|
1394
|
+
return promise.then((response) => {
|
|
1395
|
+
if (!active)
|
|
1396
|
+
return response;
|
|
1397
|
+
const responseHeaders = headerEntries(response.headers);
|
|
1398
|
+
const responseRecord = {
|
|
1399
|
+
source: `${sourcePrefix}.fetch`,
|
|
1400
|
+
startedAtUtc,
|
|
1401
|
+
completedAtUtc: new Date().toISOString(),
|
|
1402
|
+
durationMilliseconds: monotonicNow(globalObject) - started,
|
|
1403
|
+
method,
|
|
1404
|
+
url: response.url || url,
|
|
1405
|
+
requestHeaders: sanitizeHeaders(requestHeaders, {}),
|
|
1406
|
+
requestBodySizeBytes: parseContentLength(requestHeaders) ?? requestBody?.totalBytes,
|
|
1407
|
+
requestBody,
|
|
1408
|
+
statusCode: response.status,
|
|
1409
|
+
reasonPhrase: response.statusText,
|
|
1410
|
+
responseHeaders: sanitizeHeaders(responseHeaders, {}),
|
|
1411
|
+
responseBodySizeBytes: parseContentLength(responseHeaders),
|
|
1412
|
+
};
|
|
1413
|
+
return bodyFromFetchResponse(response, responseHeaders, options, () => active).then((responseBody) => {
|
|
1414
|
+
const request = sanitizeNetworkRequest({
|
|
1415
|
+
...responseRecord,
|
|
1416
|
+
responseBody,
|
|
1417
|
+
responseBodySizeBytes: responseRecord.responseBodySizeBytes ??
|
|
1418
|
+
responseBody?.totalBytes,
|
|
1419
|
+
}, options, globalObject);
|
|
1420
|
+
if (active && request)
|
|
1421
|
+
void Promise.resolve(capture(request)).catch(() => undefined);
|
|
1422
|
+
return response;
|
|
1423
|
+
}, () => {
|
|
1424
|
+
const request = sanitizeNetworkRequest(responseRecord, options, globalObject);
|
|
1425
|
+
if (active && request)
|
|
1426
|
+
void Promise.resolve(capture(request)).catch(() => undefined);
|
|
1427
|
+
return response;
|
|
1428
|
+
});
|
|
1429
|
+
}, (error) => {
|
|
1430
|
+
const request = sanitizeNetworkRequest({
|
|
1431
|
+
source: `${sourcePrefix}.fetch`,
|
|
1432
|
+
startedAtUtc,
|
|
1433
|
+
completedAtUtc: new Date().toISOString(),
|
|
1434
|
+
durationMilliseconds: monotonicNow(globalObject) - started,
|
|
1435
|
+
method,
|
|
1436
|
+
url,
|
|
1437
|
+
requestHeaders: sanitizeHeaders(requestHeaders, {}),
|
|
1438
|
+
requestBodySizeBytes: parseContentLength(requestHeaders) ?? requestBody?.totalBytes,
|
|
1439
|
+
requestBody,
|
|
1440
|
+
errorType: error instanceof Error ? error.name : "Error",
|
|
1441
|
+
errorMessage: error instanceof Error ? error.message : String(error),
|
|
1442
|
+
}, options, globalObject);
|
|
1443
|
+
if (active && request)
|
|
1444
|
+
Promise.resolve(capture(request)).catch(() => undefined);
|
|
1445
|
+
throw error;
|
|
1446
|
+
});
|
|
1447
|
+
};
|
|
1448
|
+
globalObject.fetch = wrappedFetch;
|
|
1449
|
+
cleanups.push(() => {
|
|
1450
|
+
if (globalObject.fetch === wrappedFetch)
|
|
1451
|
+
globalObject.fetch = originalFetch;
|
|
1452
|
+
});
|
|
1453
|
+
}
|
|
1454
|
+
const Xhr = globalObject.XMLHttpRequest;
|
|
1455
|
+
if (options.captureXmlHttpRequest !== false && Xhr?.prototype) {
|
|
1456
|
+
const states = new WeakMap();
|
|
1457
|
+
const prototype = Xhr.prototype;
|
|
1458
|
+
const originalOpen = prototype.open;
|
|
1459
|
+
const originalSend = prototype.send;
|
|
1460
|
+
const originalSetRequestHeader = prototype.setRequestHeader;
|
|
1461
|
+
const wrappedOpen = function (method, url, ...rest) {
|
|
1462
|
+
states.set(this, {
|
|
1463
|
+
method,
|
|
1464
|
+
url: String(url),
|
|
1465
|
+
requestHeaders: [],
|
|
1466
|
+
suppressed: fetchInvocationDepth > 0,
|
|
1467
|
+
});
|
|
1468
|
+
Reflect.apply(originalOpen, this, [method, url, ...rest]);
|
|
1469
|
+
};
|
|
1470
|
+
const wrappedSetRequestHeader = function (name, value) {
|
|
1471
|
+
states.get(this)?.requestHeaders.push({ name, value });
|
|
1472
|
+
Reflect.apply(originalSetRequestHeader, this, [name, value]);
|
|
1473
|
+
};
|
|
1474
|
+
const wrappedSend = function (body) {
|
|
1475
|
+
const state = states.get(this);
|
|
1476
|
+
if (!state || state.suppressed) {
|
|
1477
|
+
Reflect.apply(originalSend, this, [body]);
|
|
1478
|
+
return;
|
|
1479
|
+
}
|
|
1480
|
+
state.startedAtUtc = new Date().toISOString();
|
|
1481
|
+
state.started = monotonicNow(globalObject);
|
|
1482
|
+
state.requestBody = bodyFromValue(body, state.requestHeaders, options);
|
|
1483
|
+
let failure;
|
|
1484
|
+
const markFailure = (event) => {
|
|
1485
|
+
failure = event.type;
|
|
1486
|
+
};
|
|
1487
|
+
const complete = () => {
|
|
1488
|
+
if (!active)
|
|
1489
|
+
return;
|
|
1490
|
+
let responseHeaders = [];
|
|
1491
|
+
try {
|
|
1492
|
+
responseHeaders = parseXhrResponseHeaders(this.getAllResponseHeaders());
|
|
1493
|
+
}
|
|
1494
|
+
catch {
|
|
1495
|
+
// Some WebViews throw before response headers exist.
|
|
1496
|
+
}
|
|
1497
|
+
let responseBody;
|
|
1498
|
+
try {
|
|
1499
|
+
const responseType = this.responseType || "text";
|
|
1500
|
+
const responseOptions = {
|
|
1501
|
+
...options,
|
|
1502
|
+
captureRequestBody: options.captureResponseBody,
|
|
1503
|
+
};
|
|
1504
|
+
if (responseType === "text") {
|
|
1505
|
+
responseBody = bodyFromValue(this.responseText, responseHeaders, responseOptions);
|
|
1506
|
+
}
|
|
1507
|
+
else if (responseType === "arraybuffer") {
|
|
1508
|
+
responseBody = bodyFromValue(this.response, responseHeaders, responseOptions);
|
|
1509
|
+
}
|
|
1510
|
+
}
|
|
1511
|
+
catch {
|
|
1512
|
+
// Response data is not readable for every XHR response type.
|
|
1513
|
+
}
|
|
1514
|
+
const request = sanitizeNetworkRequest({
|
|
1515
|
+
source: `${sourcePrefix}.xhr`,
|
|
1516
|
+
startedAtUtc: state.startedAtUtc,
|
|
1517
|
+
completedAtUtc: new Date().toISOString(),
|
|
1518
|
+
durationMilliseconds: monotonicNow(globalObject) - (state.started ?? 0),
|
|
1519
|
+
method: state.method,
|
|
1520
|
+
url: this.responseURL || state.url,
|
|
1521
|
+
requestHeaders: state.requestHeaders,
|
|
1522
|
+
requestBodySizeBytes: parseContentLength(state.requestHeaders) ??
|
|
1523
|
+
state.requestBody?.totalBytes,
|
|
1524
|
+
requestBody: state.requestBody,
|
|
1525
|
+
statusCode: this.status || undefined,
|
|
1526
|
+
reasonPhrase: this.statusText,
|
|
1527
|
+
responseHeaders,
|
|
1528
|
+
responseBodySizeBytes: parseContentLength(responseHeaders) ?? responseBody?.totalBytes,
|
|
1529
|
+
responseBody,
|
|
1530
|
+
errorType: failure,
|
|
1531
|
+
errorMessage: failure ? `XMLHttpRequest ${failure}` : undefined,
|
|
1532
|
+
}, options, globalObject);
|
|
1533
|
+
if (request)
|
|
1534
|
+
Promise.resolve(capture(request)).catch(() => undefined);
|
|
1535
|
+
};
|
|
1536
|
+
this.addEventListener("error", markFailure);
|
|
1537
|
+
this.addEventListener("abort", markFailure);
|
|
1538
|
+
this.addEventListener("timeout", markFailure);
|
|
1539
|
+
this.addEventListener("loadend", complete, { once: true });
|
|
1540
|
+
Reflect.apply(originalSend, this, [body]);
|
|
1541
|
+
};
|
|
1542
|
+
prototype.open = wrappedOpen;
|
|
1543
|
+
prototype.setRequestHeader = wrappedSetRequestHeader;
|
|
1544
|
+
prototype.send = wrappedSend;
|
|
1545
|
+
cleanups.push(() => {
|
|
1546
|
+
if (prototype.open === wrappedOpen)
|
|
1547
|
+
prototype.open = originalOpen;
|
|
1548
|
+
if (prototype.send === wrappedSend)
|
|
1549
|
+
prototype.send = originalSend;
|
|
1550
|
+
if (prototype.setRequestHeader === wrappedSetRequestHeader) {
|
|
1551
|
+
prototype.setRequestHeader = originalSetRequestHeader;
|
|
1552
|
+
}
|
|
1553
|
+
});
|
|
1554
|
+
}
|
|
1555
|
+
let removed = false;
|
|
1556
|
+
return {
|
|
1557
|
+
remove() {
|
|
1558
|
+
if (removed)
|
|
1559
|
+
return;
|
|
1560
|
+
removed = true;
|
|
1561
|
+
active = false;
|
|
1562
|
+
for (const cleanup of cleanups.reverse())
|
|
1563
|
+
cleanup();
|
|
1564
|
+
},
|
|
1565
|
+
};
|
|
1566
|
+
}
|
|
1567
|
+
|
|
1568
|
+
const ANSIGHT_CAPACITOR_SDK_VERSION = "1.4.0-preview.1";
|
|
1569
|
+
const COMPILED_CAPACITOR_CORE_VERSION = "8.4.2";
|
|
1570
|
+
const CAPACITOR_GROUP = "capacitor";
|
|
1571
|
+
const LOCALIZATION_GROUP = "localization";
|
|
1572
|
+
function normalized(value) {
|
|
1573
|
+
if (value == null)
|
|
1574
|
+
return undefined;
|
|
1575
|
+
const result = String(value).trim();
|
|
1576
|
+
return result || undefined;
|
|
1577
|
+
}
|
|
1578
|
+
function canonicalizeLocale(value) {
|
|
1579
|
+
const locale = normalized(value)?.replace(/_/g, "-");
|
|
1580
|
+
if (!locale)
|
|
1581
|
+
return undefined;
|
|
1582
|
+
try {
|
|
1583
|
+
return Intl.getCanonicalLocales(locale)[0] ?? locale;
|
|
1584
|
+
}
|
|
1585
|
+
catch {
|
|
1586
|
+
return locale;
|
|
1587
|
+
}
|
|
1588
|
+
}
|
|
1589
|
+
function parseLocale(locale) {
|
|
1590
|
+
const parts = (locale ?? "").split("-").filter(Boolean);
|
|
1591
|
+
const language = parts[0]?.toLowerCase();
|
|
1592
|
+
const region = parts.find((part, index) => index > 0 && (/^[A-Za-z]{2}$/.test(part) || /^\d{3}$/.test(part)));
|
|
1593
|
+
return { language, region: region?.toUpperCase() };
|
|
1594
|
+
}
|
|
1595
|
+
function webViewDetails(platform, nativePlatform, userAgent) {
|
|
1596
|
+
const agent = userAgent ?? "";
|
|
1597
|
+
if (nativePlatform && platform === "ios") {
|
|
1598
|
+
return {
|
|
1599
|
+
engine: "wkWebView",
|
|
1600
|
+
version: /AppleWebKit\/([^\s]+)/.exec(agent)?.[1],
|
|
1601
|
+
};
|
|
1602
|
+
}
|
|
1603
|
+
if (nativePlatform && platform === "android") {
|
|
1604
|
+
return {
|
|
1605
|
+
engine: "chromiumWebView",
|
|
1606
|
+
version: /(?:Chrome|Chromium)\/([^\s]+)/.exec(agent)?.[1],
|
|
1607
|
+
};
|
|
1608
|
+
}
|
|
1609
|
+
if (/Firefox\/([^\s]+)/.test(agent)) {
|
|
1610
|
+
return { engine: "gecko", version: /Firefox\/([^\s]+)/.exec(agent)?.[1] };
|
|
1611
|
+
}
|
|
1612
|
+
if (/(?:Chrome|Chromium)\/([^\s]+)/.test(agent)) {
|
|
1613
|
+
return {
|
|
1614
|
+
engine: "chromium",
|
|
1615
|
+
version: /(?:Chrome|Chromium)\/([^\s]+)/.exec(agent)?.[1],
|
|
1616
|
+
};
|
|
1617
|
+
}
|
|
1618
|
+
if (/AppleWebKit\/([^\s]+)/.test(agent)) {
|
|
1619
|
+
return {
|
|
1620
|
+
engine: "webkit",
|
|
1621
|
+
version: /AppleWebKit\/([^\s]+)/.exec(agent)?.[1],
|
|
1622
|
+
};
|
|
1623
|
+
}
|
|
1624
|
+
return { engine: "unknown" };
|
|
1625
|
+
}
|
|
1626
|
+
function currentCapacitorSessionEnvironment(platform, nativePlatform) {
|
|
1627
|
+
let resolved;
|
|
1628
|
+
try {
|
|
1629
|
+
resolved = Intl.DateTimeFormat().resolvedOptions();
|
|
1630
|
+
}
|
|
1631
|
+
catch {
|
|
1632
|
+
resolved = undefined;
|
|
1633
|
+
}
|
|
1634
|
+
return {
|
|
1635
|
+
platform,
|
|
1636
|
+
nativePlatform,
|
|
1637
|
+
userAgent: typeof navigator === "undefined" ? undefined : navigator.userAgent,
|
|
1638
|
+
locale: resolved?.locale ??
|
|
1639
|
+
(typeof navigator === "undefined" ? undefined : navigator.language),
|
|
1640
|
+
timeZone: resolved?.timeZone,
|
|
1641
|
+
utcOffsetMinutes: -new Date().getTimezoneOffset(),
|
|
1642
|
+
};
|
|
1643
|
+
}
|
|
1644
|
+
function createAutomaticSessionProperties(environment) {
|
|
1645
|
+
const platform = normalized(environment.platform) ?? "unknown";
|
|
1646
|
+
const userAgent = normalized(environment.userAgent);
|
|
1647
|
+
const webView = webViewDetails(platform, environment.nativePlatform, userAgent);
|
|
1648
|
+
const locale = canonicalizeLocale(environment.locale);
|
|
1649
|
+
const parsedLocale = parseLocale(locale);
|
|
1650
|
+
const capacitor = {
|
|
1651
|
+
sdkVersion: ANSIGHT_CAPACITOR_SDK_VERSION,
|
|
1652
|
+
capacitorVersion: "8.x",
|
|
1653
|
+
compiledCapacitorVersion: COMPILED_CAPACITOR_CORE_VERSION,
|
|
1654
|
+
platform,
|
|
1655
|
+
runtimeLanguage: "javascript",
|
|
1656
|
+
executionMode: environment.nativePlatform ? "native" : "web",
|
|
1657
|
+
webViewEngine: webView.engine,
|
|
1658
|
+
};
|
|
1659
|
+
if (webView.version)
|
|
1660
|
+
capacitor.webViewEngineVersion = webView.version;
|
|
1661
|
+
if (userAgent)
|
|
1662
|
+
capacitor.userAgent = userAgent;
|
|
1663
|
+
const localization = {
|
|
1664
|
+
utcOffsetMinutes: String(environment.utcOffsetMinutes ?? -new Date().getTimezoneOffset()),
|
|
1665
|
+
};
|
|
1666
|
+
if (locale)
|
|
1667
|
+
localization.locale = locale;
|
|
1668
|
+
if (parsedLocale.language)
|
|
1669
|
+
localization.language = parsedLocale.language;
|
|
1670
|
+
if (parsedLocale.region)
|
|
1671
|
+
localization.region = parsedLocale.region;
|
|
1672
|
+
if (normalized(environment.timeZone)) {
|
|
1673
|
+
localization.timeZone = String(environment.timeZone).trim();
|
|
1674
|
+
}
|
|
1675
|
+
return {
|
|
1676
|
+
[CAPACITOR_GROUP]: capacitor,
|
|
1677
|
+
[LOCALIZATION_GROUP]: localization,
|
|
1678
|
+
};
|
|
1679
|
+
}
|
|
1680
|
+
function mergeSessionProperties(automaticProperties, customProperties) {
|
|
1681
|
+
const merged = Object.fromEntries(Object.entries(automaticProperties).map(([group, properties]) => [
|
|
1682
|
+
group,
|
|
1683
|
+
{ ...properties },
|
|
1684
|
+
]));
|
|
1685
|
+
for (const [group, properties] of Object.entries(customProperties ?? {})) {
|
|
1686
|
+
merged[group] = { ...(merged[group] ?? {}), ...properties };
|
|
1687
|
+
}
|
|
1688
|
+
return merged;
|
|
1689
|
+
}
|
|
1690
|
+
|
|
732
1691
|
const AnsightNative = core.registerPlugin("Ansight");
|
|
733
1692
|
const toolHandlers = new Map();
|
|
734
1693
|
const artifactProviders = new Map();
|
|
@@ -739,6 +1698,9 @@ var capacitorAnsight = (function (exports, core) {
|
|
|
739
1698
|
let lifecycleCleanup;
|
|
740
1699
|
let artifactToolRegistrations = [];
|
|
741
1700
|
let domToolRegistration;
|
|
1701
|
+
let networkCaptureSubscription;
|
|
1702
|
+
let networkCaptureRegistration;
|
|
1703
|
+
let networkConnectionListener;
|
|
742
1704
|
function normalizePairingPayload(payload) {
|
|
743
1705
|
if (payload == null)
|
|
744
1706
|
return payload;
|
|
@@ -746,11 +1708,19 @@ var capacitorAnsight = (function (exports, core) {
|
|
|
746
1708
|
}
|
|
747
1709
|
function normalizeOptions(input) {
|
|
748
1710
|
const options = JSON.parse(JSON.stringify(input));
|
|
1711
|
+
options.customProperties = mergeSessionProperties(automaticSessionProperties(), options.customProperties);
|
|
749
1712
|
delete options.domTools;
|
|
750
1713
|
delete options.errorCapture;
|
|
751
1714
|
delete options.lifecycle;
|
|
1715
|
+
delete options.networkCapture;
|
|
752
1716
|
return options;
|
|
753
1717
|
}
|
|
1718
|
+
function automaticSessionProperties() {
|
|
1719
|
+
return createAutomaticSessionProperties(currentCapacitorSessionEnvironment(core.Capacitor.getPlatform(), core.Capacitor.isNativePlatform()));
|
|
1720
|
+
}
|
|
1721
|
+
function automaticSessionPropertyValue(group, key) {
|
|
1722
|
+
return automaticSessionProperties()[group]?.[key];
|
|
1723
|
+
}
|
|
754
1724
|
function normalizeToolResult(value) {
|
|
755
1725
|
if (value && typeof value === "object" && "success" in value) {
|
|
756
1726
|
return value;
|
|
@@ -800,11 +1770,13 @@ var capacitorAnsight = (function (exports, core) {
|
|
|
800
1770
|
}
|
|
801
1771
|
async function afterConnectionChange(operation) {
|
|
802
1772
|
const result = await operation();
|
|
1773
|
+
await refreshNetworkCaptureConnection();
|
|
803
1774
|
await emitHostConnectionStatus();
|
|
804
1775
|
return result;
|
|
805
1776
|
}
|
|
806
1777
|
async function initialize(options = {}) {
|
|
807
1778
|
const result = await AnsightNative.initialize(normalizeOptions(options));
|
|
1779
|
+
await configureNetworkCapture(options.networkCapture);
|
|
808
1780
|
if (options.lifecycle !== false)
|
|
809
1781
|
startLifecycleTracking();
|
|
810
1782
|
if (options.errorCapture) {
|
|
@@ -818,6 +1790,7 @@ var capacitorAnsight = (function (exports, core) {
|
|
|
818
1790
|
}
|
|
819
1791
|
async function initializeAndActivate(options = {}) {
|
|
820
1792
|
const result = await AnsightNative.initializeAndActivate(normalizeOptions(options));
|
|
1793
|
+
await configureNetworkCapture(options.networkCapture);
|
|
821
1794
|
if (options.lifecycle !== false)
|
|
822
1795
|
startLifecycleTracking();
|
|
823
1796
|
if (options.errorCapture) {
|
|
@@ -842,6 +1815,80 @@ var capacitorAnsight = (function (exports, core) {
|
|
|
842
1815
|
return AnsightNative.recordEvent(typeof input === "string" ? { label: input } : input);
|
|
843
1816
|
}
|
|
844
1817
|
const recordEvent = event;
|
|
1818
|
+
async function recordNetworkRequest(input, sanitizationOptions = {}) {
|
|
1819
|
+
const request = sanitizeNetworkRequest(input, sanitizationOptions);
|
|
1820
|
+
if (!request) {
|
|
1821
|
+
return {
|
|
1822
|
+
success: false,
|
|
1823
|
+
message: "Network request capture was suppressed by the sanitizer.",
|
|
1824
|
+
};
|
|
1825
|
+
}
|
|
1826
|
+
return AnsightNative.recordNetworkRequest(request);
|
|
1827
|
+
}
|
|
1828
|
+
function installNetworkCapture(options = {}) {
|
|
1829
|
+
uninstallNetworkCapture();
|
|
1830
|
+
const registration = { options };
|
|
1831
|
+
networkCaptureRegistration = registration;
|
|
1832
|
+
ensureNetworkConnectionListener();
|
|
1833
|
+
void refreshNetworkCaptureConnection();
|
|
1834
|
+
return {
|
|
1835
|
+
remove() {
|
|
1836
|
+
if (networkCaptureRegistration === registration) {
|
|
1837
|
+
uninstallNetworkCapture();
|
|
1838
|
+
}
|
|
1839
|
+
},
|
|
1840
|
+
};
|
|
1841
|
+
}
|
|
1842
|
+
function uninstallNetworkCapture() {
|
|
1843
|
+
networkCaptureRegistration = undefined;
|
|
1844
|
+
const listener = networkConnectionListener;
|
|
1845
|
+
networkConnectionListener = undefined;
|
|
1846
|
+
if (listener)
|
|
1847
|
+
void listener.then((value) => value.remove());
|
|
1848
|
+
detachNetworkCapture();
|
|
1849
|
+
}
|
|
1850
|
+
function detachNetworkCapture() {
|
|
1851
|
+
networkCaptureSubscription?.remove();
|
|
1852
|
+
networkCaptureSubscription = undefined;
|
|
1853
|
+
}
|
|
1854
|
+
async function refreshNetworkCaptureConnection() {
|
|
1855
|
+
const registration = networkCaptureRegistration;
|
|
1856
|
+
if (!registration) {
|
|
1857
|
+
detachNetworkCapture();
|
|
1858
|
+
return;
|
|
1859
|
+
}
|
|
1860
|
+
try {
|
|
1861
|
+
const status = await AnsightNative.hostConnectionStatus();
|
|
1862
|
+
if (networkCaptureRegistration !== registration)
|
|
1863
|
+
return;
|
|
1864
|
+
applyNetworkConnectionStatus(status);
|
|
1865
|
+
}
|
|
1866
|
+
catch {
|
|
1867
|
+
if (networkCaptureRegistration === registration)
|
|
1868
|
+
detachNetworkCapture();
|
|
1869
|
+
}
|
|
1870
|
+
}
|
|
1871
|
+
function ensureNetworkConnectionListener() {
|
|
1872
|
+
networkConnectionListener ??= AnsightNative.addListener("ansightHostConnectionStatus", applyNetworkConnectionStatus);
|
|
1873
|
+
}
|
|
1874
|
+
function applyNetworkConnectionStatus(status) {
|
|
1875
|
+
const registration = networkCaptureRegistration;
|
|
1876
|
+
if (!registration || status.isConnected !== true) {
|
|
1877
|
+
detachNetworkCapture();
|
|
1878
|
+
return;
|
|
1879
|
+
}
|
|
1880
|
+
networkCaptureSubscription ??= installBrowserNetworkCapture((request) => AnsightNative.recordNetworkRequest(request), registration.options);
|
|
1881
|
+
}
|
|
1882
|
+
async function configureNetworkCapture(value) {
|
|
1883
|
+
uninstallNetworkCapture();
|
|
1884
|
+
if (!value)
|
|
1885
|
+
return;
|
|
1886
|
+
networkCaptureRegistration = {
|
|
1887
|
+
options: typeof value === "object" ? value : {},
|
|
1888
|
+
};
|
|
1889
|
+
ensureNetworkConnectionListener();
|
|
1890
|
+
await refreshNetworkCaptureConnection();
|
|
1891
|
+
}
|
|
845
1892
|
const recordCrashCandidate = (input) => AnsightNative.recordCrashCandidate(input);
|
|
846
1893
|
const screenViewed = (name, details = {}) => AnsightNative.screenViewed({ name, details });
|
|
847
1894
|
const trackRoute = screenViewed;
|
|
@@ -897,12 +1944,25 @@ var capacitorAnsight = (function (exports, core) {
|
|
|
897
1944
|
const captureScreenFrame = (options = {}) => AnsightNative.captureScreenFrame(options);
|
|
898
1945
|
const enableTouchCapture = () => AnsightNative.enableTouchCapture();
|
|
899
1946
|
const disableTouchCapture = () => AnsightNative.disableTouchCapture();
|
|
900
|
-
const updateSessionProperties = (properties) => AnsightNative.updateSessionProperties({
|
|
1947
|
+
const updateSessionProperties = (properties) => AnsightNative.updateSessionProperties({
|
|
1948
|
+
properties: mergeSessionProperties(automaticSessionProperties(), properties),
|
|
1949
|
+
});
|
|
901
1950
|
const updateCustomProperties = updateSessionProperties;
|
|
902
|
-
const clearSessionProperties = () => AnsightNative.
|
|
1951
|
+
const clearSessionProperties = () => AnsightNative.updateSessionProperties({
|
|
1952
|
+
properties: automaticSessionProperties(),
|
|
1953
|
+
});
|
|
903
1954
|
const clearCustomProperties = clearSessionProperties;
|
|
904
1955
|
const registerCustomProperty = (group, key, value) => AnsightNative.registerCustomProperty({ group, key, value });
|
|
905
|
-
const removeCustomProperty = (group, key) =>
|
|
1956
|
+
const removeCustomProperty = (group, key) => {
|
|
1957
|
+
const automaticValue = automaticSessionPropertyValue(group, key);
|
|
1958
|
+
return automaticValue == null
|
|
1959
|
+
? AnsightNative.removeCustomProperty({ group, key })
|
|
1960
|
+
: AnsightNative.registerCustomProperty({
|
|
1961
|
+
group,
|
|
1962
|
+
key,
|
|
1963
|
+
value: automaticValue,
|
|
1964
|
+
});
|
|
1965
|
+
};
|
|
906
1966
|
function addHostConnectionStatusListener(listener, options = {}) {
|
|
907
1967
|
hostConnectionListeners.add(listener);
|
|
908
1968
|
if (options.emitCurrent !== false)
|
|
@@ -989,7 +2049,7 @@ var capacitorAnsight = (function (exports, core) {
|
|
|
989
2049
|
name: "Query JavaScript artifacts",
|
|
990
2050
|
description: "Lists artifacts exposed by Capacitor JavaScript providers.",
|
|
991
2051
|
category: "Artifacts",
|
|
992
|
-
|
|
2052
|
+
policy: "read",
|
|
993
2053
|
}, async (_args, context) => {
|
|
994
2054
|
const definitions = [];
|
|
995
2055
|
for (const provider of artifactProviders.values()) {
|
|
@@ -1020,7 +2080,7 @@ var capacitorAnsight = (function (exports, core) {
|
|
|
1020
2080
|
name: "Request JavaScript artifact",
|
|
1021
2081
|
description: "Creates an artifact through a Capacitor JavaScript provider.",
|
|
1022
2082
|
category: "Artifacts",
|
|
1023
|
-
|
|
2083
|
+
policy: "read",
|
|
1024
2084
|
argumentsSchema: {
|
|
1025
2085
|
type: "object",
|
|
1026
2086
|
required: ["providerId", "artifactId"],
|
|
@@ -1253,6 +2313,10 @@ var capacitorAnsight = (function (exports, core) {
|
|
|
1253
2313
|
recordMetric,
|
|
1254
2314
|
event,
|
|
1255
2315
|
recordEvent,
|
|
2316
|
+
recordNetworkRequest,
|
|
2317
|
+
installNetworkCapture,
|
|
2318
|
+
uninstallNetworkCapture,
|
|
2319
|
+
sanitizeNetworkRequest,
|
|
1256
2320
|
screenViewed,
|
|
1257
2321
|
trackRoute,
|
|
1258
2322
|
setAppLifecycleState,
|
|
@@ -1350,6 +2414,7 @@ var capacitorAnsight = (function (exports, core) {
|
|
|
1350
2414
|
exports.initializeAndActivate = initializeAndActivate;
|
|
1351
2415
|
exports.installDomTools = installDomTools;
|
|
1352
2416
|
exports.installErrorHandlers = installErrorHandlers;
|
|
2417
|
+
exports.installNetworkCapture = installNetworkCapture;
|
|
1353
2418
|
exports.isFramesPerSecondEnabled = isFramesPerSecondEnabled;
|
|
1354
2419
|
exports.listRegisteredArtifactProviders = listRegisteredArtifactProviders;
|
|
1355
2420
|
exports.listRegisteredTools = listRegisteredTools;
|
|
@@ -1359,6 +2424,7 @@ var capacitorAnsight = (function (exports, core) {
|
|
|
1359
2424
|
exports.recordCrashCandidate = recordCrashCandidate;
|
|
1360
2425
|
exports.recordEvent = recordEvent;
|
|
1361
2426
|
exports.recordMetric = recordMetric;
|
|
2427
|
+
exports.recordNetworkRequest = recordNetworkRequest;
|
|
1362
2428
|
exports.recordedEvents = recordedEvents;
|
|
1363
2429
|
exports.recordedMetrics = recordedMetrics;
|
|
1364
2430
|
exports.registerArtifactProvider = registerArtifactProvider;
|
|
@@ -1367,6 +2433,7 @@ var capacitorAnsight = (function (exports, core) {
|
|
|
1367
2433
|
exports.registerMetricChannel = registerMetricChannel;
|
|
1368
2434
|
exports.registerTool = registerTool;
|
|
1369
2435
|
exports.removeCustomProperty = removeCustomProperty;
|
|
2436
|
+
exports.sanitizeNetworkRequest = sanitizeNetworkRequest;
|
|
1370
2437
|
exports.savePairingConfig = savePairingConfig;
|
|
1371
2438
|
exports.scanPairingQrCode = scanPairingQrCode;
|
|
1372
2439
|
exports.screenViewed = screenViewed;
|
|
@@ -1380,6 +2447,7 @@ var capacitorAnsight = (function (exports, core) {
|
|
|
1380
2447
|
exports.stopLifecycleTracking = stopLifecycleTracking;
|
|
1381
2448
|
exports.trackRoute = trackRoute;
|
|
1382
2449
|
exports.uninstallDomTools = uninstallDomTools;
|
|
2450
|
+
exports.uninstallNetworkCapture = uninstallNetworkCapture;
|
|
1383
2451
|
exports.unregisterArtifactProvider = unregisterArtifactProvider;
|
|
1384
2452
|
exports.unregisterTool = unregisterTool;
|
|
1385
2453
|
exports.updateCustomProperties = updateCustomProperties;
|