@sailfish-ai/recorder 1.10.13 → 1.11.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.
Files changed (100) hide show
  1. package/README.md +309 -7
  2. package/dist/babel-plugin-sailfish-source.cjs.br +0 -0
  3. package/dist/babel-plugin-sailfish-source.cjs.gz +0 -0
  4. package/dist/babel-plugin-sailfish-source.js.br +0 -0
  5. package/dist/babel-plugin-sailfish-source.js.gz +0 -0
  6. package/dist/chunkSerializer.js.br +0 -0
  7. package/dist/chunkSerializer.js.gz +0 -0
  8. package/dist/chunks/{chunkSerializer-Dk1eF3S8.js → chunkSerializer-BiemuRlf.js} +1 -1
  9. package/dist/chunks/chunkSerializer-BiemuRlf.js.br +0 -0
  10. package/dist/chunks/chunkSerializer-BiemuRlf.js.gz +0 -0
  11. package/dist/chunks/{chunkSerializer-CodMnuS3.js → chunkSerializer-CJQCxiLD.js} +1 -1
  12. package/dist/chunks/chunkSerializer-CJQCxiLD.js.br +0 -0
  13. package/dist/chunks/chunkSerializer-CJQCxiLD.js.gz +0 -0
  14. package/dist/chunks/{index-DW416eVj.js → index-Cfj4Epfd.js} +126 -96
  15. package/dist/chunks/index-Cfj4Epfd.js.br +0 -0
  16. package/dist/chunks/index-Cfj4Epfd.js.gz +0 -0
  17. package/dist/chunks/{index-DvLh2k6O.js → index-CuXHImrI.js} +126 -94
  18. package/dist/chunks/index-CuXHImrI.js.br +0 -0
  19. package/dist/chunks/index-CuXHImrI.js.gz +0 -0
  20. package/dist/constants.js.br +0 -0
  21. package/dist/constants.js.gz +0 -0
  22. package/dist/deviceInfo.js.br +0 -0
  23. package/dist/deviceInfo.js.gz +0 -0
  24. package/dist/env.js.br +0 -0
  25. package/dist/env.js.gz +0 -0
  26. package/dist/errorInterceptor.js.br +0 -0
  27. package/dist/errorInterceptor.js.gz +0 -0
  28. package/dist/eventStore.js.br +0 -0
  29. package/dist/eventStore.js.gz +0 -0
  30. package/dist/exponentialBackoff.js.br +0 -0
  31. package/dist/exponentialBackoff.js.gz +0 -0
  32. package/dist/fiberHook.js.br +0 -0
  33. package/dist/fiberHook.js.gz +0 -0
  34. package/dist/frameworkDetection.js.br +0 -0
  35. package/dist/frameworkDetection.js.gz +0 -0
  36. package/dist/graphql.js.br +0 -0
  37. package/dist/graphql.js.gz +0 -0
  38. package/dist/headlessDetection.js.br +0 -0
  39. package/dist/headlessDetection.js.gz +0 -0
  40. package/dist/inAppReportIssueModal/index.js +15 -14
  41. package/dist/inAppReportIssueModal/index.js.br +0 -0
  42. package/dist/inAppReportIssueModal/index.js.gz +0 -0
  43. package/dist/inAppReportIssueModal/integrations.js +56 -4
  44. package/dist/inAppReportIssueModal/integrations.js.br +0 -0
  45. package/dist/inAppReportIssueModal/integrations.js.gz +0 -0
  46. package/dist/inAppReportIssueModal/state.js.br +0 -0
  47. package/dist/inAppReportIssueModal/state.js.gz +0 -0
  48. package/dist/inAppReportIssueModal/ui.js.br +0 -0
  49. package/dist/inAppReportIssueModal/ui.js.gz +0 -0
  50. package/dist/index.js +98 -73
  51. package/dist/index.js.br +0 -0
  52. package/dist/index.js.gz +0 -0
  53. package/dist/notifyEventStore.js.br +0 -0
  54. package/dist/notifyEventStore.js.gz +0 -0
  55. package/dist/recorder.cjs +2 -2
  56. package/dist/recorder.cjs.br +0 -0
  57. package/dist/recorder.cjs.gz +0 -0
  58. package/dist/recorder.js +26 -25
  59. package/dist/recorder.js.br +0 -0
  60. package/dist/recorder.js.gz +0 -0
  61. package/dist/recorder.umd.cjs +8909 -0
  62. package/dist/recorder.umd.cjs.br +0 -0
  63. package/dist/recorder.umd.cjs.gz +0 -0
  64. package/dist/recording.js +2 -2
  65. package/dist/recording.js.br +0 -0
  66. package/dist/recording.js.gz +0 -0
  67. package/dist/segmentHelpers.js.br +0 -0
  68. package/dist/segmentHelpers.js.gz +0 -0
  69. package/dist/sendSailfishMessages.js +4 -0
  70. package/dist/sendSailfishMessages.js.br +0 -0
  71. package/dist/sendSailfishMessages.js.gz +0 -0
  72. package/dist/session.js.br +0 -0
  73. package/dist/session.js.gz +0 -0
  74. package/dist/snippet-auto-init.js +173 -0
  75. package/dist/snippet-auto-init.js.br +0 -0
  76. package/dist/snippet-auto-init.js.gz +0 -0
  77. package/dist/sourceLocation.js.br +0 -0
  78. package/dist/sourceLocation.js.gz +0 -0
  79. package/dist/types/inAppReportIssueModal/integrations.d.ts +7 -0
  80. package/dist/types/index.d.ts +5 -1
  81. package/dist/types/sendSailfishMessages.d.ts +4 -0
  82. package/dist/types/snippet-auto-init.d.ts +31 -0
  83. package/dist/types/types.d.ts +1 -0
  84. package/dist/types/umd-entry.d.ts +9 -0
  85. package/dist/umd-entry.js +11 -0
  86. package/dist/utils.js.br +0 -0
  87. package/dist/utils.js.gz +0 -0
  88. package/dist/uuid.js.br +0 -0
  89. package/dist/uuid.js.gz +0 -0
  90. package/dist/websocket.js.br +0 -0
  91. package/dist/websocket.js.gz +0 -0
  92. package/package.json +9 -5
  93. package/dist/chunks/chunkSerializer-CodMnuS3.js.br +0 -0
  94. package/dist/chunks/chunkSerializer-CodMnuS3.js.gz +0 -0
  95. package/dist/chunks/chunkSerializer-Dk1eF3S8.js.br +0 -0
  96. package/dist/chunks/chunkSerializer-Dk1eF3S8.js.gz +0 -0
  97. package/dist/chunks/index-DW416eVj.js.br +0 -0
  98. package/dist/chunks/index-DW416eVj.js.gz +0 -0
  99. package/dist/chunks/index-DvLh2k6O.js.br +0 -0
  100. package/dist/chunks/index-DvLh2k6O.js.gz +0 -0
@@ -370,7 +370,7 @@ function initializeWebSocket(t2, n2, i2, o2, s2 = false) {
370
370
  const t3 = new URL(e2);
371
371
  return `${t3.hostname}${t3.port ? `:${t3.port}` : ""}`;
372
372
  })(t2);
