action-lens 1.0.77 → 1.0.79

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/index.d.mts CHANGED
@@ -22,6 +22,9 @@ declare class ActionLensPlayer {
22
22
  sessions: (ActionRecordSession & {
23
23
  userData: User<"customer">;
24
24
  })[];
25
+ currentUrl: string | null;
26
+ startTime: number;
27
+ sessionInfo: ActionRecordSession | null;
25
28
  constructor(userId: string, targetDivId: string, _db?: Firestore, prefix?: string);
26
29
  initialize(userId: string): Promise<void>;
27
30
  replayRrwebSession(sessionId: string): Promise<any[]>;
@@ -47,6 +50,16 @@ declare class ActionLensPlayer {
47
50
  projectId?: string;
48
51
  organizationId?: string;
49
52
  recordTime: number;
53
+ ipAddress?: string;
54
+ ipOriginal?: string;
55
+ userAgent?: string;
56
+ place?: {
57
+ region: string;
58
+ latitude: number;
59
+ country: string;
60
+ longitude: number;
61
+ city: string;
62
+ };
50
63
  } & _ism_tech_actionlens_type_src_DefaultType.DefaultType & {
51
64
  userData: User<"customer">;
52
65
  })[]>;
@@ -76,6 +89,7 @@ declare class ActionLensRc {
76
89
  }, metaData?: Record<string, any>): Promise<void>;
77
90
  startConsoleRecording(): void;
78
91
  startTimelineRecording(): void;
92
+ startNetworkRecording(): void;
79
93
  startRrwebRecordingForStore(): Promise<void>;
80
94
  stopRrwebRecordingForStore(): void;
81
95
  updateActionRecordSession(): Promise<void>;
package/dist/index.d.ts CHANGED
@@ -22,6 +22,9 @@ declare class ActionLensPlayer {
22
22
  sessions: (ActionRecordSession & {
23
23
  userData: User<"customer">;
24
24
  })[];
25
+ currentUrl: string | null;
26
+ startTime: number;
27
+ sessionInfo: ActionRecordSession | null;
25
28
  constructor(userId: string, targetDivId: string, _db?: Firestore, prefix?: string);
26
29
  initialize(userId: string): Promise<void>;
27
30
  replayRrwebSession(sessionId: string): Promise<any[]>;
@@ -47,6 +50,16 @@ declare class ActionLensPlayer {
47
50
  projectId?: string;
48
51
  organizationId?: string;
49
52
  recordTime: number;
53
+ ipAddress?: string;
54
+ ipOriginal?: string;
55
+ userAgent?: string;
56
+ place?: {
57
+ region: string;
58
+ latitude: number;
59
+ country: string;
60
+ longitude: number;
61
+ city: string;
62
+ };
50
63
  } & _ism_tech_actionlens_type_src_DefaultType.DefaultType & {
51
64
  userData: User<"customer">;
52
65
  })[]>;
@@ -76,6 +89,7 @@ declare class ActionLensRc {
76
89
  }, metaData?: Record<string, any>): Promise<void>;
77
90
  startConsoleRecording(): void;
78
91
  startTimelineRecording(): void;
92
+ startNetworkRecording(): void;
79
93
  startRrwebRecordingForStore(): Promise<void>;
80
94
  stopRrwebRecordingForStore(): void;
81
95
  updateActionRecordSession(): Promise<void>;
