action-lens 1.0.17 → 1.0.19

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,214 @@ 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
+ this.startConsoleRecording();
405
+ }).catch((error) => {
406
+ console.error("\u30E6\u30FC\u30B6\u30FC\u30C7\u30FC\u30BF\u306E\u53D6\u5F97\u30A8\u30E9\u30FC:", error);
407
+ throw new Error("\u30E6\u30FC\u30B6\u30FC\u30C7\u30FC\u30BF\u306E\u53D6\u5F97\u306B\u5931\u6557\u3057\u307E\u3057\u305F");
408
+ });
409
+ }).catch((error) => {
410
+ console.error("\u30D7\u30ED\u30B8\u30A7\u30AF\u30C8\u30C7\u30FC\u30BF\u306E\u53D6\u5F97\u30A8\u30E9\u30FC:", error);
411
+ throw new Error("\u30D7\u30ED\u30B8\u30A7\u30AF\u30C8\u30C7\u30FC\u30BF\u306E\u53D6\u5F97\u306B\u5931\u6557\u3057\u307E\u3057\u305F");
412
+ });
413
+ } catch (error) {
414
+ console.error("\u521D\u671F\u5316\u30A8\u30E9\u30FC:", error);
415
+ throw error;
301
416
  }
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
417
  }
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 カスタムイベントとして記録 */
418
+ // コンソールログをキャプチャ
323
419
  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: ""
420
+ try {
421
+ const originalConsole = { ...console };
422
+ const consoleMethods = [
423
+ "log",
424
+ "info",
425
+ "warn",
426
+ "error",
427
+ "debug",
428
+ "trace",
429
+ "assert",
430
+ "clear",
431
+ "context",
432
+ "count",
433
+ "countReset",
434
+ "createTask",
435
+ "debug",
436
+ "dir",
437
+ "dirxml",
438
+ "error",
439
+ "group",
440
+ "groupCollapsed",
441
+ "groupEnd",
442
+ "memory",
443
+ "profile",
444
+ "profileEnd",
445
+ "table",
446
+ "time",
447
+ "timeEnd",
448
+ "timeLog",
449
+ "timeStamp"
450
+ ];
451
+ const db2 = this.db;
452
+ const _updateActionRecordSession = () => this.updateActionRecordSession();
453
+ consoleMethods.forEach((method) => {
454
+ console[method] = (...args) => {
455
+ originalConsole[method](...args);
456
+ if (!db2) {
457
+ console.error("Firestore\u304C\u521D\u671F\u5316\u3055\u308C\u3066\u3044\u307E\u305B\u3093");
458
+ return;
459
+ }
460
+ const consoleEvent = {
461
+ type: "custom-event",
462
+ data: {
463
+ type: "console",
464
+ method,
465
+ args: args.map(
466
+ (arg) => typeof arg === "object" ? JSON.stringify(arg) : arg
467
+ )
468
+ },
469
+ timestamp: Date.now()
470
+ };
471
+ record.addCustomEvent("console", { method: "log", args });
472
+ _updateActionRecordSession();
374
473
  };
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();
474
+ });
475
+ } catch (error) {
476
+ console.error("\u30B3\u30F3\u30BD\u30FC\u30EB\u9332\u753B\u30A8\u30E9\u30FC:", error);
477
+ throw error;
394
478
  }
395
479
  }
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
480
  // タイムライン(ナビゲーションとパフォーマンス)をキャプチャ
