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