373
- let r2 = `${"https:" === new URL(t2).protocol ? "wss" : "ws"}://${a2}/ws/notify/?apiKey=${n2}&sessionId=${i2}&sender=JS%2FTS&version=1.10.13`;
373
+ let r2 = `${"https:" === new URL(t2).protocol ? "wss" : "ws"}://${a2}/ws/notify/?apiKey=${n2}&sessionId=${i2}&sender=JS%2FTS&version=1.11.1`;
374
374
  if (o2 && (r2 += `&envValue=${encodeURIComponent(o2)}`), k = s2 ? (function tryCreateWsWorker() {
375
375
  if ("undefined" == typeof Worker) return null;
376
376
  try {
@@ -426,37 +426,40 @@ function getFuncSpanHeader() {
426
426
  return { name: "X-Sf3-FunctionSpanCaptureOverride", value: "1-1-10-10-1-1.0-1-0-0" };
427
427
  }
428
428
  const O = Object.freeze(Object.defineProperty({ __proto__: null, clearStaleFuncSpanState, disableFunctionSpanTracking, enableFunctionSpanTracking, ensureHrefCache, flushBufferedEvents, getCachedHref, getCachedHrefNoQuery, getFuncSpanHeader, initializeFunctionSpanTrackingFromApi, initializeWebSocket, isFunctionSpanTrackingEnabled, onNavigationChange, restoreFuncSpanState, sendEvent, sendMessage }, Symbol.toStringTag, { value: "Module" }));
429
- let z = null, U = null;
429
+ let U = null, z = null;
430
+ function getIdentifiedUser() {
431
+ return U;
432
+ }
430
433
  function identify(e2, t2 = {}, n2 = false) {
431
434
  const i2 = { type: "identify", userId: e2, traits: t2 };
432
- z && z.userId === e2 && JSON.stringify(z.traits) === JSON.stringify(t2) || (z = { userId: e2, traits: t2, overwrite: n2 }, sendMessage(i2));
435
+ U && U.userId === e2 && JSON.stringify(U.traits) === JSON.stringify(t2) || (U = { userId: e2, traits: t2, overwrite: n2 }, sendMessage(i2));
433
436
  }
434
437
  function addOrUpdateMetadata(e2) {
435
438
  const t2 = { type: "addOrUpdateMetadata", metadata: e2 };
436
- U && JSON.stringify(U) === JSON.stringify(e2) || (U = e2, sendMessage(t2));
439
+ z && JSON.stringify(z) === JSON.stringify(e2) || (z = e2, sendMessage(t2));
437
440
  }
438
441
  function trackingEvent(e2) {
439
442
  sendMessage({ type: "trackingEvent", trackingData: e2, timestamp: w() });
440
443
  }
441
- let H = null;
442
- const q = ["https://api.ipify.org?format=json", "https://api.ip.sb/jsonip", "https://api4.my-ip.io/ip.json"];
444
+ let N = null;
445
+ const H = ["https://api.ipify.org?format=json", "https://api.ip.sb/jsonip", "https://api4.my-ip.io/ip.json"];
443
446
  function fetchAndSendIp(e2) {
444
- H !== e2 && (H = e2, (async () => {
445
- for (const e3 of q) try {
447
+ N !== e2 && (N = e2, (async () => {
448
+ for (const e3 of H) try {
446
449
  const t2 = new AbortController(), n2 = setTimeout(() => t2.abort(), 5e3), i2 = await fetch(e3, { signal: t2.signal });
447
450
  if (clearTimeout(n2), !i2.ok) continue;
448
451
  const o2 = await i2.json(), s2 = o2.ip || o2.origin || null;
449
452
  if (s2 && "string" == typeof s2 && s2.length <= 45) return void sendMessage({ type: "visitorIp", ip: s2, timestamp: w() });
450
453
  } catch {
451
454
  }
452
- H = null;
455
+ N = null;
453
456
  })().catch(() => {
454
- H = null;
457
+ N = null;
455
458
  }));
456
459
  }
457
- let N = null;
460
+ let q = null;
458
461
  async function getSourceMapModule() {
459
- return N || (N = await import("source-map-js")), N;
462
+ return q || (q = await import("source-map-js")), q;
460
463
  }
461
464
  const W = /* @__PURE__ */ new Map(), K = /(?:\(|\s|^)(https?:\/\/[^)\s]+|\/[^)\s]+|[^)\s]+)?\/?([^/]+\.js)(?:\?[^:)]*)?:(\d+):(\d+)/;
462
465
  async function getConsumerFor(e2, t2) {
@@ -701,12 +704,12 @@ async function initializeRecording(e2, n2, i2, o2, s2, a2 = true, r2 = false, l2
701
704
  }
702
705
  const { record: n4 } = await import("@sailfish-rrweb/rrweb-record-only");
703
706
  if (J = n4, await yieldToMain(), l2) {
704
- const { chunkedSnapshot: i3 } = await import("./chunkSerializer-Dk1eF3S8.js"), o3 = n4.mirror;
707
+ const { chunkedSnapshot: i3 } = await import("./chunkSerializer-BiemuRlf.js"), o3 = n4.mirror;
705
708
  let s3 = true;
706
709
  const a3 = [];
707
710
  n4({ emit(e3) {
708
711
  s3 ? a3.push(e3) : emitWithContext(e3);
709
- }, maskInputOptions: { text: true }, maskInputFn, maskTextClass: X, ...e2, recordDOM: false });
712
+ }, maskInputOptions: { text: true }, maskInputFn, ...e2, maskTextClass: e2.maskTextClass ?? X, recordDOM: false });
710
713
  const r3 = Date.now(), l3 = await i3(document, o3, { chunkSize: 500, maxChunkMs: 16, blockClass: e2.blockClass, blockSelector: e2.blockSelector, maskTextClass: e2.maskTextClass ?? X, maskTextSelector: e2.maskTextSelector });
711
714
  if (l3) {
712
715
  emitWithContext({ type: t.Meta, data: { href: window.location.href, width: document.documentElement.clientWidth || document.body.clientWidth, height: document.documentElement.clientHeight || document.body.clientHeight }, timestamp: r3 }), emitWithContext({ type: t.FullSnapshot, data: { node: l3, initialOffset: { left: void 0 !== window.pageXOffset ? window.pageXOffset : document.documentElement.scrollLeft, top: void 0 !== window.pageYOffset ? window.pageYOffset : document.documentElement.scrollTop } }, timestamp: r3 });
@@ -715,7 +718,7 @@ async function initializeRecording(e2, n2, i2, o2, s2, a2 = true, r2 = false, l2
715
718
  } else console.warn("[Sailfish] chunkSnapshot serialization failed; session continues without initial DOM snapshot"), s3 = false;
716
719
  } else n4({ emit(e3) {
717
720
  emitWithContext(e3);
718
- }, maskInputOptions: { text: true }, maskInputFn, maskTextClass: X, ...e2 });
721
+ }, maskInputOptions: { text: true }, maskInputFn, ...e2, maskTextClass: e2.maskTextClass ?? X });
719
722
  };
