action-lens 1.0.18 → 1.0.20

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.mjs CHANGED
@@ -257,13 +257,7 @@ var ActionLensPlayer = class {
257
257
  // src/record.ts
258
258
  import { v4 as uuidv4 } from "uuid";
259
259
  import { record } from "rrweb";
260
- import {
261
- doc as doc2,
262
- collection as collection2,
263
- writeBatch,
264
- setDoc as setDoc2,
265
- getDoc as getDoc2
266
- } from "firebase/firestore";
260
+ import { doc as doc2, setDoc as setDoc2, collection as collection2, getDoc as getDoc2 } from "firebase/firestore";
267
261
  var ActionLensRc = class {
268
262
  sessionId = uuidv4();
269
263
  stopFnForStore = null;
@@ -275,136 +269,213 @@ var ActionLensRc = class {
275
269
  projectData = null;
276
270
  organizationId = null;
277
271
  originalUserId = null;
278
- /** イベントバッファとコミット閾値 */
279
- eventBuffer = [];
280
- flushThreshold = 50;
281
- constructor(_userId, projectId, _db = null, prefix = "") {
282
- if (!!this.originalUserId) {
283
- console.warn("ActionLensRc\u306F\u4E00\u5EA6\u3060\u3051\u521D\u671F\u5316\u3057\u3066\u304F\u3060\u3055\u3044\u3002");
284
- return;
285
- }
286
- this.originalUserId = _userId;
287
- this.db = _db || db;
288
- this.initialize(prefix, projectId, _userId);
289
- }
290
- async initialize(prefix, projectId, _userId) {
291
- if (!this.db) {
292
- this.db = db;
293
- }
294
- const _proj = await getDoc2(
295
- doc2(collection2(this.db, `${prefix}project`), projectId)
296
- );
297
- this.projectData = _proj.data();
298
- this.organizationId = this.projectData?.organizationId || null;
299
- if (!this.db) {
300
- this.db = db;
272
+ // 元のユーザーID(外部システムのIDなど)
273
+ constructor(_userId, projectId, userMeta, metaData = {}, _db = null, prefix = "") {
274
+ try {
275
+ this.originalUserId = _userId;
276
+ console.log("ActionLensRc\u958B\u59CB");
277
+ if (!projectId) {
278
+ console.error("projectId\u304CNULL\u3067\u3059");
279
+ throw new Error("projectId\u304CNULL\u3067\u3059");
280
+ }
281
+ if (!_userId) {
282
+ console.error("userId\u304CNULL\u3067\u3059");
283
+ throw new Error("userId\u304CNULL\u3067\u3059");
284
+ }
285
+ if (!_db) {
286
+ this.db = db;
287
+ } else {
288
+ this.db = _db;
289
+ }
290
+ getDoc2(doc2(collection2(this.db, `${prefix}project`), projectId)).then(async (_doc) => {
291
+ this.projectData = _doc.data();
292
+ const projectData = this.projectData;
293
+ this.organizationId = projectData?.organizationId || null;
294
+ if (!_db) {
295
+ this.db = db;
296
+ } else {
297
+ this.db = _db;
298
+ }
299
+ if (!this.projectData) {
300
+ await setDoc2(
301
+ doc2(collection2(this.db, `${prefix}project`), projectId),
302
+ {
303
+ id: projectId,
304
+ name: projectId,
305
+ organizationId: "",
306
+ isActivate: false,
307
+ // デフォルトでアクティブに設定
308
+ createAt: /* @__PURE__ */ new Date(),
309
+ updateAt: /* @__PURE__ */ new Date(),
310
+ createdBy: _userId,
311
+ updatedBy: _userId
312
+ },
313
+ { merge: true }
314
+ );
315
+ throw new Error("\u30D7\u30ED\u30B8\u30A7\u30AF\u30C8\u304C\u5B58\u5728\u3057\u307E\u305B\u3093");
316
+ }
317
+ if (!this.projectData.isActivate) {
318
+ console.warn(
319
+ "\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"
320
+ );
321
+ throw new Error(
322
+ "\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"
323
+ );
324
+ }
325
+ getDoc2(doc2(collection2(this.db, `${prefix}user`), _userId)).then(async (_doc2) => {
326
+ if (!this.db) {
327
+ console.error("Firestore\u304C\u521D\u671F\u5316\u3055\u308C\u3066\u3044\u307E\u305B\u3093");
328
+ throw new Error("Firestore\u304C\u521D\u671F\u5316\u3055\u308C\u3066\u3044\u307E\u305B\u3093");
329
+ }
330
+ this.userId = projectData.organizationId + "-" + _userId;
331
+ const userData = _doc2.data();
332
+ if (!_doc2.exists || !userData.organizationId || !userData.projectIds || !userData.type) {
333
+ await setDoc2(
334
+ doc2(
335
+ collection2(this.db, `${prefix}user`),
336
+ projectData.organizationId + "-" + _userId
337
+ ),
338
+ {
339
+ ...userMeta || {},
340
+ metaData,
341
+ id: projectData.organizationId + "-" + _userId,
342
+ originalUserId: _userId,
343
+ type: "customer",
344
+ organizationId: projectData.organizationId,
345
+ projectIds: [projectId],
346
+ createAt: /* @__PURE__ */ new Date(),
347
+ updateAt: /* @__PURE__ */ new Date(),
348
+ createdBy: _userId,
349
+ updatedBy: _userId,
350
+ hidden: false,
351
+ hiddenBy: ""
352
+ },
353
+ { merge: true }
354
+ ).catch((error) => {
355
+ console.error("Error creating document: ", error);
356
+ throw new Error("\u30E6\u30FC\u30B6\u30FC\u306E\u4F5C\u6210\u306B\u5931\u6557\u3057\u307E\u3057\u305F");
357
+ });
358
+ this.userData = _doc2.data();
359
+ } else {
360
+ this.userData = _doc2.data();
361
+ if (!this.userData?.projectIds?.includes(projectId)) {
362
+ await setDoc2(
363
+ doc2(
364
+ collection2(this.db, `${prefix}user`),
365
+ projectData.organizationId + "-" + _userId
366
+ ),
367
+ {
368
+ projectIds: [
369
+ ...this.userData?.projectIds || [],
370
+ projectId
371
+ ],
372
+ updateAt: /* @__PURE__ */ new Date(),
373
+ updatedBy: this.userId
374
+ },
375
+ { merge: true }
376
+ ).catch((error) => {
377
+ console.error("Error updating document: ", error);
378
+ throw new Error(
379
+ "\u30E6\u30FC\u30B6\u30FC\u306E\u30D7\u30ED\u30B8\u30A7\u30AF\u30C8ID\u306E\u66F4\u65B0\u306B\u5931\u6557\u3057\u307E\u3057\u305F"
380
+ );
381
+ });
382
+ }
383
+ if (this.userData?.organizationId !== projectData.organizationId) {
384
+ await setDoc2(
385
+ doc2(
386
+ collection2(this.db, `${prefix}user`),
387
+ projectData.organizationId + "-" + _userId
388
+ ),
389
+ {
390
+ organizationId: this.userData?.organizationId ? this.userData?.organizationId : projectData.organizationId,
391
+ updateAt: /* @__PURE__ */ new Date(),
392
+ updatedBy: this.userId
393
+ },
394
+ { merge: true }
395
+ ).catch((error) => {
396
+ console.error("Error updating document: ", error);
397
+ throw new Error("\u30E6\u30FC\u30B6\u30FC\u306E\u7D44\u7E54ID\u306E\u66F4\u65B0\u306B\u5931\u6557\u3057\u307E\u3057\u305F");
398
+ });
399
+ }
400
+ }
401
+ this.prefix = prefix;
402
+ this.projectId = projectId;
403
+ this.startRrwebRecordingForStore();
404
+ }).catch((error) => {
405
+ console.error("\u30E6\u30FC\u30B6\u30FC\u30C7\u30FC\u30BF\u306E\u53D6\u5F97\u30A8\u30E9\u30FC:", error);
406
+ throw new Error("\u30E6\u30FC\u30B6\u30FC\u30C7\u30FC\u30BF\u306E\u53D6\u5F97\u306B\u5931\u6557\u3057\u307E\u3057\u305F");
407
+ });
408
+ }).catch((error) => {
409
+ console.error("\u30D7\u30ED\u30B8\u30A7\u30AF\u30C8\u30C7\u30FC\u30BF\u306E\u53D6\u5F97\u30A8\u30E9\u30FC:", error);
410
+ throw new Error("\u30D7\u30ED\u30B8\u30A7\u30AF\u30C8\u30C7\u30FC\u30BF\u306E\u53D6\u5F97\u306B\u5931\u6557\u3057\u307E\u3057\u305F");
411
+ });
412
+ } catch (error) {
413
+ console.error("\u521D\u671F\u5316\u30A8\u30E9\u30FC:", error);
414
+ throw error;
301
415
  }
302
- const _usr = await getDoc2(
303
- doc2(collection2(this.db, `${prefix}user`), _userId)
304
- );
305
- this.userId = `${this.organizationId}-${_userId}`;
306
- this.prefix = prefix;
307
- this.projectId = projectId;
308
- this.startRrwebRecordingForStore();
309
- this.startConsoleRecording();
310
416
  }
311
- /** バッファ内イベントをまとめて Firestore に書き込む */
312
- flushBuffer() {
313
- if (!this.db || this.eventBuffer.length === 0) return;
314
- const batch = writeBatch(this.db);
315
- this.eventBuffer.forEach((rec) => {
316
- const ref = doc2(collection2(this.db, `${this.prefix}ActionRecord`));
317
- batch.set(ref, rec);
318
- });
319
- batch.commit().catch((e) => console.error("Batch commit error:", e));
320
- this.eventBuffer = [];
321
- }
322
- /** コンソール呼び出しを rrweb カスタムイベントとして記録 */
417
+ // コンソールログをキャプチャ
323
418
  startConsoleRecording() {
324
- const methods = ["log", "info", "warn", "error", "debug", "trace"];
325
- const original = {};
326
- methods.forEach((m) => {
327
- original[m] = console[m].bind(console);
328
- console[m] = (...args) => {
329
- original[m](...args);
330
- record.addCustomEvent("console", { method: m, args });
331
- this.updateActionRecordSession();
332
- };
333
- });
334
- }
335
- /** rrweb を使って画面操作をバッファ&バッチ保存 */
336
- startRrwebRecordingForStore() {
337
- if (this.stopFnForStore) return;
338
- const userId = this.userId || "unknown";
339
- const originalUserId = this.originalUserId || "";
340
- const sessionId = this.sessionId;
341
- const db2 = this.db;
342
- const prefix = this.prefix;
343
- setDoc2(doc2(collection2(db2, `${prefix}ActionRecordSession`), sessionId), {
344
- id: sessionId,
345
- startTime: /* @__PURE__ */ new Date(),
346
- endTime: null,
347
- userId,
348
- projectId: this.projectId,
349
- organizationId: this.projectData?.organizationId || null,
350
- createAt: /* @__PURE__ */ new Date(),
351
- updateAt: /* @__PURE__ */ new Date(),
352
- createdBy: userId,
353
- updatedBy: userId
354
- }).catch((e) => console.error(e));
355
- this.stopFnForStore = record({
356
- collectFonts: true,
357
- inlineImages: false,
358
- sampling: { canvas: 500, mousemove: 500, scroll: 500 },
359
- emit: (event) => {
360
- const rec = {
361
- id: doc2(collection2(db2, `${prefix}ActionRecord`)).id,
362
- timeStamp: /* @__PURE__ */ new Date(),
363
- userId,
364
- originalUserId,
365
- sessionId,
366
- type: "rrweb",
367
- rrwebRecord: JSON.stringify(event),
368
- createAt: /* @__PURE__ */ new Date(),
369
- updateAt: /* @__PURE__ */ new Date(),
370
- hidden: false,
371
- createdBy: userId,
372
- updatedBy: userId,
373
- hiddenBy: ""
419
+ try {
420
+ const originalConsole = { ...console };
421
+ const consoleMethods = [
422
+ "log",
423
+ "info",
424
+ "warn",
425
+ "error",
426
+ "debug",
427
+ "trace",
428
+ "assert",
429
+ "clear",
430
+ "context",
431
+ "count",
432
+ "countReset",
433
+ "createTask",
434
+ "debug",
435
+ "dir",
436
+ "dirxml",
437
+ "error",
438
+ "group",
439
+ "groupCollapsed",
440
+ "groupEnd",
441
+ "memory",
442
+ "profile",
443
+ "profileEnd",
444
+ "table",
445
+ "time",
446
+ "timeEnd",
447
+ "timeLog",
448
+ "timeStamp"
449
+ ];
450
+ const db2 = this.db;
451
+ const _updateActionRecordSession = () => this.updateActionRecordSession();
452
+ consoleMethods.forEach((method) => {
453
+ console[method] = (...args) => {
454
+ originalConsole[method](...args);
455
+ if (!db2) {
456
+ console.error("Firestore\u304C\u521D\u671F\u5316\u3055\u308C\u3066\u3044\u307E\u305B\u3093");
457
+ return;
458
+ }
459
+ const consoleEvent = {
460
+ type: "custom-event",
461
+ data: {
462
+ type: "console",
463
+ method,
464
+ args: args.map(
465
+ (arg) => typeof arg === "object" ? JSON.stringify(arg) : arg
466
+ )
467
+ },
468
+ timestamp: Date.now()
469
+ };
470
+ record.addCustomEvent("console", { method: "log", args });
471
+ _updateActionRecordSession();
374
472
  };
375
- this.eventBuffer.push(rec);
376
- setDoc2(
377
- doc2(collection2(db2, `${prefix}ActionRecordSession`), sessionId),
378
- { endTime: /* @__PURE__ */ new Date(), updateAt: /* @__PURE__ */ new Date(), updatedBy: userId },
379
- { merge: true }
380
- ).catch((e) => console.error(e));
381
- },
382
- recordCanvas: false
383
- });
384
- setInterval(() => {
385
- this.flushBuffer();
386
- }, 5e3);
387
- }
388
- /** 録画停止とバッファフラッシュ */
389
- stopRrwebRecordingForStore() {
390
- if (this.stopFnForStore) {
391
- this.stopFnForStore();
392
- this.stopFnForStore = null;
393
- this.flushBuffer();
473
+ });
474
+ } catch (error) {
475
+ console.error("\u30B3\u30F3\u30BD\u30FC\u30EB\u9332\u753B\u30A8\u30E9\u30FC:", error);
476
+ throw error;
394
477
  }
395
478
  }
396
- /** セッションの endTime を更新 */
397
- updateActionRecordSession() {
398
- if (!this.db || !this.sessionId || !this.userId) return;
399
- setDoc2(
400
- doc2(
401
- collection2(this.db, `${this.prefix}ActionRecordSession`),
402
- this.sessionId
403
- ),
404
- { endTime: /* @__PURE__ */ new Date(), updateAt: /* @__PURE__ */ new Date(), updatedBy: this.userId },
405
- { merge: true }
406
- ).catch((e) => console.error(e));
407
- }
408
479
  // タイムライン(ナビゲーションとパフォーマンス)をキャプチャ
409
480
  startTimelineRecording() {
410
481
  try {
@@ -494,6 +565,110 @@ var ActionLensRc = class {
494
565
  throw error;
495
566
  }
496
567
  }
568
+ startRrwebRecordingForStore() {
569
+ try {
570
+ if (this.stopFnForStore) return;
571
+ const _sessionId = this.sessionId;
572
+ const userId = this.userId || "unknown";
573
+ const originalUserId = this.originalUserId || "";
574
+ const db2 = this.db;
575
+ const prefix = this.prefix;
576
+ if (!db2) {
577
+ console.error("Firestore\u304C\u521D\u671F\u5316\u3055\u308C\u3066\u3044\u307E\u305B\u3093");
578
+ return;
579
+ }
580
+ const ActionRecordSessionRef = doc2(
581
+ collection2(db2, `${prefix}ActionRecordSession`),
582
+ _sessionId
583
+ );
584
+ setDoc2(ActionRecordSessionRef, {
585
+ id: _sessionId,
586
+ startTime: /* @__PURE__ */ new Date(),
587
+ endTime: null,
588
+ userId,
589
+ projectId: this.projectId || null,
590
+ organizationId: this.projectData?.organizationId || null,
591
+ createAt: /* @__PURE__ */ new Date(),
592
+ updateAt: /* @__PURE__ */ new Date(),
593
+ createdBy: userId,
594
+ updatedBy: userId
595
+ });
596
+ const _updateActionRecordSession = () => this.updateActionRecordSession();
597
+ this.stopFnForStore = record({
598
+ collectFonts: true,
599
+ inlineImages: true,
600
+ sampling: {
601
+ canvas: 50,
602
+ mousemove: true
603
+ },
604
+ emit(event) {
605
+ const newDocRef = doc2(collection2(db2, `${prefix}ActionRecord`));
606
+ const record2 = {
607
+ id: newDocRef.id,
608
+ timeStamp: /* @__PURE__ */ new Date(),
609
+ userId,
610
+ originalUserId,
611
+ type: "rrweb",
612
+ sessionId: _sessionId,
613
+ rrwebRecord: JSON.stringify(event),
614
+ createAt: /* @__PURE__ */ new Date(),
615
+ updateAt: /* @__PURE__ */ new Date(),
616
+ hidden: false,
617
+ createdBy: userId,
618
+ updatedBy: userId,
619
+ hiddenBy: ""
620
+ };
621
+ setDoc2(newDocRef, record2).catch((error) => {
622
+ console.error("Error saving rrweb event: ", error);
623
+ });
624
+ _updateActionRecordSession();
625
+ },
626
+ recordCanvas: false
627
+ });
628
+ } catch (error) {
629
+ console.error("rrweb\u9332\u753B\u30A8\u30E9\u30FC:", error);
630
+ throw error;
631
+ }
632
+ }
633
+ stopRrwebRecordingForStore() {
634
+ try {
635
+ if (this.stopFnForStore) {
636
+ this.stopFnForStore();
637
+ this.stopFnForStore = null;
638
+ }
639
+ } catch (error) {
640
+ console.error("rrweb\u9332\u753B\u505C\u6B62\u30A8\u30E9\u30FC:", error);
641
+ throw error;
642
+ }
643
+ }
644
+ updateActionRecordSession() {
645
+ try {
646
+ if (!this.db || !this.sessionId || !this.userId) {
647
+ console.error(
648
+ "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"
649
+ );
650
+ return;
651
+ }
652
+ const ActionRecordSessionRef = doc2(
653
+ collection2(this.db, `${this.prefix}ActionRecordSession`),
654
+ this.sessionId
655
+ );
656
+ setDoc2(
657
+ ActionRecordSessionRef,
658
+ {
659
+ endTime: /* @__PURE__ */ new Date(),
660
+ updateAt: /* @__PURE__ */ new Date(),
661
+ updatedBy: this.userId
662
+ },
663
+ { merge: true }
664
+ ).catch((error) => {
665
+ console.error("Error updating ActionRecordSession: ", error);
666
+ });
667
+ } catch (error) {
668
+ console.error("ActionRecordSession\u66F4\u65B0\u30A8\u30E9\u30FC:", error);
669
+ throw error;
670
+ }
671
+ }
497
672
  };
498
673
 
499
674
  // src/utils/date.ts