@leanbase-giangnd/js 0.3.2 → 0.4.0
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.cjs +788 -85
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.ts +1 -0
- package/dist/index.mjs +789 -86
- package/dist/index.mjs.map +1 -1
- package/dist/leanbase.iife.js +2529 -510
- package/dist/leanbase.iife.js.map +1 -1
- package/package.json +2 -1
- package/src/extensions/replay/external/lazy-loaded-session-recorder.ts +89 -15
- package/src/extensions/replay/session-recording.ts +9 -6
- package/src/version.ts +1 -1
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@leanbase-giangnd/js",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.4.0",
|
|
4
4
|
"description": "Leanbase browser SDK - event tracking, autocapture, and session replay",
|
|
5
5
|
"repository": {
|
|
6
6
|
"type": "git",
|
|
@@ -35,6 +35,7 @@
|
|
|
35
35
|
"dependencies": {
|
|
36
36
|
"@posthog/core": "workspace:*",
|
|
37
37
|
"@rrweb/record": "2.0.0-alpha.17",
|
|
38
|
+
"@rrweb/rrweb-plugin-console-record": "2.0.0-alpha.17",
|
|
38
39
|
"fflate": "^0.4.8"
|
|
39
40
|
},
|
|
40
41
|
"devDependencies": {
|
|
@@ -318,6 +318,11 @@ export class LazyLoadedSessionRecording {
|
|
|
318
318
|
* Util to help developers working on this feature manually override
|
|
319
319
|
*/
|
|
320
320
|
private _forceAllowLocalhostNetworkCapture = false
|
|
321
|
+
private _debug(...args: any[]) {
|
|
322
|
+
if (this._instance?.config?.debug) {
|
|
323
|
+
logger.info(...args)
|
|
324
|
+
}
|
|
325
|
+
}
|
|
321
326
|
// "Started" is only true once we have a valid rrweb stop handler AND we have marked recording enabled.
|
|
322
327
|
// If rrweb fails to initialize, we permanently disable replay for this page load.
|
|
323
328
|
private _recording: { stop: listenerHandler } | undefined
|
|
@@ -537,31 +542,84 @@ export class LazyLoadedSessionRecording {
|
|
|
537
542
|
}
|
|
538
543
|
}
|
|
539
544
|
|
|
540
|
-
private
|
|
545
|
+
private async _loadConsolePlugin(): Promise<RecordPlugin | null> {
|
|
546
|
+
try {
|
|
547
|
+
const mod: any = await import('@rrweb/rrweb-plugin-console-record')
|
|
548
|
+
const factory = mod?.getRecordConsolePlugin ?? mod?.default?.getRecordConsolePlugin
|
|
549
|
+
|
|
550
|
+
if (typeof factory === 'function') {
|
|
551
|
+
const plugin = factory()
|
|
552
|
+
this._debug('Console plugin loaded')
|
|
553
|
+
return plugin
|
|
554
|
+
}
|
|
555
|
+
|
|
556
|
+
logger.warn('console plugin factory unavailable after import')
|
|
557
|
+
} catch (e) {
|
|
558
|
+
logger.warn('could not load console plugin', e)
|
|
559
|
+
}
|
|
560
|
+
|
|
561
|
+
return null
|
|
562
|
+
}
|
|
563
|
+
|
|
564
|
+
private async _loadNetworkPlugin(
|
|
565
|
+
networkPayloadCapture: Pick<
|
|
566
|
+
NetworkRecordOptions,
|
|
567
|
+
'recordHeaders' | 'recordBody' | 'recordPerformance' | 'payloadHostDenyList'
|
|
568
|
+
>
|
|
569
|
+
): Promise<RecordPlugin | null> {
|
|
570
|
+
try {
|
|
571
|
+
const mod: any = await import('./network-plugin')
|
|
572
|
+
const factory = mod?.getRecordNetworkPlugin ?? mod?.default?.getRecordNetworkPlugin
|
|
573
|
+
|
|
574
|
+
if (typeof factory === 'function') {
|
|
575
|
+
const options = buildNetworkRequestOptions(this._instance.config, networkPayloadCapture)
|
|
576
|
+
const plugin = factory(options)
|
|
577
|
+
this._debug('Network plugin loaded')
|
|
578
|
+
return plugin
|
|
579
|
+
}
|
|
580
|
+
|
|
581
|
+
logger.warn('network plugin factory unavailable after import')
|
|
582
|
+
} catch (e) {
|
|
583
|
+
logger.warn('could not load network plugin', e)
|
|
584
|
+
}
|
|
585
|
+
|
|
586
|
+
return null
|
|
587
|
+
}
|
|
588
|
+
|
|
589
|
+
private async _gatherRRWebPlugins(): Promise<RecordPlugin[]> {
|
|
541
590
|
const plugins: RecordPlugin[] = []
|
|
542
591
|
|
|
592
|
+
if (!window) {
|
|
593
|
+
return plugins
|
|
594
|
+
}
|
|
595
|
+
|
|
543
596
|
if (this._isConsoleLogCaptureEnabled) {
|
|
544
|
-
|
|
597
|
+
const consolePlugin = await this._loadConsolePlugin()
|
|
598
|
+
if (consolePlugin) {
|
|
599
|
+
plugins.push(consolePlugin)
|
|
600
|
+
}
|
|
545
601
|
}
|
|
546
602
|
|
|
547
603
|
if (this._networkPayloadCapture) {
|
|
548
604
|
const canRecordNetwork = !isLocalhost() || this._forceAllowLocalhostNetworkCapture
|
|
549
605
|
|
|
550
606
|
if (canRecordNetwork) {
|
|
551
|
-
const
|
|
552
|
-
|
|
553
|
-
|
|
554
|
-
plugins.push(
|
|
555
|
-
networkFactory(buildNetworkRequestOptions(this._instance.config, this._networkPayloadCapture))
|
|
556
|
-
)
|
|
557
|
-
} else {
|
|
558
|
-
logger.info('Network plugin factory not available yet; skipping network plugin')
|
|
607
|
+
const networkPlugin = await this._loadNetworkPlugin(this._networkPayloadCapture)
|
|
608
|
+
if (networkPlugin) {
|
|
609
|
+
plugins.push(networkPlugin)
|
|
559
610
|
}
|
|
560
611
|
} else {
|
|
561
|
-
|
|
612
|
+
this._debug('NetworkCapture not started because we are on localhost.')
|
|
562
613
|
}
|
|
563
614
|
}
|
|
564
615
|
|
|
616
|
+
if (plugins.length > 0) {
|
|
617
|
+
this._debug(
|
|
618
|
+
'Replay plugins loaded',
|
|
619
|
+
plugins.map((p) => p.name)
|
|
620
|
+
)
|
|
621
|
+
}
|
|
622
|
+
|
|
565
623
|
return plugins
|
|
566
624
|
}
|
|
567
625
|
|
|
@@ -956,13 +1014,29 @@ export class LazyLoadedSessionRecording {
|
|
|
956
1014
|
|
|
957
1015
|
private _snapshotIngestionUrl(): string | null {
|
|
958
1016
|
const endpointFor = (this._instance as any)?.requestRouter?.endpointFor
|
|
959
|
-
|
|
1017
|
+
|
|
1018
|
+
// Prefer requestRouter (parity with Browser SDK)
|
|
1019
|
+
if (typeof endpointFor === 'function') {
|
|
1020
|
+
try {
|
|
1021
|
+
return endpointFor('api', this._endpoint)
|
|
1022
|
+
} catch {
|
|
1023
|
+
return null
|
|
1024
|
+
}
|
|
1025
|
+
}
|
|
1026
|
+
|
|
1027
|
+
// Fallback: construct from host/api_host if requestRouter is unavailable (older IIFE builds)
|
|
1028
|
+
const host = (this._instance.config.api_host || this._instance.config.host || '').trim()
|
|
1029
|
+
if (!host) {
|
|
960
1030
|
return null
|
|
961
1031
|
}
|
|
1032
|
+
|
|
962
1033
|
try {
|
|
963
|
-
|
|
1034
|
+
// eslint-disable-next-line compat/compat
|
|
1035
|
+
return new URL(this._endpoint, host).href
|
|
964
1036
|
} catch {
|
|
965
|
-
|
|
1037
|
+
const normalizedHost = host.endsWith('/') ? host.slice(0, -1) : host
|
|
1038
|
+
const normalizedEndpoint = this._endpoint.startsWith('/') ? this._endpoint : `/${this._endpoint}`
|
|
1039
|
+
return `${normalizedHost}${normalizedEndpoint}`
|
|
966
1040
|
}
|
|
967
1041
|
}
|
|
968
1042
|
|
|
@@ -1560,7 +1634,7 @@ export class LazyLoadedSessionRecording {
|
|
|
1560
1634
|
return
|
|
1561
1635
|
}
|
|
1562
1636
|
|
|
1563
|
-
const activePlugins = this._gatherRRWebPlugins()
|
|
1637
|
+
const activePlugins = await this._gatherRRWebPlugins()
|
|
1564
1638
|
|
|
1565
1639
|
let stopHandler: listenerHandler | undefined
|
|
1566
1640
|
try {
|
|
@@ -25,6 +25,12 @@ export class SessionRecording {
|
|
|
25
25
|
private _persistFlagsOnSessionListener: (() => void) | undefined = undefined
|
|
26
26
|
private _lazyLoadedSessionRecording: LazyLoadedSessionRecording | undefined
|
|
27
27
|
|
|
28
|
+
private _debug(...args: any[]) {
|
|
29
|
+
if (this._instance?.config?.debug) {
|
|
30
|
+
log.info(...args)
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
|
|
28
34
|
public get started(): boolean {
|
|
29
35
|
return !!this._lazyLoadedSessionRecording?.isStarted
|
|
30
36
|
}
|
|
@@ -66,8 +72,10 @@ export class SessionRecording {
|
|
|
66
72
|
|
|
67
73
|
const canRunReplay = !isUndefined(Object.assign) && !isUndefined(Array.from)
|
|
68
74
|
if (this._isRecordingEnabled && canRunReplay) {
|
|
75
|
+
this._debug('Session replay enabled; starting recorder')
|
|
69
76
|
this._lazyLoadAndStart(startReason)
|
|
70
77
|
} else {
|
|
78
|
+
this._debug('Session replay disabled; stopping recorder')
|
|
71
79
|
this.stopRecording()
|
|
72
80
|
}
|
|
73
81
|
}
|
|
@@ -156,13 +164,8 @@ export class SessionRecording {
|
|
|
156
164
|
log.info('skipping remote config with no sessionRecording', response)
|
|
157
165
|
return
|
|
158
166
|
}
|
|
159
|
-
this._receivedFlags = true
|
|
160
|
-
|
|
161
|
-
if (response.sessionRecording === false) {
|
|
162
|
-
return
|
|
163
|
-
}
|
|
164
|
-
|
|
165
167
|
this._persistRemoteConfig(response)
|
|
168
|
+
this._receivedFlags = true
|
|
166
169
|
this.startIfEnabledOrStop()
|
|
167
170
|
}
|
|
168
171
|
|
package/src/version.ts
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
export const version = '0.
|
|
1
|
+
export const version = '0.4.0'
|