@leanbase-giangnd/js 0.0.3 → 0.0.5
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 +102 -10
- package/dist/index.cjs.map +1 -1
- package/dist/index.mjs +103 -11
- package/dist/index.mjs.map +1 -1
- package/dist/leanbase.iife.js +102 -10
- package/dist/leanbase.iife.js.map +1 -1
- package/package.json +3 -3
- package/src/extensions/replay/external/lazy-loaded-session-recorder.ts +27 -8
- package/src/extensions/replay/external/snapshot-transport.ts +50 -0
- package/src/leanbase.ts +31 -1
- package/src/version.ts +1 -1
package/dist/leanbase.iife.js
CHANGED
|
@@ -2863,7 +2863,7 @@ var leanbase = (function () {
|
|
|
2863
2863
|
}
|
|
2864
2864
|
};
|
|
2865
2865
|
|
|
2866
|
-
var version = "0.0.
|
|
2866
|
+
var version = "0.0.5";
|
|
2867
2867
|
var packageInfo = {
|
|
2868
2868
|
version: version};
|
|
2869
2869
|
|
|
@@ -12019,6 +12019,53 @@ var leanbase = (function () {
|
|
|
12019
12019
|
}
|
|
12020
12020
|
}
|
|
12021
12021
|
|
|
12022
|
+
/**
|
|
12023
|
+
* Leanbase-only SnapshotTransport
|
|
12024
|
+
* Sends gzip-compressed snapshot payloads directly to the /s/ endpoint.
|
|
12025
|
+
* This bypasses `posthog.capture()` and the analytics /batch/ queue.
|
|
12026
|
+
*
|
|
12027
|
+
* Reasoning: session replay snapshots must not enter the batch/persisted
|
|
12028
|
+
* queues managed by @posthog/core. This transport posts directly to the
|
|
12029
|
+
* recorder endpoint and uses the instance.fetch() implementation so it
|
|
12030
|
+
* runs in the same environment the SDK uses.
|
|
12031
|
+
*/
|
|
12032
|
+
async function sendSnapshotDirect(instance, url, payload) {
|
|
12033
|
+
const fetchFn = instance && instance.fetch ? instance.fetch.bind(instance) : globalThis.fetch;
|
|
12034
|
+
const body = JSON.stringify(payload);
|
|
12035
|
+
const compressed = gzipSync(strToU8(body));
|
|
12036
|
+
const headers = {
|
|
12037
|
+
'Content-Encoding': 'gzip',
|
|
12038
|
+
'Content-Type': 'application/json',
|
|
12039
|
+
Accept: 'application/json'
|
|
12040
|
+
};
|
|
12041
|
+
if (!fetchFn) {
|
|
12042
|
+
// best-effort: if no fetch available, fail silently (recorder should not crash app)
|
|
12043
|
+
try {
|
|
12044
|
+
// eslint-disable-next-line no-console
|
|
12045
|
+
console.debug('[SnapshotTransport] no fetch available, dropping snapshot');
|
|
12046
|
+
} catch {}
|
|
12047
|
+
return {
|
|
12048
|
+
status: 0
|
|
12049
|
+
};
|
|
12050
|
+
}
|
|
12051
|
+
try {
|
|
12052
|
+
// Use the instance.fetch wrapper so environment-specific shims are used.
|
|
12053
|
+
return await fetchFn(url, {
|
|
12054
|
+
method: 'POST',
|
|
12055
|
+
body: compressed,
|
|
12056
|
+
headers
|
|
12057
|
+
});
|
|
12058
|
+
} catch (err) {
|
|
12059
|
+
try {
|
|
12060
|
+
// eslint-disable-next-line no-console
|
|
12061
|
+
console.debug('[SnapshotTransport] send failed', err);
|
|
12062
|
+
} catch {}
|
|
12063
|
+
return {
|
|
12064
|
+
status: 0
|
|
12065
|
+
};
|
|
12066
|
+
}
|
|
12067
|
+
}
|
|
12068
|
+
|
|
12022
12069
|
function simpleHash(str) {
|
|
12023
12070
|
let hash = 0;
|
|
12024
12071
|
for (let i = 0; i < str.length; i++) {
|
|
@@ -12046,7 +12093,6 @@ var leanbase = (function () {
|
|
|
12046
12093
|
const RECORDING_IDLE_THRESHOLD_MS = FIVE_MINUTES;
|
|
12047
12094
|
const RECORDING_MAX_EVENT_SIZE = ONE_KB * ONE_KB * 0.9; // ~1mb (with some wiggle room)
|
|
12048
12095
|
const RECORDING_BUFFER_TIMEOUT = 2000; // 2 seconds
|
|
12049
|
-
const SESSION_RECORDING_BATCH_KEY = 'recordings';
|
|
12050
12096
|
const LOGGER_PREFIX$1 = '[SessionRecording]';
|
|
12051
12097
|
const logger = createLogger(LOGGER_PREFIX$1);
|
|
12052
12098
|
const ACTIVE_SOURCES = [IncrementalSource.MouseMove, IncrementalSource.MouseInteraction, IncrementalSource.Scroll, IncrementalSource.ViewportResize, IncrementalSource.Input, IncrementalSource.TouchMove, IncrementalSource.MediaInteraction, IncrementalSource.Drag];
|
|
@@ -12764,14 +12810,31 @@ var leanbase = (function () {
|
|
|
12764
12810
|
}, RECORDING_BUFFER_TIMEOUT);
|
|
12765
12811
|
}
|
|
12766
12812
|
}
|
|
12767
|
-
_captureSnapshot(properties) {
|
|
12768
|
-
//
|
|
12769
|
-
|
|
12770
|
-
|
|
12771
|
-
|
|
12772
|
-
|
|
12773
|
-
|
|
12774
|
-
|
|
12813
|
+
async _captureSnapshot(properties) {
|
|
12814
|
+
// Send snapshots directly to the recorder endpoint to avoid the core
|
|
12815
|
+
// analytics batching and persisted queue. The lifecycle gate in
|
|
12816
|
+
// SessionRecording ensures this method is only called when recording
|
|
12817
|
+
// is allowed.
|
|
12818
|
+
try {
|
|
12819
|
+
const url = this._snapshotUrl();
|
|
12820
|
+
// include minimal metadata expected by /s/ endpoint
|
|
12821
|
+
const payload = {
|
|
12822
|
+
$snapshot_bytes: properties.$snapshot_bytes,
|
|
12823
|
+
$snapshot_data: properties.$snapshot_data,
|
|
12824
|
+
$session_id: properties.$session_id,
|
|
12825
|
+
$window_id: properties.$window_id,
|
|
12826
|
+
$lib: properties.$lib,
|
|
12827
|
+
$lib_version: properties.$lib_version,
|
|
12828
|
+
// include distinct_id from persistence for server-side association
|
|
12829
|
+
distinct_id: this._instance.persistence?.get_property('distinct_id')
|
|
12830
|
+
};
|
|
12831
|
+
await sendSnapshotDirect(this._instance, url, payload);
|
|
12832
|
+
} catch (err) {
|
|
12833
|
+
try {
|
|
12834
|
+
// eslint-disable-next-line no-console
|
|
12835
|
+
console.debug('[SessionRecording] snapshot send failed', err);
|
|
12836
|
+
} catch {}
|
|
12837
|
+
}
|
|
12775
12838
|
}
|
|
12776
12839
|
_snapshotUrl() {
|
|
12777
12840
|
const host = this._instance.config.host || '';
|
|
@@ -13487,6 +13550,35 @@ var leanbase = (function () {
|
|
|
13487
13550
|
// eslint-disable-next-line no-console
|
|
13488
13551
|
console.debug('[Leanbase.fetch] parsed.batch.length=', parsed.batch.length, 'hasSnapshot=', hasSnapshot);
|
|
13489
13552
|
} catch {}
|
|
13553
|
+
// If remote config has explicitly disabled session recording, drop snapshot events
|
|
13554
|
+
try {
|
|
13555
|
+
// Read persisted remote config that SessionRecording stores
|
|
13556
|
+
const persisted = this.get_property(SESSION_RECORDING_REMOTE_CONFIG);
|
|
13557
|
+
const serverAllowsRecording = !(persisted && persisted.enabled === false || this.config.disable_session_recording === true);
|
|
13558
|
+
if (!serverAllowsRecording && hasSnapshot) {
|
|
13559
|
+
// remove snapshot events from the batch before sending to /batch/
|
|
13560
|
+
parsed.batch = parsed.batch.filter(item => !(item && item.event === '$snapshot'));
|
|
13561
|
+
// If no events remain, short-circuit and avoid sending an empty batch
|
|
13562
|
+
if (!parsed.batch.length) {
|
|
13563
|
+
try {
|
|
13564
|
+
// eslint-disable-next-line no-console
|
|
13565
|
+
console.debug('[Leanbase.fetch] sessionRecording disabled, dropping snapshot-only batch');
|
|
13566
|
+
} catch {}
|
|
13567
|
+
return {
|
|
13568
|
+
status: 200,
|
|
13569
|
+
json: async () => ({})
|
|
13570
|
+
};
|
|
13571
|
+
}
|
|
13572
|
+
// re-encode the body so the underlying fetch receives the modified batch
|
|
13573
|
+
try {
|
|
13574
|
+
const newBody = JSON.stringify(parsed);
|
|
13575
|
+
options = {
|
|
13576
|
+
...options,
|
|
13577
|
+
body: newBody
|
|
13578
|
+
};
|
|
13579
|
+
} catch {}
|
|
13580
|
+
}
|
|
13581
|
+
} catch {}
|
|
13490
13582
|
if (hasSnapshot) {
|
|
13491
13583
|
const host = this.config && this.config.host || '';
|
|
13492
13584
|
const newUrl = host ? `${host.replace(/\/$/, '')}/s/` : url;
|