@leanbase-giangnd/js 0.2.2 → 0.2.3
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 +100 -23
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.ts +5 -0
- package/dist/index.mjs +100 -23
- package/dist/index.mjs.map +1 -1
- package/dist/leanbase.iife.js +100 -23
- package/dist/leanbase.iife.js.map +1 -1
- package/package.json +47 -46
- package/src/extensions/replay/external/lazy-loaded-session-recorder.ts +19 -7
- package/src/extensions/replay/session-recording.ts +19 -12
- package/src/leanbase.ts +68 -6
- package/src/version.ts +1 -1
- package/LICENSE +0 -37
package/dist/index.d.ts
CHANGED
|
@@ -6127,6 +6127,10 @@ declare class Leanbase extends PostHogCore {
|
|
|
6127
6127
|
consent: ConsentManager;
|
|
6128
6128
|
sessionRecording?: SessionRecording$1;
|
|
6129
6129
|
isRemoteConfigLoaded?: boolean;
|
|
6130
|
+
private _remoteConfigLoadAttempted;
|
|
6131
|
+
private _remoteConfigResolved;
|
|
6132
|
+
private _featureFlagsResolved;
|
|
6133
|
+
private _maybeStartedSessionRecording;
|
|
6130
6134
|
personProcessingSetOncePropertiesSent: boolean;
|
|
6131
6135
|
isLoaded: boolean;
|
|
6132
6136
|
initialPageviewCaptured: boolean;
|
|
@@ -6137,6 +6141,7 @@ declare class Leanbase extends PostHogCore {
|
|
|
6137
6141
|
capturePageLeave(): void;
|
|
6138
6142
|
loadRemoteConfig(): Promise<void>;
|
|
6139
6143
|
onRemoteConfig(config: RemoteConfig$1): void;
|
|
6144
|
+
private _maybeStartSessionRecording;
|
|
6140
6145
|
fetch(url: string, options: PostHogFetchOptions): Promise<PostHogFetchResponse>;
|
|
6141
6146
|
setConfig(config: Partial<LeanbaseConfig>): void;
|
|
6142
6147
|
getLibraryId(): string;
|
package/dist/index.mjs
CHANGED
|
@@ -1169,7 +1169,7 @@ const detectDeviceType = function (user_agent) {
|
|
|
1169
1169
|
}
|
|
1170
1170
|
};
|
|
1171
1171
|
|
|
1172
|
-
var version = "0.2.
|
|
1172
|
+
var version = "0.2.3";
|
|
1173
1173
|
var packageInfo = {
|
|
1174
1174
|
version: version};
|
|
1175
1175
|
|
|
@@ -4446,6 +4446,11 @@ class LazyLoadedSessionRecording {
|
|
|
4446
4446
|
});
|
|
4447
4447
|
this._makeSamplingDecision(this.sessionId);
|
|
4448
4448
|
await this._startRecorder();
|
|
4449
|
+
// If rrweb failed to load/start, do not proceed further.
|
|
4450
|
+
// This prevents installing listeners that assume rrweb is active.
|
|
4451
|
+
if (!this.isStarted) {
|
|
4452
|
+
return;
|
|
4453
|
+
}
|
|
4449
4454
|
// calling addEventListener multiple times is safe and will not add duplicates
|
|
4450
4455
|
addEventListener(win, 'beforeunload', this._onBeforeUnload);
|
|
4451
4456
|
addEventListener(win, 'offline', this._onOffline);
|
|
@@ -4979,13 +4984,19 @@ class LazyLoadedSessionRecording {
|
|
|
4979
4984
|
}
|
|
4980
4985
|
});
|
|
4981
4986
|
const activePlugins = this._gatherRRWebPlugins();
|
|
4982
|
-
|
|
4983
|
-
|
|
4984
|
-
|
|
4985
|
-
|
|
4986
|
-
|
|
4987
|
-
|
|
4988
|
-
|
|
4987
|
+
try {
|
|
4988
|
+
this._stopRrweb = rrwebRecord({
|
|
4989
|
+
emit: event => {
|
|
4990
|
+
this.onRRwebEmit(event);
|
|
4991
|
+
},
|
|
4992
|
+
plugins: activePlugins,
|
|
4993
|
+
...sessionRecordingOptions
|
|
4994
|
+
});
|
|
4995
|
+
} catch (e) {
|
|
4996
|
+
logger.error('failed to start rrweb recorder', e);
|
|
4997
|
+
this._stopRrweb = undefined;
|
|
4998
|
+
return;
|
|
4999
|
+
}
|
|
4989
5000
|
// We reset the last activity timestamp, resetting the idle timer
|
|
4990
5001
|
this._lastActivityTimestamp = Date.now();
|
|
4991
5002
|
// stay unknown if we're not sure if we're idle or not
|
|
@@ -5171,18 +5182,25 @@ class SessionRecording {
|
|
|
5171
5182
|
// If extensions provide an init function, use it. Otherwise, fall back to the local LazyLoadedSessionRecording
|
|
5172
5183
|
if (assignableWindow.__PosthogExtensions__?.initSessionRecording) {
|
|
5173
5184
|
if (!this._lazyLoadedSessionRecording) {
|
|
5174
|
-
|
|
5175
|
-
|
|
5185
|
+
const maybeRecording = assignableWindow.__PosthogExtensions__?.initSessionRecording(this._instance);
|
|
5186
|
+
if (maybeRecording && typeof maybeRecording.start === 'function') {
|
|
5187
|
+
this._lazyLoadedSessionRecording = maybeRecording;
|
|
5188
|
+
this._lazyLoadedSessionRecording._forceAllowLocalhostNetworkCapture = this._forceAllowLocalhostNetworkCapture;
|
|
5189
|
+
} else {
|
|
5190
|
+
log.warn('initSessionRecording was present but did not return a recorder instance; falling back to local recorder');
|
|
5191
|
+
}
|
|
5176
5192
|
}
|
|
5177
|
-
|
|
5178
|
-
|
|
5179
|
-
|
|
5180
|
-
maybePromise
|
|
5193
|
+
if (this._lazyLoadedSessionRecording) {
|
|
5194
|
+
try {
|
|
5195
|
+
const maybePromise = this._lazyLoadedSessionRecording.start(startReason);
|
|
5196
|
+
if (maybePromise && typeof maybePromise.catch === 'function') {
|
|
5197
|
+
maybePromise.catch(e => logger$2.error('error starting session recording', e));
|
|
5198
|
+
}
|
|
5199
|
+
} catch (e) {
|
|
5200
|
+
logger$2.error('error starting session recording', e);
|
|
5181
5201
|
}
|
|
5182
|
-
|
|
5183
|
-
logger$2.error('error starting session recording', e);
|
|
5202
|
+
return;
|
|
5184
5203
|
}
|
|
5185
|
-
return;
|
|
5186
5204
|
}
|
|
5187
5205
|
if (!this._lazyLoadedSessionRecording) {
|
|
5188
5206
|
this._lazyLoadedSessionRecording = new LazyLoadedSessionRecording(this._instance);
|
|
@@ -5297,6 +5315,10 @@ class Leanbase extends PostHogCore {
|
|
|
5297
5315
|
token
|
|
5298
5316
|
});
|
|
5299
5317
|
super(token, mergedConfig);
|
|
5318
|
+
this._remoteConfigLoadAttempted = false;
|
|
5319
|
+
this._remoteConfigResolved = false;
|
|
5320
|
+
this._featureFlagsResolved = false;
|
|
5321
|
+
this._maybeStartedSessionRecording = false;
|
|
5300
5322
|
this.personProcessingSetOncePropertiesSent = false;
|
|
5301
5323
|
this.isLoaded = false;
|
|
5302
5324
|
this.config = mergedConfig;
|
|
@@ -5320,10 +5342,20 @@ class Leanbase extends PostHogCore {
|
|
|
5320
5342
|
this.replayAutocapture.startIfEnabled();
|
|
5321
5343
|
if (this.sessionManager && this.config.cookieless_mode !== 'always') {
|
|
5322
5344
|
this.sessionRecording = new SessionRecording(this);
|
|
5323
|
-
this.sessionRecording.startIfEnabledOrStop();
|
|
5324
5345
|
}
|
|
5346
|
+
// Start session recording only once flags + remote config have been resolved.
|
|
5347
|
+
// This matches the PostHog browser SDK where replay activation is driven by remote config and flags.
|
|
5325
5348
|
if (this.config.preloadFeatureFlags !== false) {
|
|
5326
|
-
this.reloadFeatureFlags(
|
|
5349
|
+
this.reloadFeatureFlags({
|
|
5350
|
+
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
5351
|
+
cb: _err => {
|
|
5352
|
+
this._featureFlagsResolved = true;
|
|
5353
|
+
this._maybeStartSessionRecording();
|
|
5354
|
+
}
|
|
5355
|
+
});
|
|
5356
|
+
} else {
|
|
5357
|
+
// If feature flags preload is explicitly disabled, treat this requirement as satisfied.
|
|
5358
|
+
this._featureFlagsResolved = true;
|
|
5327
5359
|
}
|
|
5328
5360
|
this.config.loaded?.(this);
|
|
5329
5361
|
if (this.config.capture_pageview) {
|
|
@@ -5333,9 +5365,26 @@ class Leanbase extends PostHogCore {
|
|
|
5333
5365
|
}
|
|
5334
5366
|
}, 1);
|
|
5335
5367
|
}
|
|
5336
|
-
|
|
5337
|
-
|
|
5338
|
-
|
|
5368
|
+
const triggerRemoteConfigLoad = reason => {
|
|
5369
|
+
logger$2.info(`remote config load triggered via ${reason}`);
|
|
5370
|
+
void this.loadRemoteConfig();
|
|
5371
|
+
};
|
|
5372
|
+
if (document) {
|
|
5373
|
+
if (document.readyState === 'loading') {
|
|
5374
|
+
logger$2.info('remote config load deferred until DOMContentLoaded');
|
|
5375
|
+
const onDomReady = () => {
|
|
5376
|
+
document?.removeEventListener('DOMContentLoaded', onDomReady);
|
|
5377
|
+
triggerRemoteConfigLoad('dom');
|
|
5378
|
+
};
|
|
5379
|
+
addEventListener(document, 'DOMContentLoaded', onDomReady, {
|
|
5380
|
+
once: true
|
|
5381
|
+
});
|
|
5382
|
+
} else {
|
|
5383
|
+
triggerRemoteConfigLoad('immediate');
|
|
5384
|
+
}
|
|
5385
|
+
} else {
|
|
5386
|
+
triggerRemoteConfigLoad('no-document');
|
|
5387
|
+
}
|
|
5339
5388
|
addEventListener(window, 'onpagehide' in self ? 'pagehide' : 'unload', this.capturePageLeave.bind(this), {
|
|
5340
5389
|
passive: false
|
|
5341
5390
|
});
|
|
@@ -5372,11 +5421,19 @@ class Leanbase extends PostHogCore {
|
|
|
5372
5421
|
}
|
|
5373
5422
|
}
|
|
5374
5423
|
async loadRemoteConfig() {
|
|
5375
|
-
if (
|
|
5424
|
+
if (this._remoteConfigLoadAttempted) {
|
|
5425
|
+
return;
|
|
5426
|
+
}
|
|
5427
|
+
this._remoteConfigLoadAttempted = true;
|
|
5428
|
+
try {
|
|
5376
5429
|
const remoteConfig = await this.reloadRemoteConfigAsync();
|
|
5377
5430
|
if (remoteConfig) {
|
|
5378
5431
|
this.onRemoteConfig(remoteConfig);
|
|
5379
5432
|
}
|
|
5433
|
+
} finally {
|
|
5434
|
+
// Regardless of success/failure, we consider remote config "resolved" so replay isn't blocked forever.
|
|
5435
|
+
this._remoteConfigResolved = true;
|
|
5436
|
+
this._maybeStartSessionRecording();
|
|
5380
5437
|
}
|
|
5381
5438
|
}
|
|
5382
5439
|
onRemoteConfig(config) {
|
|
@@ -5389,6 +5446,26 @@ class Leanbase extends PostHogCore {
|
|
|
5389
5446
|
this.isRemoteConfigLoaded = true;
|
|
5390
5447
|
this.replayAutocapture?.onRemoteConfig(config);
|
|
5391
5448
|
this.sessionRecording?.onRemoteConfig(config);
|
|
5449
|
+
// Remote config has been applied; allow replay start if flags are also ready.
|
|
5450
|
+
this._remoteConfigResolved = true;
|
|
5451
|
+
this._maybeStartSessionRecording();
|
|
5452
|
+
}
|
|
5453
|
+
_maybeStartSessionRecording() {
|
|
5454
|
+
if (this._maybeStartedSessionRecording) {
|
|
5455
|
+
return;
|
|
5456
|
+
}
|
|
5457
|
+
if (!this.sessionRecording) {
|
|
5458
|
+
return;
|
|
5459
|
+
}
|
|
5460
|
+
if (!this._featureFlagsResolved || !this._remoteConfigResolved) {
|
|
5461
|
+
return;
|
|
5462
|
+
}
|
|
5463
|
+
this._maybeStartedSessionRecording = true;
|
|
5464
|
+
try {
|
|
5465
|
+
this.sessionRecording.startIfEnabledOrStop();
|
|
5466
|
+
} catch (e) {
|
|
5467
|
+
logger$2.error('Failed to start session recording', e);
|
|
5468
|
+
}
|
|
5392
5469
|
}
|
|
5393
5470
|
fetch(url, options) {
|
|
5394
5471
|
const fetchFn = getFetch();
|