package/dist/index.js CHANGED
@@ -71,6 +71,12 @@ var ActionLensPlayer = class {
71
71
  // プレイヤーの高さ
72
72
  sessions = [];
73
73
  // セッションのリスト
74
+ currentUrl = null;
75
+ // 現在のURLを保持するための変数
76
+ startTime = 0;
77
+ // セッションの開始時間
78
+ sessionInfo = null;
79
+ // セッション情報を保持するための変数
74
80
  constructor(userId, targetDivId, _db = db, prefix = "") {
75
81
  this.userId = userId;
76
82
  this.targetDivId = targetDivId;
@@ -102,7 +108,6 @@ var ActionLensPlayer = class {
102
108
  const data = doc3.data();
103
109
  return data.rrwebRecord ? JSON.parse(data.rrwebRecord) : data.rrwebRecords ? data.rrwebRecords?.map((r) => JSON.parse(r)) || [] : [];
104
110
  });
105
- console.log("events", events);
106
111
  if (events.length === 0) {
107
112
  console.warn(
108
113
  `\u30BB\u30C3\u30B7\u30E7\u30F3ID ${sessionId} \u306E\u30C7\u30FC\u30BF\u304C\u898B\u3064\u304B\u308A\u307E\u305B\u3093\u3067\u3057\u305F\u3002`
@@ -130,11 +135,9 @@ var ActionLensPlayer = class {
130
135
  this.width = this.replayer.wrapper.clientWidth;
131
136
  this.height = this.replayer.wrapper.clientHeight;
132
137
  this.replayer.on("custom-event", (event) => {
133
- console.log("Custom event:", event);
134
138
  this.handleCustomEvent(event);
135
139
  });
136
140
  this.replayer.on("finish", () => {
137
- console.log("Replay finished");
138
141
  this.replayer?.pause(0);
139
142
  this.playerStatus = "stopped";
140
143
  this.currentTime = this.replayer?.getCurrentTime() || 0;
@@ -142,7 +145,6 @@ var ActionLensPlayer = class {
142
145
  });
143
146
  this.replayer.on("resize", (e) => {
144
147
  const { width, height } = e;
145
- console.log("Replayer resized:", width, height);
146
148
  this.width = width;
147
149
  this.height = height;
148
150
  });
@@ -167,7 +169,6 @@ var ActionLensPlayer = class {
167
169
  });
168
170
  this.replayer.play();
169
171
  this.playerStatus = "playing";
170
- console.log(`\u30BB\u30C3\u30B7\u30E7\u30F3ID ${sessionId} \u306E\u518D\u751F\u3092\u958B\u59CB\u3057\u307E\u3057\u305F\u3002`);
171
172
  this.setTimeoutTimeline();
172
173
  return events.map((e) => (0, import_packer.unpack)(e));
173
174
  } catch (error) {
@@ -190,6 +191,7 @@ var ActionLensPlayer = class {
190
191
  break;
191
192
  case "navigation":
192
193
  const { url } = event.data;
194
+ this.currentUrl = url;
193
195
  this.displayEvent(`[${timeString}] Navigation to ${url}`, "navigation");
194
196
  break;
195
197
  case "performance":
@@ -200,7 +202,6 @@ var ActionLensPlayer = class {
200
202
  );
201
203
  break;
202
204
  default:
203
- console.warn("\u4E0D\u660E\u306A\u30AB\u30B9\u30BF\u30E0\u30A4\u30D9\u30F3\u30C8:", event.data.type);
204
205
  }
205
206
  }
206
207
  // イベントをオーバーレイに表示
@@ -256,7 +257,6 @@ var ActionLensPlayer = class {
256
257
  this.setTimeoutTimeline();
257
258
  if (this.replayer) {
258
259
  const offset = this.replayer.getCurrentTime();
259
- console.log("offset", offset);
260
260
  this.replayer.play(offset);
261
261
  this.playerStatus = "playing";
262
262
  this.currentTime = this.replayer?.getCurrentTime() || 0;
@@ -322,6 +322,7 @@ var ActionLensPlayer = class {
322
322
  const q = (0, import_firestore2.query)(
323
323
  (0, import_firestore2.collection)(this.db, `${this.prefix}ActionRecordSession`),
324
324
  (0, import_firestore2.where)("projectId", "==", projectId),
325
+ (0, import_firestore2.where)("recordTime", ">=", 10),
325
326
  (0, import_firestore2.orderBy)("startTime", "desc"),
326
327
  (0, import_firestore2.limit)(limitNum)
327
328
  );
@@ -350,6 +351,9 @@ var import_uuid = require("uuid");
350
351
  var import_rrweb2 = require("rrweb");
351
352
  var import_firestore3 = require("firebase/firestore");
352
353
  var import_packer2 = require("@rrweb/packer");
354
+ var import_functions = require("firebase/functions");
355
+ var functions = (0, import_functions.getFunctions)(app);
356
+ var setSessionDetail = (0, import_functions.httpsCallable)(functions, "setSessionDetail");
353
357
  var ActionLensRc = class {
354
358
  sessionId = (0, import_uuid.v4)();
355
359
  stopFnForStore = null;
@@ -554,7 +558,7 @@ var ActionLensRc = class {
554
558
  consoleMethods.forEach((method) => {
555
559
  console[method] = (...args) => {
556
560
  originalConsole[method](...args);
557
- import_rrweb2.record.addCustomEvent("console", { method: "log", args });
561
+ import_rrweb2.record.addCustomEvent("console", { method, args });
558
562
  };
559
563
  });
560
564
  } catch (error) {
@@ -582,12 +586,43 @@ var ActionLensRc = class {
582
586
  if (window.performance) {
583
587
  const observer = new PerformanceObserver((list) => {
584
588
  for (const entry of list.getEntries()) {
585
- import_rrweb2.record.addCustomEvent("performance", {
586
- name: entry.name,
587
- entryType: entry.entryType,
588
- startTime: entry.startTime,
589
- duration: entry.duration
590
- });
589
+ if (entry.entryType === "resource") {
590
+ const resourceEntry = entry;
591
+ import_rrweb2.record.addCustomEvent("network_resource", {
592
+ name: resourceEntry.name,
593
+ entryType: resourceEntry.entryType,
594
+ initiatorType: resourceEntry.initiatorType,
595
+ // websocket, script, document, font, xmlhttprequest, fetch, preflight etc.
596
+ nextHopProtocol: resourceEntry.nextHopProtocol,
597
+ encodedBodySize: resourceEntry.encodedBodySize,
598
+ decodedBodySize: resourceEntry.decodedBodySize,
599
+ transferSize: resourceEntry.transferSize,
600
+ duration: resourceEntry.duration,
601
+ startTime: resourceEntry.startTime,
602
+ fetchStart: resourceEntry.fetchStart,
603
+ domainLookupStart: resourceEntry.domainLookupStart,
604
+ domainLookupEnd: resourceEntry.domainLookupEnd,
605
+ connectStart: resourceEntry.connectStart,
606
+ connectEnd: resourceEntry.connectEnd,
607
+ secureConnectionStart: resourceEntry.secureConnectionStart,
608
+ requestStart: resourceEntry.requestStart,
609
+ responseStart: resourceEntry.responseStart,
610
+ responseEnd: resourceEntry.responseEnd,
611
+ workerStart: resourceEntry.workerStart,
612
+ redirectStart: resourceEntry.redirectStart,
613
+ redirectEnd: resourceEntry.redirectEnd,
614
+ // responseStatus is experimental, may not be available
615
+ responseStatus: resourceEntry.responseStatus || void 0,
616
+ serverTiming: resourceEntry.serverTiming
617
+ });
618
+ } else {
619
+ import_rrweb2.record.addCustomEvent("performance", {
620
+ name: entry.name,
621
+ entryType: entry.entryType,
622
+ startTime: entry.startTime,
623
+ duration: entry.duration
624
+ });
625
+ }
591
626
  }
592
627
  });
593
628
  observer.observe({ entryTypes: ["resource", "navigation", "paint"] });
@@ -597,6 +632,173 @@ var ActionLensRc = class {
597
632
  throw error;
598
633
  }
599
634
  }
635
+ // ネットワークリクエストをキャプチャ(新規追加)
636
+ startNetworkRecording() {
637
+ try {
638
+ const originalFetch = window.fetch;
639
+ window.fetch = (...args) => {
640
+ const startTime = Date.now();
641
+ let input = args[0];
642
+ let init = args[1];
643
+ let urlStr;
644
+ let method = "GET";
645
+ let requestBody;
646
+ if (input instanceof Request) {
647
+ urlStr = input.url;
648
+ method = input.method;
649
+ requestBody = input.body;
650
+ } else {
651
+ urlStr = input instanceof URL ? input.href : input.toString();
652
+ method = init?.method || "GET";
653
+ requestBody = init?.body;
654
+ }
655
+ import_rrweb2.record.addCustomEvent("network_request", {
656
+ type: "fetch",
657
+ method,
658
+ url: urlStr,
659
+ requestBody,
660
+ startTime,
661
+ status: "pending"
662
+ // 初期状態は保留中
663
+ });
664
+ return originalFetch(...args).then((response) => {
665
+ const endTime = Date.now();
666
+ const duration = endTime - startTime;
667
+ const clonedResponse = response.clone();
668
+ clonedResponse.text().then((responseBody) => {
669
+ import_rrweb2.record.addCustomEvent("network_response", {
670
+ type: "fetch",
671
+ url: urlStr,
672
+ status: response.status,
673
+ statusText: response.statusText,
674
+ responseBody,
675
+ duration,
676
+ endTime
677
+ });
678
+ }).catch((err) => {
679
+ console.error(
680
+ "\u30CD\u30C3\u30C8\u30EF\u30FC\u30AF\u30EC\u30B9\u30DD\u30F3\u30B9\u30DC\u30C7\u30A3\u8AAD\u307F\u8FBC\u307F\u30A8\u30E9\u30FC:",
681
+ err
682
+ );
683
+ });
684
+ return response;
685
+ }).catch((error) => {
686
+ const endTime = Date.now();
687
+ const duration = endTime - startTime;
688
+ import_rrweb2.record.addCustomEvent("network_error", {
689
+ type: "fetch",
690
+ url: urlStr,
691
+ error: error.message,
692
+ duration,
693
+ endTime
694
+ });
695
+ throw error;
696
+ });
697
+ };
698
+ const OriginalXMLHttpRequest = window.XMLHttpRequest;
699
+ class HookedXMLHttpRequest extends OriginalXMLHttpRequest {
700
+ _method;
701
+ _url;
702
+ _startTime;
703
+ static UNSENT = 0;
704
+ static OPENED = 1;
705
+ static HEADERS_RECEIVED = 2;
706
+ static LOADING = 3;
707
+ static DONE = 4;
708
+ open(method, url, async = true, username = null, password = null) {
709
+ this._method = method;
710
+ this._url = url.toString();
711
+ this._startTime = Date.now();
712
+ import_rrweb2.record.addCustomEvent("network_request", {
713
+ type: "xhr",
714
+ method,
715
+ url: this._url,
716
+ startTime: this._startTime,
717
+ status: "pending"
718
+ // 初期状態は保留中
719
+ });
720
+ return super.open(method, url, async, username, password);
721
+ }
722
+ send(body) {
723
+ this.addEventListener("load", () => {
724
+ const endTime = Date.now();
725
+ const duration = endTime - (this._startTime || 0);
726
+ import_rrweb2.record.addCustomEvent("network_response", {
727
+ type: "xhr",
728
+ url: this._url,
729
+ status: this.status,
730
+ statusText: this.statusText,
731
+ responseBody: this.responseText,
732
+ duration,
733
+ endTime
734
+ });
735
+ });
736
+ this.addEventListener("error", () => {
737
+ const endTime = Date.now();
738
+ const duration = endTime - (this._startTime || 0);
739
+ import_rrweb2.record.addCustomEvent("network_error", {
740
+ type: "xhr",
741
+ url: this._url,
742
+ error: "XHR error",
743
+ duration,
744
+ endTime
745
+ });
746
+ });
747
+ return super.send(body);
748
+ }
749
+ }
750
+ window.XMLHttpRequest = HookedXMLHttpRequest;
751
+ const OriginalWebSocket = window.WebSocket;
752
+ window.WebSocket = class HookedWebSocket extends OriginalWebSocket {
753
+ constructor(url, protocols) {
754
+ super(url, protocols);
755
+ const wsUrl = url.toString();
756
+ import_rrweb2.record.addCustomEvent("network_websocket_open", {
757
+ type: "websocket",
758
+ url: wsUrl,
759
+ startTime: Date.now()
760
+ });
761
+ this.addEventListener("message", (event) => {
762
+ import_rrweb2.record.addCustomEvent("network_websocket_message", {
763
+ type: "websocket",
764
+ url: wsUrl,
765
+ data: event.data,
766
+ time: Date.now()
767
+ });
768
+ });
769
+ this.addEventListener("close", (event) => {
770
+ import_rrweb2.record.addCustomEvent("network_websocket_close", {
771
+ type: "websocket",
772
+ url: wsUrl,
773
+ code: event.code,
774
+ reason: event.reason,
775
+ endTime: Date.now()
776
+ });
777
+ });
778
+ this.addEventListener("error", (event) => {
779
+ import_rrweb2.record.addCustomEvent("network_websocket_error", {
780
+ type: "websocket",
781
+ url: wsUrl,
782
+ error: "WebSocket error",
783
+ time: Date.now()
784
+ });
785
+ });
786
+ }
787
+ send(data) {
788
+ import_rrweb2.record.addCustomEvent("network_websocket_send", {
789
+ type: "websocket",
790
+ url: this.url,
791
+ data,
792
+ time: Date.now()
793
+ });
794
+ return super.send(data);
795
+ }
796
+ };
797
+ } catch (error) {
798
+ console.error("\u30CD\u30C3\u30C8\u30EF\u30FC\u30AF\u9332\u753B\u30A8\u30E9\u30FC:", error);
799
+ throw error;
800
+ }
801
+ }
600
802
  async startRrwebRecordingForStore() {
601
803
  try {
602
804
  if (this.stopFnForStore) return;
@@ -629,6 +831,27 @@ var ActionLensRc = class {
629
831
  createdBy: userId,
630
832
  updatedBy: userId
631
833
  });
834
+ try {
835
+ console.log("setSessionDetail\u95A2\u6570\u3092\u547C\u3073\u51FA\u3057\u307E\u3059", this.sessionId);
836
+ await setSessionDetail({ sessionId: this.sessionId });
837
+ } catch (error) {
838
+ console.error("setSessionDetail\u95A2\u6570\u306E\u547C\u3073\u51FA\u3057\u306B\u5931\u6557:", error);
839
+ }
840
+ const docRef = (0, import_firestore3.doc)(
841
+ (0, import_firestore3.collection)(this.db, "ActionRecordSession"),
842
+ this.sessionId
843
+ );
844
+ await (0, import_firestore3.getDoc)(docRef).then(async (doc3) => {
845
+ if (doc3.exists()) {
846
+ const data = doc3.data();
847
+ const ipAddress = data?.ipAddress || "";
848
+ const placeData = await getPlaceFromIp(ipAddress);
849
+ console.log("placeData", placeData);
850
+ await (0, import_firestore3.updateDoc)(docRef, { place: placeData });
851
+ }
852
+ }).catch((error) => {
853
+ console.error("IP\u30A2\u30C9\u30EC\u30B9\u306E\u53D6\u5F97\u306B\u5931\u6557:", error);
854
+ });
632
855
  this.stopFnForStore = (0, import_rrweb2.record)({
633
856
  packFn: import_packer2.pack,
634
857
  collectFonts: true,
@@ -642,7 +865,7 @@ var ActionLensRc = class {
642
865
  try {
643
866
  const deffTime = (/* @__PURE__ */ new Date()).getTime() - pinTime;
644
867
  rrwebRecords.push(JSON.stringify(event));
645
- if (rrwebRecords.length >= 20 || deffTime > 5e3) {
868
+ if (rrwebRecords.length >= 100 || deffTime >= 5e3 && rrwebRecords.length > 0) {
646
869
  pinTime = (/* @__PURE__ */ new Date()).getTime();
647
870
  const record2 = {
648
871
  id: "",
@@ -672,6 +895,8 @@ var ActionLensRc = class {
672
895
  recordCanvas: false
673
896
  });
674
897
  this.startConsoleRecording();
898
+ this.startTimelineRecording();
899
+ this.startNetworkRecording();
675
900
  } catch (error) {
676
901
  console.error("rrweb\u9332\u753B\u30A8\u30E9\u30FC:", error);
677
902
  throw error;
@@ -718,6 +943,25 @@ var ActionLensRc = class {
718
943
  }
719
944
  };
720
945
  var ActionLens = new ActionLensRc();
946
+ var getPlaceFromIp = async (ip) => {
947
+ try {
948
+ const response = await fetch(`https://ipapi.co/${ip}/json/`);
949
+ if (!response.ok) {
950
+ throw new Error(`IP\u60C5\u5831\u53D6\u5F97\u30A8\u30E9\u30FC: ${response.statusText}`);
951
+ }
952
+ const data = await response.json();
953
+ return {
954
+ city: data.city,
955
+ region: data.region,
956
+ country: data.country_name,
957
+ latitude: data.latitude,
958
+ longitude: data.longitude
959
+ };
960
+ } catch (error) {
961
+ console.error("IP\u60C5\u5831\u53D6\u5F97\u30A8\u30E9\u30FC:", error);
962
+ return null;
963
+ }
964
+ };
721
965
  // Annotate the CommonJS export names for ESM import in node:
722
966
  0 && (module.exports = {
723
967
  ActionLens,