issue-sticker 0.8.1 → 0.9.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.
@@ -1,7 +1,8 @@
1
+ import { c as createLucideIcon, u as ungzip_1, R as REPLAY_EVENT_TYPE, C as CANVAS_INTERACTION_TAG, a as cn, b as Replayer, M as MousePointer2 } from "./three-_bdgDAmI.js";
2
+ import { r } from "./three-_bdgDAmI.js";
1
3
  import { jsxs, jsx } from "react/jsx-runtime";
2
- import { memo, useRef, useState, useCallback, useEffect } from "react";
3
- import { c as createLucideIcon, u as ungzip_1, a as cn, R as Replayer, M as MousePointer2 } from "./mouse-pointer-2-BR00y3ir.js";
4
- import { T as TooltipProvider, a as Tooltip, b as TooltipTrigger, c as TooltipContent } from "./tooltip-DH02R32-.js";
4
+ import { memo, useRef, useEffect, useState, useCallback, useMemo } from "react";
5
+ import { T as TooltipProvider, a as Tooltip, b as TooltipTrigger, c as TooltipContent } from "./tooltip-UijEbdDX.js";
5
6
  /**
6
7
  * @license lucide-react v0.468.0 - ISC
7
8
  *
@@ -60,7 +61,8 @@ async function loadReplayEvents(url) {
60
61
  const TYPE_LABEL = {
61
62
  click: "클릭",
62
63
  input: "입력",
63
- nav: "이동"
64
+ nav: "이동",
65
+ canvas: "캔버스"
64
66
  };
65
67
  const NODE_TYPE_ELEMENT = 2;
66
68
  const NODE_TYPE_TEXT = 3;
@@ -154,13 +156,21 @@ class NodeIndex {
154
156
  return (firstClass ? `${tag}.${firstClass}` : `<${tag}>`).slice(0, 40);
155
157
  }
156
158
  }
157
- const EVENT_TYPE_FULL_SNAPSHOT = 2;
158
- const EVENT_TYPE_INCREMENTAL = 3;
159
- const EVENT_TYPE_META = 4;
160
159
  const SOURCE_MUTATION$1 = 0;
161
160
  const SOURCE_MOUSE_INTERACTION = 2;
162
161
  const SOURCE_INPUT = 5;
163
162
  const MOUSE_CLICK = 2;
163
+ function canvasLabel(payload) {
164
+ if ((payload == null ? void 0 : payload.kind) === "external") {
165
+ return "화면 변경";
166
+ }
167
+ const isDrag = (payload == null ? void 0 : payload.kind) === "drag";
168
+ const target = payload == null ? void 0 : payload.target;
169
+ if (target) {
170
+ return isDrag ? `${target} 드래그` : target;
171
+ }
172
+ return isDrag ? "드래그" : "클릭";
173
+ }
164
174
  function deriveTimeline(events) {
165
175
  var _a;
166
176
  const list = events;
@@ -169,12 +179,13 @@ function deriveTimeline(events) {
169
179
  let recordedHeight = 0;
170
180
  let seenFirstMeta = false;
171
181
  const out = [];
182
+ const canvasFrames = [];
172
183
  const index = new NodeIndex();
173
184
  for (const ev of list) {
174
185
  const ts = Number((ev == null ? void 0 : ev.timestamp) ?? 0);
175
186
  const t = ts - startTime;
176
187
  const data = (ev == null ? void 0 : ev.data) ?? {};
177
- if ((ev == null ? void 0 : ev.type) === EVENT_TYPE_META) {
188
+ if ((ev == null ? void 0 : ev.type) === REPLAY_EVENT_TYPE.Meta) {
178
189
  if (!seenFirstMeta) {
179
190
  seenFirstMeta = true;
180
191
  recordedWidth = Number(data.width ?? 0);
@@ -185,11 +196,33 @@ function deriveTimeline(events) {
185
196
  out.push({ t, type: "nav", href, label: href || TYPE_LABEL.nav });
186
197
  continue;
187
198
  }
188
- if ((ev == null ? void 0 : ev.type) === EVENT_TYPE_FULL_SNAPSHOT) {
199
+ if ((ev == null ? void 0 : ev.type) === REPLAY_EVENT_TYPE.Custom) {
200
+ if (data.tag !== CANVAS_INTERACTION_TAG) continue;
201
+ const payload = data.payload;
202
+ if (payload == null ? void 0 : payload.snapshot) {
203
+ canvasFrames.push({
204
+ t,
205
+ nodeId: typeof payload.nodeId === "number" ? payload.nodeId : null,
206
+ canvasIndex: typeof payload.canvasIndex === "number" ? payload.canvasIndex : 0,
207
+ src: payload.snapshot,
208
+ ...payload.baseline === true ? { baseline: true } : {}
209
+ });
210
+ }
211
+ if ((payload == null ? void 0 : payload.sampled) === true) continue;
212
+ out.push({
213
+ t,
214
+ type: "canvas",
215
+ label: canvasLabel(payload),
216
+ ...(payload == null ? void 0 : payload.snapshot) ? { thumbnail: payload.snapshot } : {},
217
+ ...typeof (payload == null ? void 0 : payload.nodeId) === "number" ? { nodeId: payload.nodeId } : {}
218
+ });
219
+ continue;
220
+ }
221
+ if ((ev == null ? void 0 : ev.type) === REPLAY_EVENT_TYPE.FullSnapshot) {
189
222
  index.reset(data.node);
190
223
  continue;
191
224
  }
192
- if ((ev == null ? void 0 : ev.type) === EVENT_TYPE_INCREMENTAL) {
225
+ if ((ev == null ? void 0 : ev.type) === REPLAY_EVENT_TYPE.IncrementalSnapshot) {
193
226
  const source = Number(data.source);
194
227
  if (source === SOURCE_MUTATION$1) {
195
228
  for (const add of data.adds ?? []) {
@@ -204,11 +237,9 @@ function deriveTimeline(events) {
204
237
  }
205
238
  }
206
239
  }
207
- return { startTime, recordedWidth, recordedHeight, events: out };
240
+ return { startTime, recordedWidth, recordedHeight, events: out, canvasFrames };
208
241
  }
209
242
  const WIDGET_HOST_HTML_ID = "issue-sticker-host";
210
- const EVENT_FULL_SNAPSHOT = 2;
211
- const EVENT_INCREMENTAL = 3;
212
243
  const NODE_ELEMENT = 2;
213
244
  const SOURCE_MUTATION = 0;
214
245
  const SOURCE_MOUSE_MOVE = 1;
@@ -314,13 +345,13 @@ function stripWidgetEvents(events) {
314
345
  let removedEvents = 0;
315
346
  for (const event of events) {
316
347
  const ev = event;
317
- if ((ev == null ? void 0 : ev.type) === EVENT_FULL_SNAPSHOT) {
348
+ if ((ev == null ? void 0 : ev.type) === REPLAY_EVENT_TYPE.FullSnapshot) {
318
349
  const data2 = asRecord(ev.data);
319
350
  const pruned = pruneTree(data2.node, widgetIds);
320
351
  out.push(pruned === data2.node ? event : { ...ev, data: { ...data2, node: pruned } });
321
352
  continue;
322
353
  }
323
- if ((ev == null ? void 0 : ev.type) !== EVENT_INCREMENTAL) {
354
+ if ((ev == null ? void 0 : ev.type) !== REPLAY_EVENT_TYPE.IncrementalSnapshot) {
324
355
  out.push(event);
325
356
  continue;
326
357
  }
@@ -368,10 +399,12 @@ const MOUSE_TAIL_CONFIG = {
368
399
  };
369
400
  const INITIAL_SHOW_TRAIL = true;
370
401
  const SKIP_MS = 5e3;
402
+ const PAINT_RETRY_DEADLINE_MS = 5e3;
371
403
  const TYPE_DOT = {
372
404
  click: "bg-brand",
373
405
  input: "bg-success",
374
- nav: "bg-text-tertiary"
406
+ nav: "bg-text-tertiary",
407
+ canvas: "bg-warning"
375
408
  };
376
409
  function formatTime(ms) {
377
410
  const total = Math.max(0, Math.floor(ms / 1e3));
@@ -387,7 +420,18 @@ const EventLog = memo(function EventLog2({
387
420
  onSeek,
388
421
  total
389
422
  }) {
390
- const filtered = filter === "all" ? rows : rows.filter((r) => r.type === filter);
423
+ const filtered = filter === "all" ? rows : rows.filter((r2) => r2.type === filter);
424
+ const listRef = useRef(null);
425
+ useEffect(() => {
426
+ const list = listRef.current;
427
+ const row = list == null ? void 0 : list.querySelector(`[data-row-index="${currentIndex}"]`);
428
+ if (!list || !row) return;
429
+ const top = row.offsetTop;
430
+ const bottom = top + row.offsetHeight;
431
+ if (top < list.scrollTop || bottom > list.scrollTop + list.clientHeight) {
432
+ list.scrollTop = Math.max(0, top - (list.clientHeight - row.offsetHeight) / 2);
433
+ }
434
+ }, [currentIndex, filter]);
391
435
  return /* @__PURE__ */ jsxs("div", { className: "flex h-full min-h-0 min-w-0 flex-col rounded-md border border-line-subtle bg-surface-1", children: [
392
436
  /* @__PURE__ */ jsxs("div", { className: "flex items-center justify-between border-b border-line-subtle px-3 py-2.5", children: [
393
437
  /* @__PURE__ */ jsx("span", { className: "text-sm font-semibold text-text-primary", children: "이벤트 로그" }),
@@ -396,7 +440,7 @@ const EventLog = memo(function EventLog2({
396
440
  total
397
441
  ] })
398
442
  ] }),
399
- /* @__PURE__ */ jsx("div", { className: "flex gap-1.5 border-b border-line-subtle px-3 py-2", children: ["all", "click", "input", "nav"].map((f) => /* @__PURE__ */ jsx(
443
+ /* @__PURE__ */ jsx("div", { className: "flex gap-1.5 border-b border-line-subtle px-3 py-2", children: ["all", "click", "input", "nav", "canvas"].map((f) => /* @__PURE__ */ jsx(
400
444
  "button",
401
445
  {
402
446
  type: "button",
@@ -409,12 +453,13 @@ const EventLog = memo(function EventLog2({
409
453
  },
410
454
  f
411
455
  )) }),
412
- /* @__PURE__ */ jsx("div", { className: "min-h-0 flex-1 overflow-auto", children: filtered.map((row) => {
456
+ /* @__PURE__ */ jsx("div", { ref: listRef, className: "relative min-h-0 flex-1 overflow-auto", children: filtered.map((row) => {
413
457
  const isCurrent = row.index === currentIndex;
414
458
  return /* @__PURE__ */ jsxs(
415
459
  "button",
416
460
  {
417
461
  type: "button",
462
+ "data-row-index": row.index,
418
463
  onClick: () => onSeek(row.t),
419
464
  className: cn(
420
465
  "flex w-full items-center gap-2 border-b border-line-subtle px-3 py-2 text-left text-xs hover:bg-surface-2",
@@ -423,6 +468,14 @@ const EventLog = memo(function EventLog2({
423
468
  children: [
424
469
  /* @__PURE__ */ jsx("span", { className: "w-9 shrink-0 tabular-nums text-text-tertiary", children: formatTime(row.t) }),
425
470
  /* @__PURE__ */ jsx("span", { className: cn("h-2 w-2 shrink-0 rounded-sm", TYPE_DOT[row.type]) }),
471
+ row.thumbnail && /* @__PURE__ */ jsx(
472
+ "img",
473
+ {
474
+ src: row.thumbnail,
475
+ alt: "",
476
+ className: "h-8 w-12 shrink-0 rounded-sm border border-line-subtle object-cover"
477
+ }
478
+ ),
426
479
  /* @__PURE__ */ jsx("span", { className: "min-w-0 flex-1 truncate text-text-secondary", children: row.label }),
427
480
  /* @__PURE__ */ jsx("span", { className: "shrink-0 text-text-tertiary", children: TYPE_LABEL[row.type] })
428
481
  ]
@@ -432,6 +485,29 @@ const EventLog = memo(function EventLog2({
432
485
  }) })
433
486
  ] });
434
487
  });
488
+ async function waitForReplayCanvas(replayerRef, shot, cancelled) {
489
+ const deadline = Date.now() + PAINT_RETRY_DEADLINE_MS;
490
+ for (; ; ) {
491
+ if (cancelled()) return null;
492
+ const node = findReplayCanvas(replayerRef.current, shot);
493
+ if (node) return node;
494
+ if (Date.now() >= deadline) return null;
495
+ await new Promise((resolve) => requestAnimationFrame(resolve));
496
+ }
497
+ }
498
+ function findReplayCanvas(replayer, shot) {
499
+ var _a, _b;
500
+ const replayDocument = (_a = replayer == null ? void 0 : replayer.iframe) == null ? void 0 : _a.contentDocument;
501
+ if (shot.nodeId !== null) {
502
+ const mirror = (_b = replayer == null ? void 0 : replayer.getMirror) == null ? void 0 : _b.call(replayer);
503
+ const node = mirror == null ? void 0 : mirror.getNode(shot.nodeId);
504
+ if (node && node.tagName === "CANVAS") {
505
+ return node;
506
+ }
507
+ }
508
+ const candidate = replayDocument == null ? void 0 : replayDocument.querySelectorAll("canvas")[shot.canvasIndex];
509
+ return candidate && candidate.tagName === "CANVAS" ? candidate : null;
510
+ }
435
511
  function SessionReplayPlayer({ url }) {
436
512
  const rootRef = useRef(null);
437
513
  const hostRef = useRef(null);
@@ -448,6 +524,9 @@ function SessionReplayPlayer({ url }) {
448
524
  const [durationMs, setDurationMs] = useState(0);
449
525
  const [currentMs, setCurrentMs] = useState(0);
450
526
  const [timeline, setTimeline] = useState([]);
527
+ const [canvasShots, setCanvasShots] = useState([]);
528
+ const paintedCanvasRef = useRef(/* @__PURE__ */ new Map());
529
+ const [rebuildTick, setRebuildTick] = useState(0);
451
530
  const [logRows, setLogRows] = useState([]);
452
531
  const [filter, setFilter] = useState("all");
453
532
  const [isFullscreen, setIsFullscreen] = useState(false);
@@ -467,8 +546,8 @@ function SessionReplayPlayer({ url }) {
467
546
  const startRaf = useCallback(() => {
468
547
  stopRaf();
469
548
  const tick = () => {
470
- const r = replayerRef.current;
471
- if (r) setCurrentMs(Math.min(r.getCurrentTime(), durationRef.current));
549
+ const r2 = replayerRef.current;
550
+ if (r2) setCurrentMs(Math.min(r2.getCurrentTime(), durationRef.current));
472
551
  rafRef.current = requestAnimationFrame(tick);
473
552
  };
474
553
  rafRef.current = requestAnimationFrame(tick);
@@ -528,20 +607,31 @@ function SessionReplayPlayer({ url }) {
528
607
  mouseTail: INITIAL_SHOW_TRAIL ? MOUSE_TAIL_CONFIG : false
529
608
  }
530
609
  );
610
+ replayer.on("fullsnapshot-rebuilded", () => {
611
+ if (cancelled) return;
612
+ setRebuildTick((tick) => tick + 1);
613
+ });
531
614
  replayer.on("finish", () => {
532
615
  if (cancelled) return;
533
616
  applyIsPlaying(false);
534
617
  startedRef.current = false;
535
618
  stopRaf();
536
619
  });
620
+ try {
621
+ replayer.pause(0);
622
+ } catch {
623
+ }
537
624
  replayerRef.current = replayer;
625
+ paintedCanvasRef.current.clear();
538
626
  setTimeline(derived.events);
539
627
  const totalTime = replayer.getMetaData().totalTime;
540
628
  applyDuration(totalTime);
629
+ setCanvasShots(derived.canvasFrames);
541
630
  const rows = derived.events.map((ev, i) => ({
542
631
  t: ev.t,
543
632
  type: ev.type,
544
633
  label: ev.label,
634
+ ...ev.thumbnail ? { thumbnail: ev.thumbnail } : {},
545
635
  index: i
546
636
  }));
547
637
  setLogRows(rows);
@@ -567,32 +657,32 @@ function SessionReplayPlayer({ url }) {
567
657
  return () => document.removeEventListener("fullscreenchange", onChange);
568
658
  }, []);
569
659
  const seek = useCallback((ms) => {
570
- const r = replayerRef.current;
571
- if (!r) return;
660
+ const r2 = replayerRef.current;
661
+ if (!r2) return;
572
662
  const clamped = Math.max(0, Math.min(ms, durationRef.current));
573
- if (isPlayingRef.current) r.play(clamped);
574
- else r.pause(clamped);
663
+ if (isPlayingRef.current) r2.play(clamped);
664
+ else r2.pause(clamped);
575
665
  startedRef.current = true;
576
666
  setCurrentMs(clamped);
577
667
  }, []);
578
668
  const togglePlay = useCallback(() => {
579
- const r = replayerRef.current;
580
- if (!r) return;
669
+ const r2 = replayerRef.current;
670
+ if (!r2) return;
581
671
  if (isPlayingRef.current) {
582
- r.pause();
672
+ r2.pause();
583
673
  applyIsPlaying(false);
584
674
  stopRaf();
585
675
  } else {
586
- r.play(startedRef.current ? r.getCurrentTime() : 0);
676
+ r2.play(startedRef.current ? r2.getCurrentTime() : 0);
587
677
  startedRef.current = true;
588
678
  applyIsPlaying(true);
589
679
  startRaf();
590
680
  }
591
681
  }, [stopRaf, startRaf]);
592
682
  const restart = useCallback(() => {
593
- const r = replayerRef.current;
594
- if (!r) return;
595
- r.play(0);
683
+ const r2 = replayerRef.current;
684
+ if (!r2) return;
685
+ r2.play(0);
596
686
  startedRef.current = true;
597
687
  applyIsPlaying(true);
598
688
  startRaf();
@@ -634,6 +724,57 @@ function SessionReplayPlayer({ url }) {
634
724
  [togglePlay, seek, currentMs, toggleFullscreen]
635
725
  );
636
726
  const currentIndex = logRows.reduce((acc, row) => row.t <= currentMs ? row.index : acc, -1);
727
+ const currentShots = useMemo(() => {
728
+ const byCanvas = /* @__PURE__ */ new Map();
729
+ for (const shot of canvasShots) {
730
+ const applies = shot.t <= currentMs || shot.baseline && !byCanvas.has(shot.canvasIndex);
731
+ if (applies) {
732
+ byCanvas.set(shot.canvasIndex, shot);
733
+ }
734
+ }
735
+ return Array.from(byCanvas.values());
736
+ }, [canvasShots, currentMs]);
737
+ const shotKey = currentShots.map((shot) => `${shot.canvasIndex}:${shot.t}`).join("|");
738
+ useEffect(() => {
739
+ let cancelled = false;
740
+ const painted = paintedCanvasRef.current;
741
+ const apply = async () => {
742
+ for (const shot of currentShots) {
743
+ const prev = painted.get(shot.canvasIndex);
744
+ if (prev && prev.src === shot.src && prev.rebuild === rebuildTick && prev.node.isConnected) {
745
+ continue;
746
+ }
747
+ const node = await waitForReplayCanvas(replayerRef, shot, () => cancelled);
748
+ if (cancelled || !node) {
749
+ continue;
750
+ }
751
+ const image = new Image();
752
+ image.src = shot.src;
753
+ try {
754
+ await image.decode();
755
+ } catch {
756
+ continue;
757
+ }
758
+ if (cancelled) {
759
+ return;
760
+ }
761
+ node.style.backgroundImage = `url("${shot.src}")`;
762
+ node.style.backgroundSize = "100% 100%";
763
+ node.style.backgroundRepeat = "no-repeat";
764
+ painted.set(shot.canvasIndex, { node, src: shot.src, rebuild: rebuildTick });
765
+ }
766
+ for (const [canvasIndex, entry] of Array.from(painted.entries())) {
767
+ if (!currentShots.some((shot) => shot.canvasIndex === canvasIndex)) {
768
+ entry.node.style.backgroundImage = "";
769
+ painted.delete(canvasIndex);
770
+ }
771
+ }
772
+ };
773
+ void apply();
774
+ return () => {
775
+ cancelled = true;
776
+ };
777
+ }, [shotKey, rebuildTick]);
637
778
  if (state === "error") {
638
779
  return /* @__PURE__ */ jsx("p", { className: "text-sm text-text-secondary", children: "리플레이를 불러오지 못했습니다." });
639
780
  }
@@ -802,5 +943,6 @@ function SessionReplayViewer({ issue }) {
802
943
  return /* @__PURE__ */ jsx(SessionReplayPlayer, { url });
803
944
  }
804
945
  export {
805
- SessionReplayViewer
946
+ SessionReplayViewer,
947
+ r as registerThree
806
948
  };
@@ -1,7 +1,7 @@
1
- import { u as uploadScreenshotDataUrls, a as uploadSignedMediaWithApi, d as directUploadToSignedUrl, p as pristineFetch, g as getElementPosition, c as captureWithModernScreenshot, b as buildJiraCreateFields, e as buildNotionCreateFields, f as buildGuestOwnerQuery, h as composeIssueFilterGroups, i as buildIssueIntegrationsPayload, j as devLogger, C as ConsoleCollector, N as NetworkCollector, s as selectNetworkLogsForSubmit, k as filterExcludeServiceRelatedLogs, l as filterExcludeServiceRelatedConsoleLogs, m as compactNetworkLogsForTransport, n as CONSOLE_LOG_SUBMIT_LIMIT, o as buildExternalUserPayload, q as shrinkNetworkLogsToFit, r as measureJsonBytes, t as sanitizeString, v as getCurrentPageUrl, S as ScreenRecordingController, w as SessionReplayCaptureController, x as preloadModernScreenshot, I as ISSUE_STICKER_INTERNAL_LOG_PREFIX } from "./externalUserPayload-D-P1-QaW.js";
1
+ import { u as uploadScreenshotDataUrls, a as uploadSignedMediaWithApi, d as directUploadToSignedUrl, p as pristineFetch, g as getElementPosition, c as captureWithModernScreenshot, b as buildJiraCreateFields, e as buildNotionCreateFields, f as buildGuestOwnerQuery, h as composeIssueFilterGroups, i as buildIssueIntegrationsPayload, j as devLogger, W as WebSocketCollector, C as ConsoleCollector, N as NetworkCollector, s as selectNetworkLogsForSubmit, k as filterExcludeServiceRelatedLogs, l as filterExcludeServiceRelatedConsoleLogs, m as compactNetworkLogsForTransport, n as CONSOLE_LOG_SUBMIT_LIMIT, o as buildExternalUserPayload, q as shrinkNetworkLogsToFit, r as measureJsonBytes, t as sanitizeString, v as serializeSocketTranscript, w as uploadSocketTranscript, x as getCurrentPageUrl, S as ScreenRecordingController, y as SessionReplayCaptureController, z as preloadModernScreenshot, I as ISSUE_STICKER_INTERNAL_LOG_PREFIX } from "./externalUserPayload-CVYSPfcx.js";
2
+ import { r } from "./three-_bdgDAmI.js";
2
3
  import "react/jsx-runtime";
3
4
  import "react";
4
- import "./mouse-pointer-2-BR00y3ir.js";
5
5
  const WINDOW_MS = 6e4;
6
6
  const MAX_PER_WINDOW = 5;
7
7
  class AutoIssueRateLimit {
@@ -854,7 +854,8 @@ class HeadlessIssueRepository {
854
854
  }
855
855
  const defaultDeps = {
856
856
  createNetworkCollector: (apiBaseUrl) => new NetworkCollector(apiBaseUrl),
857
- createConsoleCollector: () => new ConsoleCollector()
857
+ createConsoleCollector: () => new ConsoleCollector(),
858
+ createSocketCollector: (apiBaseUrl) => new WebSocketCollector(apiBaseUrl)
858
859
  };
859
860
  class HeadlessLogCollectors {
860
861
  constructor(config, getApiBaseUrl2, deps = defaultDeps) {
@@ -863,9 +864,10 @@ class HeadlessLogCollectors {
863
864
  this.deps = deps;
864
865
  this.networkCollector = null;
865
866
  this.consoleCollector = null;
867
+ this.socketCollector = null;
866
868
  }
867
869
  start() {
868
- var _a, _b;
870
+ var _a, _b, _c, _d, _e;
869
871
  if (((_a = this.config.capture) == null ? void 0 : _a.networkLogs) !== false && !this.networkCollector) {
870
872
  this.networkCollector = this.deps.createNetworkCollector(this.getApiBaseUrl());
871
873
  this.networkCollector.start();
@@ -874,13 +876,26 @@ class HeadlessLogCollectors {
874
876
  this.consoleCollector = this.deps.createConsoleCollector();
875
877
  this.consoleCollector.start();
876
878
  }
879
+ if (((_c = this.config.capture) == null ? void 0 : _c.socketLogs) !== false && !this.socketCollector) {
880
+ const socket = this.deps.createSocketCollector(this.getApiBaseUrl());
881
+ this.socketCollector = socket;
882
+ (_e = (_d = this.networkCollector) == null ? void 0 : _d.bindSocketLogs) == null ? void 0 : _e.call(_d, () => socket.getNetworkLogs());
883
+ socket.start();
884
+ }
877
885
  }
878
886
  stop() {
879
- var _a, _b;
887
+ var _a, _b, _c;
880
888
  (_a = this.networkCollector) == null ? void 0 : _a.stop();
881
889
  (_b = this.consoleCollector) == null ? void 0 : _b.stop();
890
+ (_c = this.socketCollector) == null ? void 0 : _c.stop();
882
891
  this.networkCollector = null;
883
892
  this.consoleCollector = null;
893
+ this.socketCollector = null;
894
+ }
895
+ /** 제출 시점에 소켓 전사를 만들 재료. 없으면 빈 배열 — serializeSocketTranscript 가 null 로 걸러낸다. */
896
+ getSocketConnections() {
897
+ var _a;
898
+ return ((_a = this.socketCollector) == null ? void 0 : _a.getConnections()) ?? [];
884
899
  }
885
900
  /**
886
901
  * 스크린샷 캡처처럼 **우리가 서드파티 요청을 일으키는** 구간을 감싼다.
@@ -1107,6 +1122,7 @@ function buildIssueCreatePayload({
1107
1122
  session_replay_upload_id: uploads.replayUpload.uploadId,
1108
1123
  session_replay_meta: uploads.replayUpload.meta
1109
1124
  } : {},
1125
+ ...uploads.socketUpload ? { socket_log_upload_id: uploads.socketUpload.uploadId } : {},
1110
1126
  console_logs: logs.consoleLogs.length > 0 ? logs.consoleLogs : void 0,
1111
1127
  user_agent: userAgent,
1112
1128
  tenant_id: auth.tenantId,
@@ -1138,18 +1154,27 @@ async function submitHeadlessIssueDraft({
1138
1154
  logs,
1139
1155
  currentUrl,
1140
1156
  userAgent,
1141
- uploadSessionReplaySnapshot
1157
+ uploadSessionReplaySnapshot,
1158
+ getSocketConnections
1142
1159
  }) {
1143
1160
  const screenshotUploads = draft.mediaMode === "screenshot" ? await transport.uploadScreenshotPreviews(draft.screenshotPreviewUrls) : [];
1144
1161
  const screenshotUploadIds = screenshotUploads.map((upload) => upload.id);
1145
1162
  const videoUpload = draft.mediaMode === "video" && pendingVideoFile ? await transport.uploadSignedMedia(pendingVideoFile, "video") : null;
1146
1163
  const replayUpload = draft.sessionReplayEnabled ? await uploadSessionReplaySnapshot() : null;
1164
+ const socketSnapshot = await serializeSocketTranscript(getSocketConnections());
1165
+ const socketUpload = socketSnapshot ? await uploadSocketTranscript(
1166
+ {
1167
+ post: (endpoint, body) => transport.request(endpoint, { method: "POST", body }),
1168
+ directUpload: directUploadToSignedUrl
1169
+ },
1170
+ socketSnapshot
1171
+ ) : null;
1147
1172
  const { payload: issueData, stillOverBudget } = buildIssueCreatePayload({
1148
1173
  draft,
1149
1174
  auth,
1150
1175
  config,
1151
1176
  projectId,
1152
- uploads: { screenshotUploadIds, videoUpload, replayUpload },
1177
+ uploads: { screenshotUploadIds, videoUpload, replayUpload, socketUpload },
1153
1178
  logs,
1154
1179
  currentUrl,
1155
1180
  userAgent
@@ -1499,7 +1524,8 @@ class HeadlessClientImpl {
1499
1524
  logs: this.logCollectors.collect(),
1500
1525
  currentUrl: getCurrentPageUrl(),
1501
1526
  userAgent: typeof navigator !== "undefined" ? navigator.userAgent : void 0,
1502
- uploadSessionReplaySnapshot: () => this.uploadSessionReplaySnapshot()
1527
+ uploadSessionReplaySnapshot: () => this.uploadSessionReplaySnapshot(),
1528
+ getSocketConnections: () => this.logCollectors.getSocketConnections()
1503
1529
  });
1504
1530
  this.clearCaptureListeners();
1505
1531
  this.clearPendingMedia();
@@ -1561,7 +1587,8 @@ class HeadlessClientImpl {
1561
1587
  logs,
1562
1588
  currentUrl: getCurrentPageUrl(),
1563
1589
  userAgent: typeof navigator !== "undefined" ? navigator.userAgent : void 0,
1564
- uploadSessionReplaySnapshot: () => this.uploadSessionReplaySnapshot()
1590
+ uploadSessionReplaySnapshot: () => this.uploadSessionReplaySnapshot(),
1591
+ getSocketConnections: () => this.logCollectors.getSocketConnections()
1565
1592
  });
1566
1593
  this.state.setSnapshot({
1567
1594
  issues: [createdIssue, ...this.snapshot.issues]
@@ -1858,5 +1885,6 @@ function createIssueStickerHeadless(config) {
1858
1885
  export {
1859
1886
  IssueStickerHeadlessError,
1860
1887
  createIssueStickerHeadless,
1861
- createIssueStickerHeadless as default
1888
+ createIssueStickerHeadless as default,
1889
+ r as registerThree
1862
1890
  };