@mhosaic/feedback 0.14.0 → 0.15.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/dist/{chunk-A4MBOFRR.mjs → chunk-67JM6XVT.mjs} +69 -28
- package/dist/chunk-67JM6XVT.mjs.map +1 -0
- package/dist/{chunk-DKE6ELJ4.mjs → chunk-FGA63IEZ.mjs} +16 -4
- package/dist/chunk-FGA63IEZ.mjs.map +1 -0
- package/dist/embed.min.js +4 -4
- package/dist/embed.min.js.map +1 -1
- package/dist/error-tracking.d.ts +19 -0
- package/dist/error-tracking.mjs +23 -3
- package/dist/error-tracking.mjs.map +1 -1
- package/dist/index.mjs +2 -2
- package/dist/react.mjs +2 -2
- package/dist/webvitals.mjs +1 -1
- package/package.json +1 -1
- package/dist/chunk-A4MBOFRR.mjs.map +0 -1
- package/dist/chunk-DKE6ELJ4.mjs.map +0 -1
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import {
|
|
2
2
|
scrubCredentials
|
|
3
|
-
} from "./chunk-
|
|
3
|
+
} from "./chunk-FGA63IEZ.mjs";
|
|
4
4
|
|
|
5
5
|
// src/api/client.ts
|
|
6
6
|
var SCALAR_FIELDS = [
|
|
@@ -12,6 +12,23 @@ var SCALAR_FIELDS = [
|
|
|
12
12
|
"user_agent",
|
|
13
13
|
"capture_method"
|
|
14
14
|
];
|
|
15
|
+
function assertSafeEndpoint(endpoint) {
|
|
16
|
+
let parsed;
|
|
17
|
+
try {
|
|
18
|
+
parsed = new URL(endpoint);
|
|
19
|
+
} catch {
|
|
20
|
+
throw new Error(
|
|
21
|
+
`[mhosaic-feedback] \`endpoint\` is not a valid URL: ${endpoint}`
|
|
22
|
+
);
|
|
23
|
+
}
|
|
24
|
+
if (parsed.protocol === "https:") return;
|
|
25
|
+
if (parsed.protocol === "http:" && (parsed.hostname === "localhost" || parsed.hostname === "127.0.0.1" || parsed.hostname === "[::1]")) {
|
|
26
|
+
return;
|
|
27
|
+
}
|
|
28
|
+
throw new Error(
|
|
29
|
+
`[mhosaic-feedback] \`endpoint\` must use https:// (got ${parsed.protocol}//${parsed.hostname}). http:// is only allowed for localhost in dev.`
|
|
30
|
+
);
|
|
31
|
+
}
|
|
15
32
|
function createApiClient(options) {
|
|
16
33
|
const endpoint = (options.endpoint ?? "").replace(/\/+$/, "");
|
|
17
34
|
if (!endpoint) {
|
|
@@ -19,6 +36,7 @@ function createApiClient(options) {
|
|
|
19
36
|
'[mhosaic-feedback] `endpoint` is required (e.g. "https://feedback.example.com").'
|
|
20
37
|
);
|
|
21
38
|
}
|
|
39
|
+
assertSafeEndpoint(endpoint);
|
|
22
40
|
const fetcher = options.fetch ?? globalThis.fetch;
|
|
23
41
|
async function submitReport(input) {
|
|
24
42
|
let payload = input;
|
|
@@ -872,6 +890,20 @@ function truncateUrl(url, maxLength = 80) {
|
|
|
872
890
|
const keepEnd = maxLength - 1 - keepStart;
|
|
873
891
|
return `${url.slice(0, keepStart)}\u2026${url.slice(url.length - keepEnd)}`;
|
|
874
892
|
}
|
|
893
|
+
function safeExternalHref(url) {
|
|
894
|
+
if (!url) return void 0;
|
|
895
|
+
let parsed;
|
|
896
|
+
try {
|
|
897
|
+
parsed = new URL(url);
|
|
898
|
+
} catch {
|
|
899
|
+
return void 0;
|
|
900
|
+
}
|
|
901
|
+
if (parsed.protocol === "https:") return parsed.toString();
|
|
902
|
+
if (parsed.protocol === "http:" && (parsed.hostname === "localhost" || parsed.hostname === "127.0.0.1" || parsed.hostname === "[::1]")) {
|
|
903
|
+
return parsed.toString();
|
|
904
|
+
}
|
|
905
|
+
return void 0;
|
|
906
|
+
}
|
|
875
907
|
|
|
876
908
|
// src/widget/ReportDetailView.tsx
|
|
877
909
|
import { Fragment, jsx as jsx2, jsxs as jsxs2 } from "preact/jsx-runtime";
|
|
@@ -980,16 +1012,19 @@ function ReportDetailView({
|
|
|
980
1012
|
/* @__PURE__ */ jsxs2("div", { class: "report-detail-body", children: [
|
|
981
1013
|
/* @__PURE__ */ jsx2(ContextBlock, { detail, strings }),
|
|
982
1014
|
/* @__PURE__ */ jsx2("p", { class: "report-detail-description", children: detail.description }),
|
|
983
|
-
detail.screenshot_url &&
|
|
984
|
-
|
|
985
|
-
|
|
986
|
-
|
|
987
|
-
|
|
988
|
-
|
|
989
|
-
|
|
990
|
-
|
|
991
|
-
|
|
992
|
-
|
|
1015
|
+
detail.screenshot_url && (() => {
|
|
1016
|
+
const safeHref = safeExternalHref(detail.screenshot_url);
|
|
1017
|
+
return safeHref ? /* @__PURE__ */ jsx2(
|
|
1018
|
+
"a",
|
|
1019
|
+
{
|
|
1020
|
+
class: "report-detail-screenshot",
|
|
1021
|
+
href: safeHref,
|
|
1022
|
+
target: "_blank",
|
|
1023
|
+
rel: "noopener noreferrer",
|
|
1024
|
+
children: /* @__PURE__ */ jsx2("img", { src: detail.screenshot_url, alt: "", loading: "lazy" })
|
|
1025
|
+
}
|
|
1026
|
+
) : /* @__PURE__ */ jsx2("div", { class: "report-detail-screenshot", children: /* @__PURE__ */ jsx2("img", { src: detail.screenshot_url, alt: "", loading: "lazy" }) });
|
|
1027
|
+
})(),
|
|
993
1028
|
/* @__PURE__ */ jsx2("h3", { class: "report-detail-section", children: strings["detail.thread"] }),
|
|
994
1029
|
detail.comments.length === 0 ? /* @__PURE__ */ jsx2("p", { class: "report-detail-empty", children: strings["detail.no_replies"] }) : /* @__PURE__ */ jsx2("ul", { class: "report-comments", children: detail.comments.map((c) => /* @__PURE__ */ jsx2("li", { children: /* @__PURE__ */ jsx2(CommentBubble, { comment: c, strings }) })) }),
|
|
995
1030
|
detail.status_history && detail.status_history.length > 0 && /* @__PURE__ */ jsx2(StatusHistorySection, { rows: detail.status_history, strings }),
|
|
@@ -1048,19 +1083,22 @@ function ContextBlock({ detail, strings }) {
|
|
|
1048
1083
|
/* @__PURE__ */ jsx2("span", { class: "report-detail-context-label", children: strings["detail.context.submitted_at"] }),
|
|
1049
1084
|
/* @__PURE__ */ jsx2("span", { children: formatSubmittedAt(detail.created_at) })
|
|
1050
1085
|
] }),
|
|
1051
|
-
detail.page_url &&
|
|
1052
|
-
|
|
1053
|
-
/* @__PURE__ */
|
|
1054
|
-
"
|
|
1055
|
-
|
|
1056
|
-
|
|
1057
|
-
|
|
1058
|
-
|
|
1059
|
-
|
|
1060
|
-
|
|
1061
|
-
|
|
1062
|
-
|
|
1063
|
-
|
|
1086
|
+
detail.page_url && (() => {
|
|
1087
|
+
const safeHref = safeExternalHref(detail.page_url);
|
|
1088
|
+
return /* @__PURE__ */ jsxs2("div", { class: "report-detail-context-line", title: detail.page_url, children: [
|
|
1089
|
+
/* @__PURE__ */ jsx2("span", { class: "report-detail-context-label", children: strings["detail.context.page"] }),
|
|
1090
|
+
safeHref ? /* @__PURE__ */ jsx2(
|
|
1091
|
+
"a",
|
|
1092
|
+
{
|
|
1093
|
+
class: "report-detail-context-url",
|
|
1094
|
+
href: safeHref,
|
|
1095
|
+
target: "_blank",
|
|
1096
|
+
rel: "noopener noreferrer",
|
|
1097
|
+
children: truncateUrl(detail.page_url, 64)
|
|
1098
|
+
}
|
|
1099
|
+
) : /* @__PURE__ */ jsx2("span", { class: "report-detail-context-url", children: truncateUrl(detail.page_url, 64) })
|
|
1100
|
+
] });
|
|
1101
|
+
})()
|
|
1064
1102
|
] });
|
|
1065
1103
|
}
|
|
1066
1104
|
function formatSubmittedAt(iso) {
|
|
@@ -4583,7 +4621,10 @@ function createFeedback(config) {
|
|
|
4583
4621
|
async function buildAndSubmit(values) {
|
|
4584
4622
|
const manualScreenshot = values.synthetic ? void 0 : values.screenshot;
|
|
4585
4623
|
const technical_context = capture.snapshot();
|
|
4586
|
-
if (user)
|
|
4624
|
+
if (user) {
|
|
4625
|
+
const { userHash: _hash, exp: _exp, ...safeUser } = user;
|
|
4626
|
+
technical_context.user = safeUser;
|
|
4627
|
+
}
|
|
4587
4628
|
if (metadata && Object.keys(metadata).length > 0) {
|
|
4588
4629
|
technical_context.metadata = { ...metadata };
|
|
4589
4630
|
}
|
|
@@ -4598,8 +4639,8 @@ function createFeedback(config) {
|
|
|
4598
4639
|
capture_method: captureMethod,
|
|
4599
4640
|
technical_context
|
|
4600
4641
|
};
|
|
4601
|
-
if ("0.
|
|
4602
|
-
payload.widget_version = "0.
|
|
4642
|
+
if ("0.15.0") {
|
|
4643
|
+
payload.widget_version = "0.15.0";
|
|
4603
4644
|
}
|
|
4604
4645
|
if (manualScreenshot) payload.screenshot = manualScreenshot;
|
|
4605
4646
|
if (values.synthetic) payload.synthetic = true;
|
|
@@ -4685,4 +4726,4 @@ function createFeedback(config) {
|
|
|
4685
4726
|
export {
|
|
4686
4727
|
createFeedback
|
|
4687
4728
|
};
|
|
4688
|
-
//# sourceMappingURL=chunk-
|
|
4729
|
+
//# sourceMappingURL=chunk-67JM6XVT.mjs.map
|