action-lens 1.0.10 → 1.0.12

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
@@ -50,15 +50,24 @@ declare class ActionLensRc {
50
50
  projectData: Project | null;
51
51
  organizationId: string | null;
52
52
  originalUserId: string | null;
53
+ /** イベントバッファとコミット閾値 */
54
+ private eventBuffer;
55
+ private readonly flushThreshold;
53
56
  constructor(_userId: string | null, projectId: string | null, userMeta: {
54
57
  name: string;
55
58
  email: string;
56
59
  } | null, metaData?: Record<string, any>, _db?: Firestore | null, prefix?: string);
60
+ /** バッファ内イベントをまとめて Firestore に書き込む */
61
+ private flushBuffer;
62
+ /** コンソール呼び出しを rrweb カスタムイベントとして記録 */
57
63
  startConsoleRecording(): void;
58
- startTimelineRecording(): void;
64
+ /** rrweb を使って画面操作をバッファ&バッチ保存 */
59
65
  startRrwebRecordingForStore(): void;
66
+ /** 録画停止とバッファフラッシュ */
60
67
  stopRrwebRecordingForStore(): void;
68
+ /** セッションの endTime を更新 */
61
69
  updateActionRecordSession(): void;
70
+ startTimelineRecording(): void;
62
71
  }
63
72
 
64
73
  /** Timestampの時はDateへの変更 */
package/dist/index.d.ts CHANGED
@@ -50,15 +50,24 @@ declare class ActionLensRc {
50
50
  projectData: Project | null;
51
51
  organizationId: string | null;
52
52
  originalUserId: string | null;
53
+ /** イベントバッファとコミット閾値 */
54
+ private eventBuffer;
55
+ private readonly flushThreshold;
53
56
  constructor(_userId: string | null, projectId: string | null, userMeta: {
54
57
  name: string;
55
58
  email: string;
56
59
  } | null, metaData?: Record<string, any>, _db?: Firestore | null, prefix?: string);
60
+ /** バッファ内イベントをまとめて Firestore に書き込む */
61
+ private flushBuffer;
62
+ /** コンソール呼び出しを rrweb カスタムイベントとして記録 */
57
63
  startConsoleRecording(): void;
58
- startTimelineRecording(): void;
64
+ /** rrweb を使って画面操作をバッファ&バッチ保存 */
59
65
  startRrwebRecordingForStore(): void;
66
+ /** 録画停止とバッファフラッシュ */
60
67
  stopRrwebRecordingForStore(): void;
68
+ /** セッションの endTime を更新 */
61
69
  updateActionRecordSession(): void;
70
+ startTimelineRecording(): void;
62
71
  }
63
72
 
64
73
  /** Timestampの時はDateへの変更 */
