@leanbase-giangnd/js 0.2.4 → 0.3.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.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@leanbase-giangnd/js",
3
- "version": "0.2.4",
3
+ "version": "0.3.1",
4
4
  "description": "Leanbase browser SDK - event tracking, autocapture, and session replay",
5
5
  "repository": {
6
6
  "type": "git",
@@ -1,122 +1,13 @@
1
1
  /* eslint-disable @typescript-eslint/no-unused-vars */
2
2
  import { window as win } from '../../utils'
3
-
4
- // We avoid importing '@rrweb/record' at module load time to prevent IIFE builds
5
- // from requiring a top-level global. Instead, expose a lazy proxy that will
6
- // dynamically import the module the first time it's used.
7
-
8
- let _cachedRRWeb: any | null = null
9
-
10
- async function _loadRRWebModule(): Promise<any> {
11
- if (_cachedRRWeb) return _cachedRRWeb
12
- try {
13
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
14
- const mod: any = await import('@rrweb/record')
15
- _cachedRRWeb = mod
16
- return _cachedRRWeb
17
- } catch (e) {
18
- return null
19
- }
20
- }
21
-
22
- // queue for method calls before rrweb loads
23
- const _queuedCalls: Array<() => void> = []
24
-
25
- // Create a proxy function that delegates to the real rrweb.record when called
26
- const rrwebRecordProxy: any = function (...args: any[]) {
27
- let realStop: (() => void) | undefined
28
- let calledReal = false
29
-
30
- // Start loading asynchronously and call the real record when available
31
- void (async () => {
32
- const mod = await _loadRRWebModule()
33
- const real = mod && (mod.record ?? mod.default?.record)
34
- if (real) {
35
- try {
36
- calledReal = true
37
- realStop = real(...args)
38
- // flush any queued calls that were waiting for rrweb
39
- while (_queuedCalls.length) {
40
- try {
41
- const fn = _queuedCalls.shift()!
42
- fn()
43
- } catch (e) {
44
- // ignore
45
- }
46
- }
47
- } catch (e) {
48
- // ignore
49
- }
50
- }
51
- })()
52
-
53
- // return a stop function that will call the real stop when available
54
- return () => {
55
- if (realStop) {
56
- try {
57
- realStop()
58
- } catch (e) {
59
- // ignore
60
- }
61
- } else if (!calledReal) {
62
- // If rrweb hasn't been initialised yet, queue a stop request that will
63
- // call the real stop once available.
64
- _queuedCalls.push(() => {
65
- try {
66
- realStop?.()
67
- } catch (e) {
68
- // ignore
69
- }
70
- })
71
- }
72
- }
73
- }
74
-
75
- // methods that can be called on the rrweb.record object - queue until real module is available
76
- rrwebRecordProxy.addCustomEvent = function (tag?: string, payload?: any) {
77
- const call = () => {
78
- try {
79
- const real = _cachedRRWeb && (_cachedRRWeb.record ?? _cachedRRWeb.default?.record)
80
- real?.addCustomEvent?.(tag, payload)
81
- } catch (e) {
82
- // ignore
83
- }
84
- }
85
- if (_cachedRRWeb) call()
86
- else _queuedCalls.push(call)
87
- }
88
-
89
- rrwebRecordProxy.takeFullSnapshot = function () {
90
- const call = () => {
91
- try {
92
- const real = _cachedRRWeb && (_cachedRRWeb.record ?? _cachedRRWeb.default?.record)
93
- real?.takeFullSnapshot?.()
94
- } catch (e) {
95
- // ignore
96
- }
97
- }
98
- if (_cachedRRWeb) call()
99
- else _queuedCalls.push(call)
100
- }
101
- // Delay importing heavy modules to avoid circular dependencies at build time.
102
- // They will be required lazily when used at runtime.
103
- // We avoid requiring the lazy-loaded recorder here to prevent circular dependencies during bundling.
104
- // Instead, `LazyLoadedSessionRecording` will register a factory on the global under
105
- // `__PosthogExtensions__._initSessionRecordingFactory` when it loads.
106
3
  type InitSessionRecordingFactory = (instance: any) => any
107
4
 
108
- // Use a safe global target (prefer `win`, fallback to globalThis)
109
5
  const _target: any = (win as any) ?? (globalThis as any)
110
6
 
111
7
  _target.__PosthogExtensions__ = _target.__PosthogExtensions__ || {}
112
8
 
113
- // Expose rrweb.record under the same contract. We provide a lazy proxy so
114
- // builds that execute this file don't require rrweb at module evaluation time.
115
- _target.__PosthogExtensions__.rrweb = _target.__PosthogExtensions__.rrweb || {
116
- record: rrwebRecordProxy,
117
- }
9
+ _target.__PosthogExtensions__.rrweb = _target.__PosthogExtensions__.rrweb || {}
118
10
 
119
- // Provide initSessionRecording if not present — return a new LazyLoadedSessionRecording when called
120
11
  _target.__PosthogExtensions__.initSessionRecording =
121
12
  _target.__PosthogExtensions__.initSessionRecording ||
122
13
  ((instance: any) => {
@@ -125,20 +16,16 @@ _target.__PosthogExtensions__.initSessionRecording =
125
16
  if (factory) {
126
17
  return factory(instance)
127
18
  }
128
- // If no factory is registered yet, return undefined — callers should handle lazy-loading.
129
19
  return undefined
130
20
  })
131
21
 
132
- // Provide a no-op loadExternalDependency that calls the callback immediately (since rrweb is bundled)
133
22
  _target.__PosthogExtensions__.loadExternalDependency =
134
23
  _target.__PosthogExtensions__.loadExternalDependency ||
135
24
  ((instance: any, scriptName: string, cb?: (err?: any) => void) => {
136
25
  if (cb) cb(undefined)
137
26
  })
138
27
 
139
- // Provide rrwebPlugins object with network plugin factory if not present
140
28
  _target.__PosthogExtensions__.rrwebPlugins = _target.__PosthogExtensions__.rrwebPlugins || {}
141
- // Default to undefined; the lazy-loaded recorder will register the real factory when it initializes.
142
29
  _target.__PosthogExtensions__.rrwebPlugins.getRecordNetworkPlugin =
143
30
  _target.__PosthogExtensions__.rrwebPlugins.getRecordNetworkPlugin || (() => undefined)
144
31
 
@@ -318,7 +318,12 @@ export class LazyLoadedSessionRecording {
318
318
  * Util to help developers working on this feature manually override
319
319
  */
320
320
  private _forceAllowLocalhostNetworkCapture = false
321
+ // "Started" is only true once we have a valid rrweb stop handler AND we have marked recording enabled.
322
+ // If rrweb fails to initialize, we permanently disable replay for this page load.
323
+ private _recording: { stop: listenerHandler } | undefined
321
324
  private _stopRrweb: listenerHandler | undefined = undefined
325
+ private _permanentlyDisabled: boolean = false
326
+ private _loggedPermanentlyDisabled: boolean = false
322
327
  private _lastActivityTimestamp: number = Date.now()
323
328
  /**
324
329
  * if pageview capture is disabled,
@@ -357,6 +362,25 @@ export class LazyLoadedSessionRecording {
357
362
 
358
363
  private _removeEventTriggerCaptureHook: (() => void) | undefined = undefined
359
364
 
365
+ private _disablePermanently(reason: string, error?: unknown): void {
366
+ this._permanentlyDisabled = true
367
+ this._isFullyReady = false
368
+ this._mutationThrottler?.stop()
369
+ this._mutationThrottler = undefined
370
+ this._queuedRRWebEvents = []
371
+ this._recording = undefined
372
+ this._stopRrweb = undefined
373
+
374
+ if (!this._loggedPermanentlyDisabled) {
375
+ this._loggedPermanentlyDisabled = true
376
+ if (error) {
377
+ logger.error(`replay disabled: ${reason}`, error)
378
+ } else {
379
+ logger.error(`replay disabled: ${reason}`)
380
+ }
381
+ }
382
+ }
383
+
360
384
  private get _sessionManager() {
361
385
  if (!this._instance.sessionManager) {
362
386
  throw new Error(LOGGER_PREFIX + ' must be started with a valid sessionManager.')
@@ -579,6 +603,9 @@ export class LazyLoadedSessionRecording {
579
603
  }
580
604
 
581
605
  private _tryAddCustomEvent(tag: string, payload: any): boolean {
606
+ if (!this.isStarted || !this._recording) {
607
+ return false
608
+ }
582
609
  const rrwebRecord = getRRWebRecord()
583
610
  if (!rrwebRecord || typeof (rrwebRecord as any).addCustomEvent !== 'function') {
584
611
  return false
@@ -609,6 +636,10 @@ export class LazyLoadedSessionRecording {
609
636
  }
610
637
 
611
638
  private _processQueuedEvents() {
639
+ if (!this.isStarted || !this._recording) {
640
+ this._queuedRRWebEvents = []
641
+ return
642
+ }
612
643
  if (this._queuedRRWebEvents.length) {
613
644
  // if rrweb isn't ready to accept events earlier, then we queued them up.
614
645
  // now that `emit` has been called rrweb should be ready to accept them.
@@ -631,6 +662,9 @@ export class LazyLoadedSessionRecording {
631
662
  }
632
663
 
633
664
  private _tryTakeFullSnapshot(): boolean {
665
+ if (!this.isStarted || !this._recording) {
666
+ return false
667
+ }
634
668
  const rrwebRecord = getRRWebRecord()
635
669
  if (!rrwebRecord || typeof (rrwebRecord as any).takeFullSnapshot !== 'function') {
636
670
  return false
@@ -651,6 +685,9 @@ export class LazyLoadedSessionRecording {
651
685
  }
652
686
 
653
687
  private _scheduleFullSnapshot(): void {
688
+ if (!this.isStarted || !this._recording) {
689
+ return
690
+ }
654
691
  if (this._fullSnapshotTimer) {
655
692
  clearInterval(this._fullSnapshotTimer)
656
693
  }
@@ -670,6 +707,9 @@ export class LazyLoadedSessionRecording {
670
707
  }
671
708
 
672
709
  private _pauseRecording() {
710
+ if (!this.isStarted || !this._recording) {
711
+ return
712
+ }
673
713
  // we check _urlBlocked not status, since more than one thing can affect status
674
714
  if (this._urlTriggerMatching.urlBlocked) {
675
715
  return
@@ -689,6 +729,9 @@ export class LazyLoadedSessionRecording {
689
729
  }
690
730
 
691
731
  private _resumeRecording() {
732
+ if (!this.isStarted || !this._recording) {
733
+ return
734
+ }
692
735
  // we check _urlBlocked not status, since more than one thing can affect status
693
736
  if (!this._urlTriggerMatching.urlBlocked) {
694
737
  return
@@ -704,6 +747,9 @@ export class LazyLoadedSessionRecording {
704
747
  }
705
748
 
706
749
  private _activateTrigger(triggerType: TriggerType) {
750
+ if (!this.isStarted || !this._recording || !this._isFullyReady) {
751
+ return
752
+ }
707
753
  if (this._triggerMatching.triggerStatus(this.sessionId) === TRIGGER_PENDING) {
708
754
  // status is stored separately for URL and event triggers
709
755
  this._instance?.persistence?.register({
@@ -718,7 +764,7 @@ export class LazyLoadedSessionRecording {
718
764
  }
719
765
 
720
766
  get isStarted(): boolean {
721
- return !!this._stopRrweb
767
+ return !!this._recording?.stop
722
768
  }
723
769
 
724
770
  get _remoteConfig(): SessionRecordingPersistedConfig | undefined {
@@ -731,6 +777,9 @@ export class LazyLoadedSessionRecording {
731
777
  }
732
778
 
733
779
  async start(startReason?: SessionStartReason) {
780
+ if (this._permanentlyDisabled) {
781
+ return
782
+ }
734
783
  this._isFullyReady = false
735
784
  const config = this._remoteConfig
736
785
  if (!config) {
@@ -761,9 +810,17 @@ export class LazyLoadedSessionRecording {
761
810
  this._urlTriggerMatching.onConfig(config)
762
811
 
763
812
  this._eventTriggerMatching.onConfig(config)
764
- this._removeEventTriggerCaptureHook?.()
765
- this._addEventTriggerListener()
766
813
 
814
+ // Start rrweb first; only once we have a valid recorder do we install any listeners/timers.
815
+ await this._startRecorder()
816
+
817
+ // If rrweb failed to load/start, do not proceed further.
818
+ // This prevents installing listeners that assume rrweb is active.
819
+ if (!this.isStarted) {
820
+ return
821
+ }
822
+
823
+ // Now that rrweb has started, we can safely install replay side-effects.
767
824
  this._linkedFlagMatching.onConfig(config, (flag, variant) => {
768
825
  this._reportStarted('linked_flag_matched', {
769
826
  flag,
@@ -772,13 +829,8 @@ export class LazyLoadedSessionRecording {
772
829
  })
773
830
 
774
831
  this._makeSamplingDecision(this.sessionId)
775
- await this._startRecorder()
776
-
777
- // If rrweb failed to load/start, do not proceed further.
778
- // This prevents installing listeners that assume rrweb is active.
779
- if (!this.isStarted) {
780
- return
781
- }
832
+ this._removeEventTriggerCaptureHook?.()
833
+ this._addEventTriggerListener()
782
834
 
783
835
  // Only start processing rrweb emits once the ingestion endpoint is available.
784
836
  // If it isn't available, we must degrade to a no-op (never crash the host app).
@@ -886,9 +938,9 @@ export class LazyLoadedSessionRecording {
886
938
  // Clear any queued rrweb events to prevent memory leaks from closures
887
939
  this._queuedRRWebEvents = []
888
940
 
889
- this._stopRrweb?.()
941
+ this._recording?.stop?.()
942
+ this._recording = undefined
890
943
  this._stopRrweb = undefined
891
-
892
944
  this._isFullyReady = false
893
945
 
894
946
  logger.info('stopped')
@@ -911,8 +963,13 @@ export class LazyLoadedSessionRecording {
911
963
  }
912
964
 
913
965
  onRRwebEmit(rawEvent: eventWithTime) {
966
+ // First-line invariant gate: drop everything unless replay is truly started.
967
+ if (!this.isStarted || !this._recording) {
968
+ return
969
+ }
970
+
914
971
  // Never process rrweb emits until we're fully ready.
915
- if (!this._isFullyReady || !this.isStarted) {
972
+ if (!this._isFullyReady) {
916
973
  return
917
974
  }
918
975
 
@@ -1046,6 +1103,9 @@ export class LazyLoadedSessionRecording {
1046
1103
  }
1047
1104
 
1048
1105
  public overrideLinkedFlag() {
1106
+ if (!this.isStarted || !this._recording || !this._isFullyReady) {
1107
+ return
1108
+ }
1049
1109
  this._linkedFlagMatching.linkedFlagSeen = true
1050
1110
  this._tryTakeFullSnapshot()
1051
1111
  this._reportStarted('linked_flag_overridden')
@@ -1058,6 +1118,9 @@ export class LazyLoadedSessionRecording {
1058
1118
  * instead call `posthog.startSessionRecording({sampling: true})`
1059
1119
  * */
1060
1120
  public overrideSampling() {
1121
+ if (!this.isStarted || !this._recording || !this._isFullyReady) {
1122
+ return
1123
+ }
1061
1124
  this._instance.persistence?.register({
1062
1125
  // short-circuits the `makeSamplingDecision` function in the session recording module
1063
1126
  [SESSION_RECORDING_IS_SAMPLED]: this.sessionId,
@@ -1073,6 +1136,9 @@ export class LazyLoadedSessionRecording {
1073
1136
  * instead call `posthog.startSessionRecording({trigger: 'url' | 'event'})`
1074
1137
  * */
1075
1138
  public overrideTrigger(triggerType: TriggerType) {
1139
+ if (!this.isStarted || !this._recording || !this._isFullyReady) {
1140
+ return
1141
+ }
1076
1142
  this._activateTrigger(triggerType)
1077
1143
  }
1078
1144
 
@@ -1243,6 +1309,9 @@ export class LazyLoadedSessionRecording {
1243
1309
  }
1244
1310
 
1245
1311
  private _reportStarted(startReason: SessionStartReason, tagPayload?: Record<string, any>) {
1312
+ if (!this.isStarted || !this._recording) {
1313
+ return
1314
+ }
1246
1315
  this._instance.registerForSession({
1247
1316
  $session_recording_start_reason: startReason,
1248
1317
  })
@@ -1416,7 +1485,7 @@ export class LazyLoadedSessionRecording {
1416
1485
  }
1417
1486
 
1418
1487
  private async _startRecorder() {
1419
- if (this._stopRrweb) {
1488
+ if (this._permanentlyDisabled || this._recording) {
1420
1489
  return
1421
1490
  }
1422
1491
 
@@ -1474,46 +1543,56 @@ export class LazyLoadedSessionRecording {
1474
1543
  }
1475
1544
 
1476
1545
  if (!rrwebRecord) {
1477
- logger.error(
1478
- '_startRecorder was called but rrwebRecord is not available. This indicates something has gone wrong.'
1479
- )
1546
+ this._disablePermanently('rrweb record function unavailable')
1480
1547
  return
1481
1548
  }
1482
1549
 
1483
- this._mutationThrottler =
1484
- this._mutationThrottler ??
1485
- new MutationThrottler(rrwebRecord, {
1486
- refillRate: this._instance.config.session_recording?.__mutationThrottlerRefillRate,
1487
- bucketSize: this._instance.config.session_recording?.__mutationThrottlerBucketSize,
1488
- onBlockedNode: (id, node) => {
1489
- const message = `Too many mutations on node '${id}'. Rate limiting. This could be due to SVG animations or something similar`
1490
- logger.info(message, {
1491
- node: node,
1492
- })
1493
-
1494
- this.log(LOGGER_PREFIX + ' ' + message, 'warn')
1495
- },
1496
- })
1497
-
1498
1550
  const activePlugins = this._gatherRRWebPlugins()
1551
+
1552
+ let stopHandler: listenerHandler | undefined
1499
1553
  try {
1500
- this._stopRrweb = rrwebRecord({
1554
+ stopHandler = rrwebRecord({
1501
1555
  emit: (event) => {
1502
1556
  try {
1503
1557
  this.onRRwebEmit(event)
1504
1558
  } catch (e) {
1559
+ // never throw from rrweb emit handler
1505
1560
  logger.error('error in rrweb emit handler', e)
1506
1561
  }
1507
1562
  },
1508
1563
  plugins: activePlugins,
1509
1564
  ...sessionRecordingOptions,
1510
- })
1565
+ }) as unknown as listenerHandler
1511
1566
  } catch (e) {
1512
- logger.error('failed to start rrweb recorder', e)
1513
- this._stopRrweb = undefined
1567
+ this._disablePermanently('rrweb recorder threw during initialization', e)
1568
+ return
1569
+ }
1570
+
1571
+ if (typeof stopHandler !== 'function') {
1572
+ this._disablePermanently('rrweb recorder returned an invalid stop handler')
1514
1573
  return
1515
1574
  }
1516
1575
 
1576
+ // Mark replay started only after rrweb has successfully returned a valid stop handler.
1577
+ this._recording = { stop: stopHandler }
1578
+ this._stopRrweb = stopHandler
1579
+
1580
+ // Only create mutation throttler once replay is truly started.
1581
+ this._mutationThrottler =
1582
+ this._mutationThrottler ??
1583
+ new MutationThrottler(rrwebRecord, {
1584
+ refillRate: this._instance.config.session_recording?.__mutationThrottlerRefillRate,
1585
+ bucketSize: this._instance.config.session_recording?.__mutationThrottlerBucketSize,
1586
+ onBlockedNode: (id, node) => {
1587
+ const message = `Too many mutations on node '${id}'. Rate limiting. This could be due to SVG animations or something similar`
1588
+ logger.info(message, {
1589
+ node: node,
1590
+ })
1591
+
1592
+ this.log(LOGGER_PREFIX + ' ' + message, 'warn')
1593
+ },
1594
+ })
1595
+
1517
1596
  // We reset the last activity timestamp, resetting the idle timer
1518
1597
  this._lastActivityTimestamp = Date.now()
1519
1598
  // stay unknown if we're not sure if we're idle or not
@@ -16,11 +16,8 @@ export class MutationThrottler {
16
16
  onBlockedNode?: (id: number, node: Node | null) => void
17
17
  } = {}
18
18
  ) {
19
- const configuredBucketSize = this._options.bucketSize ?? 100
20
- const effectiveBucketSize = Math.max(configuredBucketSize - 1, 1)
21
-
22
19
  this._rateLimiter = new BucketedRateLimiter({
23
- bucketSize: effectiveBucketSize,
20
+ bucketSize: this._options.bucketSize ?? 100,
24
21
  refillRate: this._options.refillRate ?? 10,
25
22
  refillInterval: 1000, // one second
26
23
  _onBucketRateLimited: this._onNodeRateLimited,
@@ -21,7 +21,6 @@ export class SessionRecording {
21
21
  _forceAllowLocalhostNetworkCapture: boolean = false
22
22
 
23
23
  private _receivedFlags: boolean = false
24
- private _serverRecordingEnabled: boolean = false
25
24
 
26
25
  private _persistFlagsOnSessionListener: (() => void) | undefined = undefined
27
26
  private _lazyLoadedSessionRecording: LazyLoadedSessionRecording | undefined
@@ -30,10 +29,6 @@ export class SessionRecording {
30
29
  return !!this._lazyLoadedSessionRecording?.isStarted
31
30
  }
32
31
 
33
- /**
34
- * defaults to buffering mode until a flags response is received
35
- * once a flags response is received status can be disabled, active or sampled
36
- */
37
32
  get status(): SessionRecordingStatus {
38
33
  if (this._lazyLoadedSessionRecording) {
39
34
  return this._lazyLoadedSessionRecording.status
@@ -72,28 +67,16 @@ export class SessionRecording {
72
67
  const canRunReplay = !isUndefined(Object.assign) && !isUndefined(Array.from)
73
68
  if (this._isRecordingEnabled && canRunReplay) {
74
69
  this._lazyLoadAndStart(startReason)
75
- log.info('starting')
76
70
  } else {
77
71
  this.stopRecording()
78
72
  }
79
73
  }
80
74
 
81
- /**
82
- * session recording waits until it receives remote config before loading the script
83
- * this is to ensure we can control the script name remotely
84
- * and because we wait until we have local and remote config to determine if we should start at all
85
- * if start is called and there is no remote config then we wait until there is
86
- */
87
75
  private _lazyLoadAndStart(startReason?: SessionStartReason) {
88
- // by checking `_isRecordingEnabled` here we know that
89
- // we have stored remote config and client config to read
90
- // replay waits for both local and remote config before starting
91
76
  if (!this._isRecordingEnabled) {
92
77
  return
93
78
  }
94
79
 
95
- // If extensions provide a loader, use it. Otherwise fallback to the local _onScriptLoaded which
96
- // will create the local LazyLoadedSessionRecording (so tests that mock it work correctly).
97
80
  const loader = assignableWindow.__PosthogExtensions__?.loadExternalDependency
98
81
  if (typeof loader === 'function') {
99
82
  loader(this._instance, this._scriptName as any, (err: any) => {
@@ -162,18 +145,11 @@ export class SessionRecording {
162
145
 
163
146
  persistResponse()
164
147
 
165
- // in case we see multiple flags responses, we should only use the response from the most recent one
166
148
  this._persistFlagsOnSessionListener?.()
167
- // we 100% know there is a session manager by this point
168
149
  this._persistFlagsOnSessionListener = this._instance.sessionManager?.onSessionId(persistResponse)
169
150
  }
170
151
  }
171
152
 
172
- private _clearRemoteConfig() {
173
- this._instance.persistence?.unregister(SESSION_RECORDING_REMOTE_CONFIG)
174
- this._resetSampling()
175
- }
176
-
177
153
  onRemoteConfig(response: RemoteConfig) {
178
154
  if (!('sessionRecording' in response)) {
179
155
  // if sessionRecording is not in the response, we do nothing
@@ -183,13 +159,9 @@ export class SessionRecording {
183
159
  this._receivedFlags = true
184
160
 
185
161
  if (response.sessionRecording === false) {
186
- this._serverRecordingEnabled = false
187
- this._clearRemoteConfig()
188
- this.stopRecording()
189
162
  return
190
163
  }
191
164
 
192
- this._serverRecordingEnabled = true
193
165
  this._persistRemoteConfig(response)
194
166
  this.startIfEnabledOrStop()
195
167
  }
@@ -264,44 +236,21 @@ export class SessionRecording {
264
236
  this._lazyLoadedSessionRecording?.onRRwebEmit?.(rawEvent)
265
237
  }
266
238
 
267
- /**
268
- * this ignores the linked flag config and (if other conditions are met) causes capture to start
269
- *
270
- * It is not usual to call this directly,
271
- * instead call `posthog.startSessionRecording({linked_flag: true})`
272
- * */
273
239
  public overrideLinkedFlag() {
274
240
  // TODO what if this gets called before lazy loading is done
275
241
  this._lazyLoadedSessionRecording?.overrideLinkedFlag()
276
242
  }
277
243
 
278
- /**
279
- * this ignores the sampling config and (if other conditions are met) causes capture to start
280
- *
281
- * It is not usual to call this directly,
282
- * instead call `posthog.startSessionRecording({sampling: true})`
283
- * */
284
244
  public overrideSampling() {
285
245
  // TODO what if this gets called before lazy loading is done
286
246
  this._lazyLoadedSessionRecording?.overrideSampling()
287
247
  }
288
248
 
289
- /**
290
- * this ignores the URL/Event trigger config and (if other conditions are met) causes capture to start
291
- *
292
- * It is not usual to call this directly,
293
- * instead call `posthog.startSessionRecording({trigger: 'url' | 'event'})`
294
- * */
295
249
  public overrideTrigger(triggerType: TriggerType) {
296
250
  // TODO what if this gets called before lazy loading is done
297
251
  this._lazyLoadedSessionRecording?.overrideTrigger(triggerType)
298
252
  }
299
253
 
300
- /*
301
- * whenever we capture an event, we add these properties to the event
302
- * these are used to debug issues with the session recording
303
- * when looking at the event feed for a session
304
- */
305
254
  get sdkDebugProperties(): Properties {
306
255
  return (
307
256
  this._lazyLoadedSessionRecording?.sdkDebugProperties || {
@@ -310,14 +259,6 @@ export class SessionRecording {
310
259
  )
311
260
  }
312
261
 
313
- /**
314
- * This adds a custom event to the session recording
315
- *
316
- * It is not intended for arbitrary public use - playback only displays known custom events
317
- * And is exposed on the public interface only so that other parts of the SDK are able to use it
318
- *
319
- * if you are calling this from client code, you're probably looking for `posthog.capture('$custom_event', {...})`
320
- */
321
262
  tryAddCustomEvent(tag: string, payload: any): boolean {
322
263
  return !!this._lazyLoadedSessionRecording?.tryAddCustomEvent(tag, payload)
323
264
  }
package/src/version.ts CHANGED
@@ -1 +1 @@
1
- export const version = '0.2.4'
1
+ export const version = '0.3.1'