409
481
  startTimelineRecording() {
410
482
  try {
@@ -494,6 +566,110 @@ var ActionLensRc = class {
494
566
  throw error;
495
567
  }
496
568
  }
569
+ startRrwebRecordingForStore() {
570
+ try {
571
+ if (this.stopFnForStore) return;
572
+ const _sessionId = this.sessionId;
573
+ const userId = this.userId || "unknown";
574
+ const originalUserId = this.originalUserId || "";
575
+ const db2 = this.db;
576
+ const prefix = this.prefix;
577
+ if (!db2) {
578
+ console.error("Firestore\u304C\u521D\u671F\u5316\u3055\u308C\u3066\u3044\u307E\u305B\u3093");
579
+ return;
580
+ }
581
+ const ActionRecordSessionRef = doc2(
582
+ collection2(db2, `${prefix}ActionRecordSession`),
583
+ _sessionId
584
+ );
585
+ setDoc2(ActionRecordSessionRef, {
586
+ id: _sessionId,
587
+ startTime: /* @__PURE__ */ new Date(),
588
+ endTime: null,
589
+ userId,
590
+ projectId: this.projectId || null,
591
+ organizationId: this.projectData?.organizationId || null,
592
+ createAt: /* @__PURE__ */ new Date(),
593
+ updateAt: /* @__PURE__ */ new Date(),
594
+ createdBy: userId,
595
+ updatedBy: userId
596
+ });
597
+ const _updateActionRecordSession = () => this.updateActionRecordSession();
598
+ this.stopFnForStore = record({
599
+ collectFonts: true,
600
+ inlineImages: true,
601
+ sampling: {
602
+ canvas: 50,
603
+ mousemove: true
604
+ },
605
+ emit(event) {
606
+ const newDocRef = doc2(collection2(db2, `${prefix}ActionRecord`));
607
+ const record2 = {
608
+ id: newDocRef.id,
609
+ timeStamp: /* @__PURE__ */ new Date(),
610
+ userId,
611
+ originalUserId,
612
+ type: "rrweb",
613
+ sessionId: _sessionId,
614
+ rrwebRecord: JSON.stringify(event),
615
+ createAt: /* @__PURE__ */ new Date(),
616
+ updateAt: /* @__PURE__ */ new Date(),
617
+ hidden: false,
618
+ createdBy: userId,
619
+ updatedBy: userId,
620
+ hiddenBy: ""
621
+ };
622
+ setDoc2(newDocRef, record2).catch((error) => {
623
+ console.error("Error saving rrweb event: ", error);
624
+ });
625
+ _updateActionRecordSession();
626
+ },
627
+ recordCanvas: false
628
+ });
629
+ } catch (error) {
630
+ console.error("rrweb\u9332\u753B\u30A8\u30E9\u30FC:", error);
631
+ throw error;
632
+ }
633
+ }
634
+ stopRrwebRecordingForStore() {
635
+ try {
636
+ if (this.stopFnForStore) {
637
+ this.stopFnForStore();
638
+ this.stopFnForStore = null;
639
+ }
640
+ } catch (error) {
641
+ console.error("rrweb\u9332\u753B\u505C\u6B62\u30A8\u30E9\u30FC:", error);
642
+ throw error;
643
+ }
644
+ }
645
+ updateActionRecordSession() {
646
+ try {
647
+ if (!this.db || !this.sessionId || !this.userId) {
648
+ console.error(
649
+ "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"
650
+ );
651
+ return;
652
+ }
653
+ const ActionRecordSessionRef = doc2(
654
+ collection2(this.db, `${this.prefix}ActionRecordSession`),
655
+ this.sessionId
656
+ );
657
+ setDoc2(
658
+ ActionRecordSessionRef,
659
+ {
660
+ endTime: /* @__PURE__ */ new Date(),
661
+ updateAt: /* @__PURE__ */ new Date(),
662
+ updatedBy: this.userId
663
+ },
664
+ { merge: true }
665
+ ).catch((error) => {
666
+ console.error("Error updating ActionRecordSession: ", error);
667
+ });
668
+ } catch (error) {
669
+ console.error("ActionRecordSession\u66F4\u65B0\u30A8\u30E9\u30FC:", error);
670
+ throw error;
671
+ }
672
+ }
497
673
  };
498
674
 
499
675
  // src/utils/date.ts