package/dist/index.js CHANGED
@@ -290,214 +290,124 @@ var ActionLensRc = class {
290
290
  projectData = null;
291
291
  organizationId = null;
292
292
  originalUserId = null;
293
- // 元のユーザーID(外部システムのIDなど)
293
+ /** イベントバッファとコミット閾値 */
294
+ eventBuffer = [];
295
+ flushThreshold = 50;
294
296
  constructor(_userId, projectId, userMeta, metaData = {}, _db = null, prefix = "") {
295
- try {
296
- this.originalUserId = _userId;
297
- console.log("ActionLensRc\u958B\u59CB");
298
- if (!projectId) {
299
- console.error("projectId\u304CNULL\u3067\u3059");
300
- throw new Error("projectId\u304CNULL\u3067\u3059");
301
- }
302
- if (!_userId) {
303
- console.error("userId\u304CNULL\u3067\u3059");
304
- throw new Error("userId\u304CNULL\u3067\u3059");
305
- }
306
- if (!_db) {
297
+ this.originalUserId = _userId;
298
+ this.db = _db || db;
299
+ (0, import_firestore3.getDoc)((0, import_firestore3.doc)((0, import_firestore3.collection)(this.db, `${prefix}project`), projectId)).then(async (_proj) => {
300
+ this.projectData = _proj.data();
301
+ this.organizationId = this.projectData?.organizationId || null;
302
+ if (!this.db) {
307
303
  this.db = db;
308
- } else {
309
- this.db = _db;
310
304
  }
311
- (0, import_firestore3.getDoc)((0, import_firestore3.doc)((0, import_firestore3.collection)(this.db, `${prefix}project`), projectId)).then(async (_doc) => {
312
- this.projectData = _doc.data();
313
- const projectData = this.projectData;
314
- this.organizationId = projectData?.organizationId || null;
315
- if (!_db) {
316
- this.db = db;
317
- } else {
318
- this.db = _db;
319
- }
320
- if (!this.projectData) {
321
- await (0, import_firestore3.setDoc)(
322
- (0, import_firestore3.doc)((0, import_firestore3.collection)(this.db, `${prefix}project`), projectId),
323
- {
324
- id: projectId,
325
- name: projectId,
326
- organizationId: "",
327
- isActivate: false,
328
- // デフォルトでアクティブに設定
329
- createAt: /* @__PURE__ */ new Date(),
330
- updateAt: /* @__PURE__ */ new Date(),
331
- createdBy: _userId,
332
- updatedBy: _userId
333
- },
334
- { merge: true }
335
- );
336
- throw new Error("\u30D7\u30ED\u30B8\u30A7\u30AF\u30C8\u304C\u5B58\u5728\u3057\u307E\u305B\u3093");
337
- }
338
- if (!this.projectData.isActivate) {
339
- console.warn(
340
- "\u30D7\u30ED\u30B8\u30A7\u30AF\u30C8\u306F\u975E\u30A2\u30AF\u30C6\u30A3\u30D6\u3067\u3059\u3002\u9332\u753B\u3092\u958B\u59CB\u3067\u304D\u307E\u305B\u3093\u3002"
341
- );
342
- throw new Error(
343
- "\u30D7\u30ED\u30B8\u30A7\u30AF\u30C8\u306F\u975E\u30A2\u30AF\u30C6\u30A3\u30D6\u3067\u3059\u3002\u9332\u753B\u3092\u958B\u59CB\u3067\u304D\u307E\u305B\u3093\u3002"
344
- );
345
- }
346
- (0, import_firestore3.getDoc)((0, import_firestore3.doc)((0, import_firestore3.collection)(this.db, `${prefix}user`), _userId)).then(async (_doc2) => {
347
- if (!this.db) {
348
- console.error("Firestore\u304C\u521D\u671F\u5316\u3055\u308C\u3066\u3044\u307E\u305B\u3093");
349
- throw new Error("Firestore\u304C\u521D\u671F\u5316\u3055\u308C\u3066\u3044\u307E\u305B\u3093");
350
- }
351
- this.userId = projectData.organizationId + "-" + _userId;
352
- const userData = _doc2.data();
353
- if (!_doc2.exists || !userData.organizationId || !userData.projectIds || !userData.type) {
354
- await (0, import_firestore3.setDoc)(
355
- (0, import_firestore3.doc)(
356
- (0, import_firestore3.collection)(this.db, `${prefix}user`),
357
- projectData.organizationId + "-" + _userId
358
- ),
359
- {
360
- ...userMeta || {},
361
- metaData,
362
- id: projectData.organizationId + "-" + _userId,
363
- originalUserId: _userId,
364
- type: "customer",
365
- organizationId: projectData.organizationId,
366
- projectIds: [projectId],
367
- createAt: /* @__PURE__ */ new Date(),
368
- updateAt: /* @__PURE__ */ new Date(),
369
- createdBy: _userId,
370
- updatedBy: _userId,
371
- hidden: false,
372
- hiddenBy: ""
373
- },
374
- { merge: true }
375
- ).catch((error) => {
376
- console.error("Error creating document: ", error);
377
- throw new Error("\u30E6\u30FC\u30B6\u30FC\u306E\u4F5C\u6210\u306B\u5931\u6557\u3057\u307E\u3057\u305F");
378
- });
379
- this.userData = _doc2.data();
380
- } else {
381
- this.userData = _doc2.data();
382
- if (!this.userData?.projectIds?.includes(projectId)) {
383
- await (0, import_firestore3.setDoc)(
384
- (0, import_firestore3.doc)(
385
- (0, import_firestore3.collection)(this.db, `${prefix}user`),
386
- projectData.organizationId + "-" + _userId
387
- ),
388
- {
389
- projectIds: [
390
- ...this.userData?.projectIds || [],
391
- projectId
392
- ],
393
- updateAt: /* @__PURE__ */ new Date(),
394
- updatedBy: this.userId
395
- },
396
- { merge: true }
397
- ).catch((error) => {
398
- console.error("Error updating document: ", error);
399
- throw new Error(
400
- "\u30E6\u30FC\u30B6\u30FC\u306E\u30D7\u30ED\u30B8\u30A7\u30AF\u30C8ID\u306E\u66F4\u65B0\u306B\u5931\u6557\u3057\u307E\u3057\u305F"
401
- );
402
- });
403
- }
404
- if (this.userData?.organizationId !== projectData.organizationId) {
405
- await (0, import_firestore3.setDoc)(
406
- (0, import_firestore3.doc)(
407
- (0, import_firestore3.collection)(this.db, `${prefix}user`),
408
- projectData.organizationId + "-" + _userId
409
- ),
410
- {
411
- organizationId: this.userData?.organizationId ? this.userData?.organizationId : projectData.organizationId,
412
- updateAt: /* @__PURE__ */ new Date(),
413
- updatedBy: this.userId
414
- },
415
- { merge: true }
416
- ).catch((error) => {
417
- console.error("Error updating document: ", error);
418
- throw new Error("\u30E6\u30FC\u30B6\u30FC\u306E\u7D44\u7E54ID\u306E\u66F4\u65B0\u306B\u5931\u6557\u3057\u307E\u3057\u305F");
419
- });
420
- }
421
- }
422
- this.prefix = prefix;
423
- this.projectId = projectId;
424
- this.startRrwebRecordingForStore();
425
- this.startConsoleRecording();
426
- }).catch((error) => {
427
- console.error("\u30E6\u30FC\u30B6\u30FC\u30C7\u30FC\u30BF\u306E\u53D6\u5F97\u30A8\u30E9\u30FC:", error);
428
- throw new Error("\u30E6\u30FC\u30B6\u30FC\u30C7\u30FC\u30BF\u306E\u53D6\u5F97\u306B\u5931\u6557\u3057\u307E\u3057\u305F");
429
- });
430
- }).catch((error) => {
431
- console.error("\u30D7\u30ED\u30B8\u30A7\u30AF\u30C8\u30C7\u30FC\u30BF\u306E\u53D6\u5F97\u30A8\u30E9\u30FC:", error);
432
- throw new Error("\u30D7\u30ED\u30B8\u30A7\u30AF\u30C8\u30C7\u30FC\u30BF\u306E\u53D6\u5F97\u306B\u5931\u6557\u3057\u307E\u3057\u305F");
433
- });
434
- } catch (error) {
435
- console.error("\u521D\u671F\u5316\u30A8\u30E9\u30FC:", error);
436
- throw error;
437
- }
305
+ (0, import_firestore3.getDoc)((0, import_firestore3.doc)((0, import_firestore3.collection)(this.db, `${prefix}user`), _userId)).then(async (_usr) => {
306
+ this.userId = `${this.organizationId}-${_userId}`;
307
+ this.prefix = prefix;
308
+ this.projectId = projectId;
309
+ this.startRrwebRecordingForStore();
310
+ this.startConsoleRecording();
311
+ }).catch((e) => console.error("\u30E6\u30FC\u30B6\u30FC\u30C7\u30FC\u30BF\u53D6\u5F97\u30A8\u30E9\u30FC:", e));
312
+ }).catch((e) => console.error("\u30D7\u30ED\u30B8\u30A7\u30AF\u30C8\u53D6\u5F97\u30A8\u30E9\u30FC:", e));
313
+ }
314
+ /** バッファ内イベントをまとめて Firestore に書き込む */
315
+ flushBuffer() {
316
+ if (!this.db || this.eventBuffer.length === 0) return;
317
+ const batch = (0, import_firestore3.writeBatch)(this.db);
318
+ this.eventBuffer.forEach((rec) => {
319
+ const ref = (0, import_firestore3.doc)((0, import_firestore3.collection)(this.db, `${this.prefix}ActionRecord`));
320
+ batch.set(ref, rec);
321
+ });
322
+ batch.commit().catch((e) => console.error("Batch commit error:", e));
323
+ this.eventBuffer = [];
438
324
  }
439
- // コンソールログをキャプチャ
325
+ /** コンソール呼び出しを rrweb カスタムイベントとして記録 */
440
326
  startConsoleRecording() {
441
- try {
442
- const originalConsole = { ...console };
443
- const consoleMethods = [
444
- "log",
445
- "info",
446
- "warn",
447
- "error",
448
- "debug",
449
- "trace",
450
- "assert",
451
- "clear",
452
- "context",
453
- "count",
454
- "countReset",
455
- "createTask",
456
- "debug",
457
- "dir",
458
- "dirxml",
459
- "error",
460
- "group",
461
- "groupCollapsed",
462
- "groupEnd",
463
- "memory",
464
- "profile",
465
- "profileEnd",
466
- "table",
467
- "time",
468
- "timeEnd",
469
- "timeLog",
470
- "timeStamp"
471
- ];
472
- const db2 = this.db;
473
- const _updateActionRecordSession = () => this.updateActionRecordSession();
474
- consoleMethods.forEach((method) => {
475
- console[method] = (...args) => {
476
- originalConsole[method](...args);
477
- if (!db2) {
478
- console.error("Firestore\u304C\u521D\u671F\u5316\u3055\u308C\u3066\u3044\u307E\u305B\u3093");
479
- return;
480
- }
481
- const consoleEvent = {
482
- type: "custom-event",
483
- data: {
484
- type: "console",
485
- method,
486
- args: args.map(
487
- (arg) => typeof arg === "object" ? JSON.stringify(arg) : arg
488
- )
489
- },
490
- timestamp: Date.now()
491
- };
492
- import_rrweb2.record.addCustomEvent("console", { method: "log", args });
493
- _updateActionRecordSession();
327
+ const methods = ["log", "info", "warn", "error", "debug", "trace"];
328
+ const original = {};
329
+ methods.forEach((m) => {
330
+ original[m] = console[m].bind(console);
331
+ console[m] = (...args) => {
332
+ original[m](...args);
333
+ import_rrweb2.record.addCustomEvent("console", { method: m, args });
334
+ this.updateActionRecordSession();
335
+ };
336
+ });
337
+ }
338
+ /** rrweb を使って画面操作をバッファ&バッチ保存 */
339
+ startRrwebRecordingForStore() {
340
+ if (this.stopFnForStore) return;
341
+ const userId = this.userId || "unknown";
342
+ const originalUserId = this.originalUserId || "";
343
+ const sessionId = this.sessionId;
344
+ const db2 = this.db;
345
+ const prefix = this.prefix;
346
+ (0, import_firestore3.setDoc)((0, import_firestore3.doc)((0, import_firestore3.collection)(db2, `${prefix}ActionRecordSession`), sessionId), {
347
+ id: sessionId,
348
+ startTime: /* @__PURE__ */ new Date(),
349
+ endTime: null,
350
+ userId,
351
+ projectId: this.projectId,
352
+ organizationId: this.projectData?.organizationId || null,
353
+ createAt: /* @__PURE__ */ new Date(),
354
+ updateAt: /* @__PURE__ */ new Date(),
355
+ createdBy: userId,
356
+ updatedBy: userId
357
+ }).catch((e) => console.error(e));
358
+ this.stopFnForStore = (0, import_rrweb2.record)({
359
+ collectFonts: true,
360
+ inlineImages: false,
361
+ sampling: { canvas: 500, mousemove: false, scroll: 500 },
362
+ emit: (event) => {
363
+ const rec = {
364
+ id: (0, import_firestore3.doc)((0, import_firestore3.collection)(db2, `${prefix}ActionRecord`)).id,
365
+ timeStamp: /* @__PURE__ */ new Date(),
366
+ userId,
367
+ originalUserId,
368
+ sessionId,
369
+ type: "rrweb",
370
+ rrwebRecord: JSON.stringify(event),
371
+ createAt: /* @__PURE__ */ new Date(),
372
+ updateAt: /* @__PURE__ */ new Date(),
373
+ hidden: false,
374
+ createdBy: userId,
375
+ updatedBy: userId,
376
+ hiddenBy: ""
494
377
  };
495
- });
496
- } catch (error) {
497
- console.error("\u30B3\u30F3\u30BD\u30FC\u30EB\u9332\u753B\u30A8\u30E9\u30FC:", error);
498
- throw error;
378
+ this.eventBuffer.push(rec);
379
+ (0, import_firestore3.setDoc)(
380
+ (0, import_firestore3.doc)((0, import_firestore3.collection)(db2, `${prefix}ActionRecordSession`), sessionId),
381
+ { endTime: /* @__PURE__ */ new Date(), updateAt: /* @__PURE__ */ new Date(), updatedBy: userId },
382
+ { merge: true }
383
+ ).catch((e) => console.error(e));
384
+ },
385
+ recordCanvas: false
386
+ });
387
+ setInterval(() => {
388
+ this.flushBuffer();
389
+ }, 5e3);
390
+ }
391
+ /** 録画停止とバッファフラッシュ */
392
+ stopRrwebRecordingForStore() {
393
+ if (this.stopFnForStore) {
394
+ this.stopFnForStore();
395
+ this.stopFnForStore = null;
396
+ this.flushBuffer();
499
397
  }
500
398
  }
399
+ /** セッションの endTime を更新 */
400
+ updateActionRecordSession() {
401
+ if (!this.db || !this.sessionId || !this.userId) return;
402
+ (0, import_firestore3.setDoc)(
403
+ (0, import_firestore3.doc)(
404
+ (0, import_firestore3.collection)(this.db, `${this.prefix}ActionRecordSession`),
405
+ this.sessionId
406
+ ),
407
+ { endTime: /* @__PURE__ */ new Date(), updateAt: /* @__PURE__ */ new Date(), updatedBy: this.userId },
408
+ { merge: true }
409
+ ).catch((e) => console.error(e));
410
+ }
501
411
  // タイムライン(ナビゲーションとパフォーマンス)をキャプチャ
502
412
  startTimelineRecording() {
503
413
  try {
@@ -587,110 +497,6 @@ var ActionLensRc = class {
587
497
  throw error;
588
498
  }
589
499
  }
590
- startRrwebRecordingForStore() {
591
- try {
592
- if (this.stopFnForStore) return;
593
- const _sessionId = this.sessionId;
594
- const userId = this.userId || "unknown";
595
- const originalUserId = this.originalUserId || "";
596
- const db2 = this.db;
597
- const prefix = this.prefix;
598
- if (!db2) {
599
- console.error("Firestore\u304C\u521D\u671F\u5316\u3055\u308C\u3066\u3044\u307E\u305B\u3093");
600
- return;
601
- }
602
- const ActionRecordSessionRef = (0, import_firestore3.doc)(
603
- (0, import_firestore3.collection)(db2, `${prefix}ActionRecordSession`),
604
- _sessionId
605
- );
606
- (0, import_firestore3.setDoc)(ActionRecordSessionRef, {
607
- id: _sessionId,
608
- startTime: /* @__PURE__ */ new Date(),
609
- endTime: null,
610
- userId,
611
- projectId: this.projectId || null,
612
- organizationId: this.projectData?.organizationId || null,
613
- createAt: /* @__PURE__ */ new Date(),
614
- updateAt: /* @__PURE__ */ new Date(),
615
- createdBy: userId,
616
- updatedBy: userId
617
- });
618
- const _updateActionRecordSession = () => this.updateActionRecordSession();
619
- this.stopFnForStore = (0, import_rrweb2.record)({
620
- collectFonts: true,
621
- inlineImages: true,
622
- sampling: {
623
- canvas: 1e3,
624
- mousemove: 600
625
- },
626
- emit(event) {
627
- const newDocRef = (0, import_firestore3.doc)((0, import_firestore3.collection)(db2, `${prefix}ActionRecord`));
628
- const record2 = {
629
- id: newDocRef.id,
630
- timeStamp: /* @__PURE__ */ new Date(),
631
- userId,
632
- originalUserId,
633
- type: "rrweb",
634
- sessionId: _sessionId,
635
- rrwebRecord: JSON.stringify(event),
636
- createAt: /* @__PURE__ */ new Date(),
637
- updateAt: /* @__PURE__ */ new Date(),
638
- hidden: false,
639
- createdBy: userId,
640
- updatedBy: userId,
641
- hiddenBy: ""
642
- };
643
- (0, import_firestore3.setDoc)(newDocRef, record2).catch((error) => {
644
- console.error("Error saving rrweb event: ", error);
645
- });
646
- _updateActionRecordSession();
647
- },
648
- recordCanvas: false
649
- });
650
- } catch (error) {
651
- console.error("rrweb\u9332\u753B\u30A8\u30E9\u30FC:", error);
652
- throw error;
653
- }
654
- }
655
- stopRrwebRecordingForStore() {
656
- try {
657
- if (this.stopFnForStore) {
658
- this.stopFnForStore();
659
- this.stopFnForStore = null;
660
- }
661
- } catch (error) {
662
- console.error("rrweb\u9332\u753B\u505C\u6B62\u30A8\u30E9\u30FC:", error);
663
- throw error;
664
- }
665
- }
666
- updateActionRecordSession() {
667
- try {
668
- if (!this.db || !this.sessionId || !this.userId) {
669
- console.error(
670
- "Firestore\u304C\u521D\u671F\u5316\u3055\u308C\u3066\u3044\u307E\u305B\u3093\u3001\u307E\u305F\u306FsessionId\u3001userId\u304C\u8A2D\u5B9A\u3055\u308C\u3066\u3044\u307E\u305B\u3093"
671
- );
672
- return;
673
- }
674
- const ActionRecordSessionRef = (0, import_firestore3.doc)(
675
- (0, import_firestore3.collection)(this.db, `${this.prefix}ActionRecordSession`),
676
- this.sessionId
677
- );
678
- (0, import_firestore3.setDoc)(
679
- ActionRecordSessionRef,
680
- {
681
- endTime: /* @__PURE__ */ new Date(),
682
- updateAt: /* @__PURE__ */ new Date(),
683
- updatedBy: this.userId
684
- },
685
- { merge: true }
686
- ).catch((error) => {
687
- console.error("Error updating ActionRecordSession: ", error);
688
- });
689
- } catch (error) {
690
- console.error("ActionRecordSession\u66F4\u65B0\u30A8\u30E9\u30FC:", error);
691
- throw error;
692
- }
693
- }
694
500
  };
695
501
 
696
502
  // src/utils/date.ts