720
723
  if (a2) {
721
724
  let e3 = false;
@@ -930,12 +933,26 @@ function updateIssueTypeOptions(e2, t2) {
930
933
  }
931
934
  function getFieldsForProject(e2, t2) {
932
935
  if (!(re == null ? void 0 : re.fieldConfigurations) || !e2) return [];
933
- const n2 = Array.isArray(re.fieldConfigurations) ? re.fieldConfigurations.find((n3) => n3.project_key === e2 && (!t2 || n3.issue_type_id === t2)) : re.fieldConfigurations[e2];
936
+ const n2 = Array.isArray(re.fieldConfigurations) ? re.fieldConfigurations.find((n3) => !(n3.project_key !== e2 && String(n3.project_id) !== String(e2) || t2 && String(n3.issue_type_id) !== String(t2))) : re.fieldConfigurations[e2];
934
937
  return n2 && n2.fields ? n2.fields : [];
935
938
  }
936
939
  function getUsers() {
937
940
  return (re == null ? void 0 : re.users) ? re.users : [];
938
941
  }
942
+ function getDefaultReporterAccountId() {
943
+ const e2 = getUsers(), t2 = getIdentifiedUser();
944
+ if (!e2.length || !t2) return null;
945
+ const n2 = t2.traits || {}, i2 = (n2.email || t2.userId || "").toLowerCase().trim(), o2 = (n2.name || n2.displayName || n2.fullName || n2.full_name || (n2.firstName || n2.first_name ? `${n2.firstName || n2.first_name} ${n2.lastName || n2.last_name || ""}`.trim() : "") || "").toLowerCase().trim(), findUnique = (t3) => {
946
+ const n3 = e2.filter(t3);
947
+ return 1 === n3.length ? n3[0] : null;
948
+ };
949
+ let s2 = i2 ? findUnique((e3) => (e3.email || e3.emailAddress || "").toLowerCase().trim() === i2) : null;
950
+ if (!s2 && o2 && (s2 = findUnique((e3) => (e3.name || e3.displayName || "").toLowerCase().trim() === o2)), !s2 && i2) {
951
+ const e3 = i2.split("@")[0];
952
+ e3.length >= 3 && (s2 = findUnique((t3) => (t3.name || t3.displayName || "").toLowerCase().trim().includes(e3)));
953
+ }
954
+ return s2 && (s2.id || s2.accountId) || null;
955
+ }
939
956
  function getProjectsForTeam(e2) {
940
957
  if (!re) return [];
941
958
  const t2 = re.teams && Array.isArray(re.teams) && re.teams.length > 0;
@@ -968,7 +985,7 @@ const ce = Object.freeze(Object.defineProperty({ __proto__: null, fetchIntegrati
968
985
  } catch (e3) {
969
986
  console.error("Error fetching integration data:", e3), re = null;
970
987
  }
971
- }, getFieldsForProject, getIntegrationData, getProjectsForTeam, getSprintFieldId, getUsers, hasValidIntegration, populatePriorityOptions, populateSelectOptions, populateSprintOptions, refreshIntegrationData, updateFormWithIntegrationData, updateIssueTypeOptions }, Symbol.toStringTag, { value: "Module" })), de = "sf-create-issue-preference", ue = "sf-create-eng-ticket-preference";
988
+ }, getDefaultReporterAccountId, getFieldsForProject, getIntegrationData, getProjectsForTeam, getSprintFieldId, getUsers, hasValidIntegration, populatePriorityOptions, populateSelectOptions, populateSprintOptions, refreshIntegrationData, updateFormWithIntegrationData, updateIssueTypeOptions }, Symbol.toStringTag, { value: "Module" })), de = "sf-create-issue-preference", ue = "sf-create-eng-ticket-preference";
972
989
  function getInitialState() {
973
990
  const e2 = (function loadUserPreferences() {
974
991
  return { createIssue: f && "true" === localStorage.getItem(de), createEngTicket: f && "true" === localStorage.getItem(ue) };
@@ -1558,8 +1575,11 @@ function injectModalHTML(e2 = "lookback") {
1558
1575
  if (!hasValidIntegration()) return l2.checked = false, pe.createEngTicket = false, localStorage.setItem(ue, "false"), c2 && (c2.style.display = "none"), void alert("No engineering ticket integration found. Please install and configure an integration (Jira, Linear, or Zendesk) first.");
1559
1576
  const e5 = getIntegrationData();
1560
1577
  if (e5) {
1561
- if (!pe.engTicketTeam && e5.defaultTeam && (pe.engTicketTeam = e5.defaultTeam), !pe.engTicketProject && e5.defaultProject && (pe.engTicketProject = e5.defaultProject), !pe.engTicketPriority && e5.defaultPriority && (pe.engTicketPriority = e5.defaultPriority), updateFormWithIntegrationData(pe), "jira" === ((_a = e5.provider) == null ? void 0 : _a.toLowerCase()) && e5.jiraReporterAccountId && pe.engTicketProject) {
1562
- getFieldsForProject(pe.engTicketProject, pe.engTicketIssueType).find((e6) => "reporter" === e6.fieldId) && !pe.engTicketCustomFields.reporter && (pe.engTicketCustomFields.reporter = e5.jiraReporterAccountId);
1578
+ if (!pe.engTicketTeam && e5.defaultTeam && (pe.engTicketTeam = e5.defaultTeam), !pe.engTicketProject && e5.defaultProject && (pe.engTicketProject = e5.defaultProject), !pe.engTicketPriority && e5.defaultPriority && (pe.engTicketPriority = e5.defaultPriority), updateFormWithIntegrationData(pe), "jira" === ((_a = e5.provider) == null ? void 0 : _a.toLowerCase()) && pe.engTicketProject && !pe.engTicketCustomFields.reporter) {
1579
+ if (getFieldsForProject(pe.engTicketProject, pe.engTicketIssueType).find((e6) => "reporter" === e6.fieldId)) {
1580
+ const t5 = getDefaultReporterAccountId();
1581
+ pe.engTicketCustomFields.reporter = t5 || e5.jiraReporterAccountId || "";
1582
+ }
1563
1583
  }
1564
1584
  const t4 = document.getElementById("sf-eng-ticket-project"), n3 = document.getElementById("sf-eng-ticket-type");
1565
1585
  t4 && t4.value && renderDynamicFields(t4.value, n3 == null ? void 0 : n3.value);
@@ -1693,8 +1713,11 @@ function initializeEngTicketForm() {
1693
1713
  var _a;
1694
1714
  const e2 = be.integrationData;
1695
1715
  if (e2) {
1696
- if (!pe.engTicketTeam && e2.defaultTeam && (pe.engTicketTeam = e2.defaultTeam), !pe.engTicketProject && e2.defaultProject && (pe.engTicketProject = e2.defaultProject), !pe.engTicketPriority && e2.defaultPriority && (pe.engTicketPriority = e2.defaultPriority), updateFormWithIntegrationData(pe), "jira" === ((_a = e2.provider) == null ? void 0 : _a.toLowerCase()) && e2.jiraReporterAccountId && pe.engTicketProject) {
1697
- getFieldsForProject(pe.engTicketProject, pe.engTicketIssueType).find((e3) => "reporter" === e3.fieldId) && !pe.engTicketCustomFields.reporter && (pe.engTicketCustomFields.reporter = e2.jiraReporterAccountId);
1716
+ if (!pe.engTicketTeam && e2.defaultTeam && (pe.engTicketTeam = e2.defaultTeam), !pe.engTicketProject && e2.defaultProject && (pe.engTicketProject = e2.defaultProject), !pe.engTicketPriority && e2.defaultPriority && (pe.engTicketPriority = e2.defaultPriority), updateFormWithIntegrationData(pe), "jira" === ((_a = e2.provider) == null ? void 0 : _a.toLowerCase()) && pe.engTicketProject && !pe.engTicketCustomFields.reporter) {
1717
+ if (getFieldsForProject(pe.engTicketProject, pe.engTicketIssueType).find((e3) => "reporter" === e3.fieldId)) {
1718
+ const t2 = getDefaultReporterAccountId();
1719
+ pe.engTicketCustomFields.reporter = t2 || e2.jiraReporterAccountId || "";
1720
+ }
1698
1721
  }
1699
1722
  pe.engTicketProject && renderDynamicFields(pe.engTicketProject, pe.engTicketIssueType);
1700
1723
  }
@@ -1732,8 +1755,11 @@ function bindEngTicketListeners() {
1732
1755
  var _a;
1733
1756
  pe.engTicketProject = t2.value, t2.style.color = t2.value ? "" : "#9ca3af", pe.engTicketCustomFields = {};
1734
1757
  const e3 = getIntegrationData();
1735
- if (e3 && o2 && (updateIssueTypeOptions(o2, t2.value), pe.engTicketIssueType = o2.value), e3 && "jira" === ((_a = e3.provider) == null ? void 0 : _a.toLowerCase()) && e3.jiraReporterAccountId && t2.value) {
1736
- getFieldsForProject(t2.value, pe.engTicketIssueType).find((e4) => "reporter" === e4.fieldId) && (pe.engTicketCustomFields.reporter = e3.jiraReporterAccountId);
1758
+ if (e3 && o2 && (updateIssueTypeOptions(o2, t2.value), pe.engTicketIssueType = o2.value), e3 && "jira" === ((_a = e3.provider) == null ? void 0 : _a.toLowerCase()) && t2.value) {
1759
+ if (getFieldsForProject(t2.value, pe.engTicketIssueType).find((e4) => "reporter" === e4.fieldId)) {
1760
+ const t3 = getDefaultReporterAccountId();
1761
+ pe.engTicketCustomFields.reporter = t3 || e3.jiraReporterAccountId || "";
1762
+ }
1737
1763
  }
1738
1764
  renderDynamicFields(t2.value, pe.engTicketIssueType);
1739
1765
  }), s2 && s2.addEventListener("change", () => {
@@ -1985,39 +2011,40 @@ function _ensureModuleSideEffects() {
1985
2011
  clearPageVisitDataFromSessionStorage();
1986
2012
  }));
1987
2013
  }
1988
- function matchUrlWithWildcard(e2, t2) {
1989
- let n2, i2;
1990
- if ("string" == typeof e2 ? n2 = e2 : "undefined" != typeof URL && e2 instanceof URL ? n2 = e2.href : "undefined" != typeof Request && e2 instanceof Request ? n2 = e2.url : null != e2 && "function" == typeof e2.toString && (n2 = e2.toString()), !n2) return false;
1991
- try {
1992
- const e3 = "undefined" != typeof window ? window.location.href : "http://localhost/";
1993
- i2 = new URL(n2, e3);
1994
- } catch {
1995
- return false;
1996
- }
1997
- const { hostname: o2, pathname: s2, port: a2, protocol: r2 } = i2;
1998
- if (!/^https?:$/.test(r2)) return false;
1999
- const l2 = o2.startsWith("www.") ? o2.slice(4).toLowerCase() : o2.toLowerCase();
2014
+ function matchParsedUrlAgainstPatterns(e2, t2) {
2015
+ const { hostname: n2, pathname: i2, port: o2 } = e2, s2 = n2.startsWith("www.") ? n2.slice(4).toLowerCase() : n2.toLowerCase();
2000
2016
  return t2.some((e3) => {
2001
2017
  const t3 = String(e3 || "").replace(/^[a-zA-Z]+:\/\//, "");
2002
- let [n3, i3] = t3.split("/", 2), o3 = "";
2003
- n3.includes(":") && ([n3, o3] = n3.split(":"));
2004
- const r3 = getCachedRegex(`^${n3.replace(/\./g, "\\.").replace(/\*/g, ".*")}$`, "i"), c2 = l2.startsWith("www.") ? l2.slice(4) : l2;
2005
- if (o3 && "*" !== o3 && a2 !== o3) return false;
2018
+ let [n3, a2] = t3.split("/", 2), r2 = "";
2019
+ n3.includes(":") && ([n3, r2] = n3.split(":"));
2020
+ const l2 = getCachedRegex(`^${n3.replace(/\./g, "\\.").replace(/\*/g, ".*")}$`, "i"), c2 = s2.startsWith("www.") ? s2.slice(4) : s2;
2021
+ if (r2 && "*" !== r2 && o2 !== r2) return false;
2006
2022
  if (n3.startsWith("*.")) {
2007
2023
  const e4 = n3.slice(2).toLowerCase();
2008
- if (!(l2 === e4 || c2 === e4 || l2.endsWith("." + e4))) return false;
2009
- if (i3) {
2010
- return getCachedRegex(`^/${i3.replace(/\*/g, ".*").replace(/\/$/, "")}`, "i").test(s2);
2024
+ if (!(s2 === e4 || c2 === e4 || s2.endsWith("." + e4))) return false;
2025
+ if (a2) {
2026
+ return getCachedRegex(`^/${a2.replace(/\*/g, ".*").replace(/\/$/, "")}`, "i").test(i2);
2011
2027
  }
2012
2028
  return true;
2013
2029
  }
2014
- if (!r3.test(c2) && !r3.test(l2)) return false;
2015
- if (i3) {
2016
- return getCachedRegex(`^/${i3.replace(/\*/g, ".*").replace(/\/$/, "")}`, "i").test(s2);
2030
+ if (!l2.test(c2) && !l2.test(s2)) return false;
2031
+ if (a2) {
2032
+ return getCachedRegex(`^/${a2.replace(/\*/g, ".*").replace(/\/$/, "")}`, "i").test(i2);
2017
2033
  }
2018
2034
  return true;
2019
2035
  });
2020
2036
  }
2037
+ function matchUrlWithWildcard(e2, t2) {
2038
+ let n2, i2;
2039
+ if ("string" == typeof e2 ? n2 = e2 : "undefined" != typeof URL && e2 instanceof URL ? n2 = e2.href : "undefined" != typeof Request && e2 instanceof Request ? n2 = e2.url : null != e2 && "function" == typeof e2.toString && (n2 = e2.toString()), !n2) return false;
2040
+ try {
2041
+ const e3 = "undefined" != typeof window ? window.location.href : "http://localhost/";
2042
+ i2 = new URL(n2, e3);
2043
+ } catch {
2044
+ return false;
2045
+ }
2046
+ return matchParsedUrlAgainstPatterns(i2, t2);
2047
+ }
2021
2048
  function createSkipHeadersPropagationChecker(e2 = [], t2 = []) {
2022
2049
  const n2 = [...Te, ...e2], i2 = t2.length > 0;
2023
2050
  return function shouldSkipHeadersPropagation(e3) {
@@ -2028,7 +2055,7 @@ function createSkipHeadersPropagationChecker(e2 = [], t2 = []) {
2028
2055
  return true;
2029
2056
  }
2030
2057
  const s2 = o2.pathname.toLowerCase(), a2 = s2.lastIndexOf(".");
2031
- return !(-1 === a2 || !Ie.has(s2.slice(a2))) || (!(!i2 || matchUrlWithWildcard(e3, t2)) || !!matchUrlWithWildcard(e3, n2));
2058
+ return !(-1 === a2 || !Ie.has(s2.slice(a2))) || (!(!i2 || matchParsedUrlAgainstPatterns(o2, t2)) || !!matchParsedUrlAgainstPatterns(o2, n2));
2032
2059
  };
2033
2060
  }
2034
2061
  function setupFetchInterceptor(e2 = [], t2 = { captureStreamingResponseBody: true, captureResponseBodyMaxMb: 10, captureStreamPrefixKb: 64, captureStreamTimeoutMs: 1e4 }, i2 = []) {
@@ -2201,7 +2228,7 @@ function setupFetchInterceptor(e2 = [], t2 = { captureStreamingResponseBody: tru
2201
2228
  })(e3, i3, o3, d2, u2, s2, c2);
2202
2229
  } });
2203
2230
  }
2204
- async function startRecording({ apiKey: e2, backendApi: t2 = "https://api-service.sailfishqa.com", domainsToPropagateHeaderTo: i2 = [], domainsToNotPropagateHeaderTo: o2 = [], serviceVersion: s2, serviceIdentifier: a2, gitSha: r2, serviceAdditionalMetadata: l2, enableIpTracking: c2, captureStreamingResponseBody: d2 = true, captureResponseBodyMaxMb: u2 = 10, captureStreamPrefixKb: p2 = 64, captureStreamTimeoutMs: f2 = 1e4, enableFiberTracking: m2 = false, deferRecording: h2, deferRecordingStart: y2, chunkSnapshot: b2, useWsWorker: w2 = true }) {
2231
+ async function startRecording({ apiKey: e2, backendApi: t2 = "https://api-service.sailfishqa.com", domainsToPropagateHeaderTo: i2 = ["*"], domainsToNotPropagateHeaderTo: o2 = [], serviceVersion: s2, serviceIdentifier: a2, gitSha: r2, serviceAdditionalMetadata: l2, enableIpTracking: c2, captureStreamingResponseBody: d2 = true, captureResponseBodyMaxMb: u2 = 10, captureStreamPrefixKb: p2 = 64, captureStreamTimeoutMs: f2 = 1e4, enableFiberTracking: m2 = false, deferRecording: h2, deferRecordingStart: y2, chunkSnapshot: b2, useWsWorker: w2 = true, maskTextClass: v2, library: S2 }) {
2205
2232
  var _a, _b;
2206
2233
  if ((function isHeadlessOrLighthouse() {
2207
2234
  try {
@@ -2214,10 +2241,10 @@ async function startRecording({ apiKey: e2, backendApi: t2 = "https://api-servic
2214
2241
  return false;
2215
2242
  }
2216
2243
  })()) return;
2217
- const v2 = h2 ?? y2 ?? true, S2 = getOrSetSessionId(), k2 = window.__sailfish_recorder || (window.__sailfish_recorder = {});
2218
- if (k2.sessionId = S2, k2.apiKey = e2, k2.backendApi = t2, k2.serviceAdditionalMetadata = l2, k2.initialized && k2.sessionId === S2 && k2.ws && 1 === k2.ws.readyState) return void trackDomainChangesOnce();
2219
- const x2 = { captureStreamingResponseBody: d2, captureResponseBodyMaxMb: u2, captureStreamPrefixKb: p2, captureStreamTimeoutMs: f2 };
2220
- sessionStorage.getItem("pageVisitUUID") || (sessionStorage.setItem("pageVisitUUID", uuidv4()), invalidateUrlCache()), k2.xhrPatched || (!(function setupXMLHttpRequestInterceptor(e3 = [], t3 = { captureStreamingResponseBody: true, captureResponseBodyMaxMb: 10, captureStreamPrefixKb: 64, captureStreamTimeoutMs: 1e4 }, i3 = []) {
2244
+ const k2 = h2 ?? y2 ?? true, x2 = getOrSetSessionId(), I2 = window.__sailfish_recorder || (window.__sailfish_recorder = {});
2245
+ if (I2.sessionId = x2, I2.apiKey = e2, I2.backendApi = t2, I2.serviceAdditionalMetadata = l2, I2.initialized && I2.sessionId === x2 && I2.ws && 1 === I2.ws.readyState) return void trackDomainChangesOnce();
2246
+ const T2 = { captureStreamingResponseBody: d2, captureResponseBodyMaxMb: u2, captureStreamPrefixKb: p2, captureStreamTimeoutMs: f2 };
2247
+ sessionStorage.getItem("pageVisitUUID") || (sessionStorage.setItem("pageVisitUUID", uuidv4()), invalidateUrlCache()), I2.xhrPatched || (!(function setupXMLHttpRequestInterceptor(e3 = [], t3 = { captureStreamingResponseBody: true, captureResponseBodyMaxMb: 10, captureStreamPrefixKb: 64, captureStreamTimeoutMs: 1e4 }, i3 = []) {
2221
2248
  const o3 = XMLHttpRequest.prototype.open, s3 = XMLHttpRequest.prototype.send, a3 = XMLHttpRequest.prototype.setRequestHeader, r3 = getOrSetSessionId(), l3 = createSkipHeadersPropagationChecker(e3, i3);
2222
2249
  XMLHttpRequest.prototype.setRequestHeader = function(e4, t4) {
2223
2250
  return this._capturedRequestHeaders || (this._capturedRequestHeaders = {}), this._capturedRequestHeaders[e4] = t4, a3.call(this, e4, t4);
@@ -2282,22 +2309,22 @@ async function startRecording({ apiKey: e2, backendApi: t2 = "https://api-servic
2282
2309
  emitFinished(false, e5, t4);
2283
2310
  }, { once: true }), s3.apply(this, e4);
2284
2311
  };
2285
- })(o2, x2, i2), k2.xhrPatched = true), k2.fetchPatched || (setupFetchInterceptor(o2, x2, i2), k2.fetchPatched = true), await yieldToMain(), k2.domEventsInit || (initializeDomContentEvents(S2), k2.domEventsInit = true), await yieldToMain(), k2.consoleInit || (initializeConsolePlugin(Ae, S2), k2.consoleInit = true), await yieldToMain(), k2.errorInit || (!(function initializeErrorInterceptor() {
2312
+ })(o2, T2, i2), I2.xhrPatched = true), I2.fetchPatched || (setupFetchInterceptor(o2, T2, i2), I2.fetchPatched = true), await yieldToMain(), I2.domEventsInit || (initializeDomContentEvents(x2), I2.domEventsInit = true), await yieldToMain(), I2.consoleInit || (initializeConsolePlugin(Ae, x2), I2.consoleInit = true), await yieldToMain(), I2.errorInit || (!(function initializeErrorInterceptor() {
2286
2313
  window.addEventListener("error", (e3) => {
2287
2314
  captureError(e3.error || e3.message);
2288
2315
  }), window.addEventListener("unhandledrejection", (e3) => {
2289
2316
  captureError(e3.reason, true);
2290
2317
  });
2291
- })(), k2.errorInit = true), await yieldToMain(), _ensureModuleSideEffects(), (function storeCredentialsAndConnection({ apiKey: e3, backendApi: t3 }) {
2318
+ })(), I2.errorInit = true), await yieldToMain(), _ensureModuleSideEffects(), (function storeCredentialsAndConnection({ apiKey: e3, backendApi: t3 }) {
2292
2319
  g && (sessionStorage.setItem("sailfishApiKey", e3), sessionStorage.setItem("sailfishBackendApi", t3));
2293
- })({ apiKey: e2, backendApi: t2 }), !isFunctionSpanTrackingEnabled() || k2.ws && 1 === k2.ws.readyState || fetchFunctionSpanTrackingEnabled(e2, t2).then((e3) => {
2320
+ })({ apiKey: e2, backendApi: t2 }), !isFunctionSpanTrackingEnabled() || I2.ws && 1 === I2.ws.readyState || fetchFunctionSpanTrackingEnabled(e2, t2).then((e3) => {
2294
2321
  var _a2;
2295
2322
  ((_a2 = e3.data) == null ? void 0 : _a2.isFunctionSpanTrackingEnabledFromApiKey) ?? false ? ke && console.log("[Sailfish] Function span tracking state validated with backend: ACTIVE") : (clearStaleFuncSpanState(), ke && console.log("[Sailfish] Cleared stale function span tracking state - backend validation shows tracking is not active"));
2296
2323
  }).catch((e3) => {
2297
2324
  ke && console.warn("[Sailfish] Failed to validate function span tracking status with backend:", e3);
2298
- }), k2.sentDoNotPropagateOnce || (sendDomainsToNotPropagateHeaderTo(e2, [...o2, ...Te], t2).catch((e3) => console.error("Failed to send domains to not propagate header to:", e3)), k2.sentDoNotPropagateOnce = true), (async function gatherAndCacheDeviceInfo() {
2325
+ }), I2.sentDoNotPropagateOnce || (sendDomainsToNotPropagateHeaderTo(e2, [...o2, ...Te], t2).catch((e3) => console.error("Failed to send domains to not propagate header to:", e3)), I2.sentDoNotPropagateOnce = true), (async function gatherAndCacheDeviceInfo() {
2299
2326
  sendMessage({ type: "deviceInfo", data: { deviceInfo: { language: navigator.language, userAgent: navigator.userAgent } } });
2300
- })(), c2 && fetchAndSendIp(S2);
2327
+ })(), c2 && fetchAndSendIp(x2);
2301
2328
  try {
2302
2329
  const n2 = r2 ?? (function readGitSha() {
2303
2330
  var _a2;
@@ -2316,7 +2343,7 @@ async function startRecording({ apiKey: e2, backendApi: t2 = "https://api-servic
2316
2343
  if ("string" == typeof e3 && e3) return e3;
2317
2344
  } catch {
2318
2345
  }
2319
- })(), i3 = a2 ?? "", o3 = s2 ?? "", c3 = "JS/TS", d3 = (function getMapUuidFromWindow() {
2346
+ })(), i3 = a2 ?? "", o3 = s2 ?? "", c3 = S2 ?? "JS/TS", d3 = (function getMapUuidFromWindow() {
2320
2347
  try {
2321
2348
  const e3 = window;
2322
2349
  if (e3 && "string" == typeof e3.sfMapUuid && e3.sfMapUuid) return e3.sfMapUuid;
@@ -2336,15 +2363,15 @@ async function startRecording({ apiKey: e2, backendApi: t2 = "https://api-servic
2336
2363
  return { framework: i4[0] ?? null, additionalFrameworks: i4.slice(1), serviceRole: "frontend" };
2337
2364
  })(), f3 = { ...u3, serviceRole: p3.serviceRole, ...null !== p3.framework && { framework: p3.framework }, ...p3.additionalFrameworks.length > 0 && { additionalFrameworks: p3.additionalFrameworks } };
2338
2365
  await yieldToMain();
2339
- const [g2, h3] = await Promise.all([fetchCaptureSettings(e2, t2), startRecordingSession(e2, S2, t2, i3, o3, d3, n2, c3, f3)]), y3 = { ...Me, ...(_a = g2.data) == null ? void 0 : _a.captureSettingsFromApiKey, enableFiberTracking: m2 };
2340
- if (k2.ws && 1 === k2.ws.readyState) return;
2366
+ const [g2, h3] = await Promise.all([fetchCaptureSettings(e2, t2), startRecordingSession(e2, x2, t2, i3, o3, d3, n2, c3, f3)]), y3 = { ...Me, ...(_a = g2.data) == null ? void 0 : _a.captureSettingsFromApiKey, enableFiberTracking: m2, ...void 0 !== v2 ? { maskTextClass: v2 } : {} };
2367
+ if (I2.ws && 1 === I2.ws.readyState) return;
2341
2368
  if ((_b = h3.data) == null ? void 0 : _b.startRecordingSession) {
2342
2369
  const n3 = (l2 == null ? void 0 : l2.env) || (l2 == null ? void 0 : l2.environment);
2343
2370
  await yieldToMain();
2344
- const i4 = await initializeRecording(y3, t2, e2, S2, n3, v2, w2, b2 ?? false);
2345
- k2.ws = i4, k2.initialized = true, trackDomainChangesOnce(), k2.sentMapUuidOnce || (!(function sendMapUuidIfAvailable(e3 = "", t3 = "") {
2371
+ const i4 = await initializeRecording(y3, t2, e2, x2, n3, k2, w2, b2 ?? false);
2372
+ I2.ws = i4, I2.initialized = true, trackDomainChangesOnce(), I2.sentMapUuidOnce || (!(function sendMapUuidIfAvailable(e3 = "", t3 = "") {
2346
2373
  window.sfMapUuid && sendMessage({ type: "mapUuid", data: { mapUuid: window.sfMapUuid, serviceIdentifier: e3, serviceVersion: t3 } });
2347
- })(a2, s2), k2.sentMapUuidOnce = true);
2374
+ })(a2, s2), I2.sentMapUuidOnce = true);
2348
2375
  } else console.error("Failed to start recording session:", h3.errors || h3);
2349
2376
  } catch (e3) {
2350
2377
  console.error("Error starting recording:", e3);
@@ -2354,41 +2381,46 @@ const initRecorder = async (e2) => {
2354
2381
  if ("undefined" == typeof window) return;
2355
2382
  const t2 = window.__sailfish_recorder || (window.__sailfish_recorder = {}), n2 = getOrSetSessionId();
2356
2383
  return clearPageVisitDataFromSessionStorage(), t2.initialized && t2.sessionId === n2 && t2.ws && 1 === t2.ws.readyState ? void 0 : (t2.initPromise || (t2.initPromise = (async () => {
2357
- if (t2.hasLoggedInitOnce || (console.log("Initializing Sailfish Recorder (first run) …"), t2.hasLoggedInitOnce = true), await startRecording(e2), !t2.issueReportingInit) {
2358
- const n3 = e2.backendApi ?? "https://api-service.sailfishqa.com", [{ setupIssueReporting: i2 }, { fetchIntegrationData: o2, getIntegrationData: s2 }] = await Promise.all([Promise.resolve().then(() => Se), Promise.resolve().then(() => ce)]);
2359
- let a2 = null;
2360
- try {
2361
- await o2(e2.apiKey, n3), a2 = s2();
2362
- } catch (e3) {
2363
- console.warn("[Sailfish] Failed to fetch integration data for issue reporting:", e3);
2384
+ try {
2385
+ if (t2.hasLoggedInitOnce || (console.log("Initializing Sailfish Recorder (first run) …"), t2.hasLoggedInitOnce = true), await startRecording(e2), !t2.issueReportingInit) {
2386
+ const n3 = e2.backendApi ?? "https://api-service.sailfishqa.com", [{ setupIssueReporting: i2 }, { fetchIntegrationData: o2, getIntegrationData: s2 }] = await Promise.all([Promise.resolve().then(() => Se), Promise.resolve().then(() => ce)]);
2387
+ let a2 = null;
2388
+ try {
2389
+ await o2(e2.apiKey, n3), a2 = s2();
2390
+ } catch (e3) {
2391
+ console.warn("[Sailfish] Failed to fetch integration data for issue reporting:", e3);
2392
+ }
2393
+ i2({ apiKey: e2.apiKey, backendApi: n3, getSessionId: () => getOrSetSessionId(), shortcuts: e2.reportIssueShortcuts, customBaseUrl: e2.customBaseUrl, integrationData: a2, showEngTicketFieldsInReportIssueModalDefault: e2.showEngTicketFieldsInReportIssueModalDefault }), t2.issueReportingInit = true;
2364
2394
  }
2365
- i2({ apiKey: e2.apiKey, backendApi: n3, getSessionId: () => getOrSetSessionId(), shortcuts: e2.reportIssueShortcuts, customBaseUrl: e2.customBaseUrl, integrationData: a2, showEngTicketFieldsInReportIssueModalDefault: e2.showEngTicketFieldsInReportIssueModalDefault }), t2.issueReportingInit = true;
2395
+ } catch (e3) {
2396
+ console.warn("[Sailfish] Recorder initialization failed:", e3);
2366
2397
  }
2367
2398
  })().finally(() => {
2368
2399
  delete t2.initPromise;
2369
2400
  })), t2.initPromise);
2370
2401
  };
2371
2402
  export {
2372
- initializeFunctionSpanTrackingFromApi as A,
2373
- initializeRecording as B,
2374
- initializeWebSocket as C,
2403
+ initializeDomContentEvents as A,
2404
+ initializeFunctionSpanTrackingFromApi as B,
2405
+ initializeRecording as C,
2375
2406
  Me as D,
2376
- invalidateUrlCache as E,
2377
- isFunctionSpanTrackingEnabled as F,
2378
- matchUrlWithWildcard as G,
2379
- w as H,
2380
- onNavigationChange as I,
2381
- openReportIssueModal as J,
2382
- restoreFuncSpanState as K,
2383
- sendDomainsToNotPropagateHeaderTo as L,
2384
- sendEvent as M,
2385
- sendGraphQLRequest as N,
2386
- sendMessage as O,
2387
- startRecording as P,
2388
- startRecordingSession as Q,
2389
- trackingEvent as R,
2407
+ initializeWebSocket as E,
2408
+ invalidateUrlCache as F,
2409
+ isFunctionSpanTrackingEnabled as G,
2410
+ matchUrlWithWildcard as H,
2411
+ w as I,
2412
+ onNavigationChange as J,
2413
+ openReportIssueModal as K,
2414
+ restoreFuncSpanState as L,
2415
+ sendDomainsToNotPropagateHeaderTo as M,
2416
+ sendEvent as N,
2417
+ sendGraphQLRequest as O,
2418
+ sendMessage as P,
2419
+ startRecording as Q,
2420
+ startRecordingSession as R,
2390
2421
  $e as S,
2391
- withAppUrlMetadata as T,
2422
+ trackingEvent as T,
2423
+ withAppUrlMetadata as U,
2392
2424
  Ae as a,
2393
2425
  addOrUpdateMetadata as b,
2394
2426
  buildBatches as c,
@@ -2408,11 +2440,11 @@ export {
2408
2440
  getCachedHref as q,
2409
2441
  getCachedHrefNoQuery as r,
2410
2442
  getFuncSpanHeader as s,
2411
- getOrSetSessionId as t,
2412
- getUrlAndStoredUuids as u,
2413
- identify as v,
2414
- initRecorder as w,
2415
- initializeConsolePlugin as x,
2443
+ getIdentifiedUser as t,
2444
+ getOrSetSessionId as u,
2445
+ getUrlAndStoredUuids as v,
2446
+ identify as w,
2447
+ initRecorder as x,
2416
2448
  yieldToMain as y,
2417
- initializeDomContentEvents as z
2449
+ initializeConsolePlugin as z
2418
2450
  };
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
package/dist/env.js.br ADDED
Binary file
package/dist/env.js.gz ADDED
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
@@ -1,5 +1,5 @@
1
1
  import { createTriageAndIssueFromRecorder, createTriageFromRecorder, } from "../graphql";
2
- import { getFieldsForProject, getIntegrationData, getProjectsForTeam, getSprintFieldId, getUsers, hasValidIntegration, refreshIntegrationData, updateFormWithIntegrationData, updateIssueTypeOptions, } from "./integrations";
2
+ import { getDefaultReporterAccountId, getFieldsForProject, getIntegrationData, getProjectsForTeam, getSprintFieldId, getUsers, hasValidIntegration, refreshIntegrationData, updateFormWithIntegrationData, updateIssueTypeOptions, } from "./integrations";
3
3
  import { currentState, isRecording, recordingEndTime, recordingStartTime, resetState, setIsRecording, setRecordingEndTime, setRecordingStartTime, setTimerInterval, timerInterval, } from "./state";
4
4
  import { STORAGE_KEYS } from "./types";
5
5
  import { getChevronSVG, renderCustomMultiSelect, renderDynamicField, } from "./ui";
@@ -837,15 +837,16 @@ function initializeEngTicketForm() {
837
837
  }
838
838
  // Update form with integration data
839
839
  updateFormWithIntegrationData(currentState);
840
- // Handle reporter field for Jira
840
+ // Handle reporter field for Jira — match identified user by name/email
841
841
  if (integrationData.provider?.toLowerCase() === "jira" &&
842
- integrationData.jiraReporterAccountId &&
843
- currentState.engTicketProject) {
842
+ currentState.engTicketProject &&
843
+ !currentState.engTicketCustomFields["reporter"]) {
844
844
  const fields = getFieldsForProject(currentState.engTicketProject, currentState.engTicketIssueType);
845
845
  const reporterField = fields.find((f) => f.fieldId === "reporter");
846
- if (reporterField && !currentState.engTicketCustomFields["reporter"]) {
846
+ if (reporterField) {
847
+ const matchedReporter = getDefaultReporterAccountId();
847
848
  currentState.engTicketCustomFields["reporter"] =
848
- integrationData.jiraReporterAccountId;
849
+ matchedReporter || integrationData.jiraReporterAccountId || "";
849
850
  }
850
851
  }
851
852
  // If a project is already selected, render dynamic fields
@@ -961,13 +962,13 @@ function bindEngTicketListeners() {
961
962
  }
962
963
  if (integrationData &&
963
964
  integrationData.provider?.toLowerCase() === "jira" &&
964
- integrationData.jiraReporterAccountId &&
965
965
  engProjectSelect.value) {
966
966
  const fields = getFieldsForProject(engProjectSelect.value, currentState.engTicketIssueType);
967
967
  const reporterField = fields.find((f) => f.fieldId === "reporter");
968
968
  if (reporterField) {
969
+ const matchedReporter = getDefaultReporterAccountId();
969
970
  currentState.engTicketCustomFields["reporter"] =
970
- integrationData.jiraReporterAccountId;
971
+ matchedReporter || integrationData.jiraReporterAccountId || "";
971
972
  }
972
973
  }
973
974
  renderDynamicFields(engProjectSelect.value, currentState.engTicketIssueType);
@@ -1160,16 +1161,16 @@ function bindListeners() {
1160
1161
  currentState.engTicketPriority = integrationData.defaultPriority;
1161
1162
  }
1162
1163
  updateFormWithIntegrationData(currentState);
1163
- // Handle reporter field for Jira
1164
+ // Handle reporter field for Jira — match identified user
1164
1165
  if (integrationData.provider?.toLowerCase() === "jira" &&
1165
- integrationData.jiraReporterAccountId &&
1166
- currentState.engTicketProject) {
1166
+ currentState.engTicketProject &&
1167
+ !currentState.engTicketCustomFields["reporter"]) {
1167
1168
  const fields = getFieldsForProject(currentState.engTicketProject, currentState.engTicketIssueType);
1168
1169
  const reporterField = fields.find((f) => f.fieldId === "reporter");
1169
- if (reporterField &&
1170
- !currentState.engTicketCustomFields["reporter"]) {
1170
+ if (reporterField) {
1171
+ const matchedReporter = getDefaultReporterAccountId();
1171
1172
  currentState.engTicketCustomFields["reporter"] =
1172
- integrationData.jiraReporterAccountId;
1173
+ matchedReporter || integrationData.jiraReporterAccountId || "";
1173
1174
  }
1174
1175
  }
1175
1176
  // Render dynamic fields if a project is already selected
@@ -1,4 +1,5 @@
1
1
  import { fetchEngineeringTicketPlatformIntegrations } from "../graphql";
2
+ import { getIdentifiedUser } from "../sendSailfishMessages";
2
3
  const SUPPORT_TICKET_INTEGRATIONS = ["jira", "linear", "zendesk"];
3
4
  let integrationData = null;
4
5
  // Cache per cloud so switching between clouds is instant
@@ -220,11 +221,14 @@ export function getFieldsForProject(projectId, issueTypeId) {
220
221
  if (!integrationData?.fieldConfigurations || !projectId) {
221
222
  return [];
222
223
  }
223
- // fieldConfigurations is organized by project+issue_type combination
224
- // Match on both project_key and issue_type_id
224
+ // fieldConfigurations is organized by project+issue_type combination.
225
+ // Match project by key OR numeric id, and issue type with string coercion
226
+ // to avoid type mismatches (number vs string from different code paths).
225
227
  const projectConfig = Array.isArray(integrationData.fieldConfigurations)
226
- ? integrationData.fieldConfigurations.find((config) => config.project_key === projectId &&
227
- (!issueTypeId || config.issue_type_id === issueTypeId))
228
+ ? integrationData.fieldConfigurations.find((config) => (config.project_key === projectId ||
229
+ String(config.project_id) === String(projectId)) &&
230
+ (!issueTypeId ||
231
+ String(config.issue_type_id) === String(issueTypeId)))
228
232
  : integrationData.fieldConfigurations[projectId];
229
233
  if (!projectConfig || !projectConfig.fields) {
230
234
  return [];
@@ -237,6 +241,54 @@ export function getUsers() {
237
241
  }
238
242
  return integrationData.users;
239
243
  }
244
+ /**
245
+ * Match the current identified user against the Jira users list and
246
+ * return their accountId. Uses email, name, and email-prefix matching
247
+ * (same logic as the dashboard). Only returns a match when exactly one
248
+ * user matches to avoid ambiguity.
249
+ */
250
+ export function getDefaultReporterAccountId() {
251
+ const users = getUsers();
252
+ const identified = getIdentifiedUser();
253
+ if (!users.length || !identified)
254
+ return null;
255
+ const traits = identified.traits || {};
256
+ const email = (traits.email || identified.userId || "").toLowerCase().trim();
257
+ const name = (traits.name ||
258
+ traits.displayName ||
259
+ traits.fullName ||
260
+ traits.full_name ||
261
+ (traits.firstName || traits.first_name
262
+ ? `${traits.firstName || traits.first_name} ${traits.lastName || traits.last_name || ""}`.trim()
263
+ : "") ||
264
+ "").toLowerCase().trim();
265
+ const findUnique = (pred) => {
266
+ const matches = users.filter(pred);
267
+ return matches.length === 1 ? matches[0] : null;
268
+ };
269
+ // 1. Exact email match
270
+ let matched = email
271
+ ? findUnique((u) => (u.email || u.emailAddress || "").toLowerCase().trim() === email)
272
+ : null;
273
+ // 2. Exact name match
274
+ if (!matched && name) {
275
+ matched = findUnique((u) => {
276
+ const userName = (u.name || u.displayName || "").toLowerCase().trim();
277
+ return userName === name;
278
+ });
279
+ }
280
+ // 3. Email prefix match against name
281
+ if (!matched && email) {
282
+ const prefix = email.split("@")[0];
283
+ if (prefix.length >= 3) {
284
+ matched = findUnique((u) => {
285
+ const userName = (u.name || u.displayName || "").toLowerCase().trim();
286
+ return userName.includes(prefix);
287
+ });
288
+ }
289
+ }
290
+ return matched ? (matched.id || matched.accountId || null) : null;
291
+ }
240
292
  // Get projects based on team selection (for Linear) or directly from integration (for Jira)
241
293
  export function getProjectsForTeam(teamId) {
242
294
  if (!integrationData)