posthog-js 1.93.2 → 1.93.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/array.full.js +1 -1
- package/dist/array.full.js.map +1 -1
- package/dist/array.js +1 -1
- package/dist/array.js.map +1 -1
- package/dist/es.js +1 -1
- package/dist/es.js.map +1 -1
- package/dist/module.d.ts +3 -0
- package/dist/module.js +1 -1
- package/dist/module.js.map +1 -1
- package/lib/package.json +1 -1
- package/lib/src/extensions/replay/sessionrecording.d.ts +2 -0
- package/lib/src/extensions/replay/sessionrecording.js +16 -12
- package/lib/src/extensions/replay/sessionrecording.js.map +1 -1
- package/lib/src/types.d.ts +1 -0
- package/lib/src/types.js.map +1 -1
- package/package.json +1 -1
package/lib/package.json
CHANGED
|
@@ -47,6 +47,8 @@ export declare class SessionRecording {
|
|
|
47
47
|
private _startCapture;
|
|
48
48
|
private _isInteractiveEvent;
|
|
49
49
|
private _updateWindowAndSessionIds;
|
|
50
|
+
private _tryRRwebMethod;
|
|
51
|
+
private _tryAddCustomEvent;
|
|
50
52
|
private _tryTakeFullSnapshot;
|
|
51
53
|
private _onScriptLoaded;
|
|
52
54
|
onRRwebEmit(rawEvent: eventWithTime): void;
|
|
@@ -372,13 +372,12 @@ var SessionRecording = /** @class */ (function () {
|
|
|
372
372
|
// Some recording events are triggered by non-user events (e.g. "X minutes ago" text updating on the screen).
|
|
373
373
|
// We don't want to extend the session or trigger a new session in these cases. These events are designated by event
|
|
374
374
|
// type -> incremental update, and source -> mutation.
|
|
375
|
-
var _a, _b;
|
|
376
375
|
var isUserInteraction = this._isInteractiveEvent(event);
|
|
377
376
|
if (!isUserInteraction && !this.isIdle) {
|
|
378
377
|
// We check if the lastActivityTimestamp is old enough to go idle
|
|
379
378
|
if (event.timestamp - this._lastActivityTimestamp > RECORDING_IDLE_ACTIVITY_TIMEOUT_MS) {
|
|
380
379
|
this.isIdle = true;
|
|
381
|
-
|
|
380
|
+
this._tryAddCustomEvent('sessionIdle', {
|
|
382
381
|
reason: 'user inactivity',
|
|
383
382
|
timeSinceLastActive: event.timestamp - this._lastActivityTimestamp,
|
|
384
383
|
threshold: RECORDING_IDLE_ACTIVITY_TIMEOUT_MS,
|
|
@@ -390,7 +389,7 @@ var SessionRecording = /** @class */ (function () {
|
|
|
390
389
|
if (this.isIdle) {
|
|
391
390
|
// Remove the idle state if set and trigger a full snapshot as we will have ignored previous mutations
|
|
392
391
|
this.isIdle = false;
|
|
393
|
-
|
|
392
|
+
this._tryAddCustomEvent('sessionNoLongerIdle', {
|
|
394
393
|
reason: 'user activity',
|
|
395
394
|
type: event.type,
|
|
396
395
|
});
|
|
@@ -401,7 +400,7 @@ var SessionRecording = /** @class */ (function () {
|
|
|
401
400
|
return;
|
|
402
401
|
}
|
|
403
402
|
// We only want to extend the session if it is an interactive event.
|
|
404
|
-
var
|
|
403
|
+
var _a = this.sessionManager.checkAndGetSessionAndWindowId(!isUserInteraction, event.timestamp), windowId = _a.windowId, sessionId = _a.sessionId;
|
|
405
404
|
var sessionIdChanged = this.sessionId !== sessionId;
|
|
406
405
|
var windowIdChanged = this.windowId !== windowId;
|
|
407
406
|
if ([FULL_SNAPSHOT_EVENT_TYPE, META_EVENT_TYPE].indexOf(event.type) === -1 &&
|
|
@@ -411,22 +410,28 @@ var SessionRecording = /** @class */ (function () {
|
|
|
411
410
|
this.windowId = windowId;
|
|
412
411
|
this.sessionId = sessionId;
|
|
413
412
|
};
|
|
414
|
-
SessionRecording.prototype.
|
|
415
|
-
var _a;
|
|
416
|
-
// TODO this should ignore based on emit?
|
|
413
|
+
SessionRecording.prototype._tryRRwebMethod = function (rrwebMethod) {
|
|
417
414
|
if (!this._captureStarted) {
|
|
418
415
|
return false;
|
|
419
416
|
}
|
|
420
417
|
try {
|
|
421
|
-
(
|
|
418
|
+
rrwebMethod();
|
|
422
419
|
return true;
|
|
423
420
|
}
|
|
424
421
|
catch (e) {
|
|
425
|
-
// Sometimes a race can occur where the recorder is not fully started yet
|
|
426
|
-
logger.error('
|
|
422
|
+
// Sometimes a race can occur where the recorder is not fully started yet
|
|
423
|
+
logger.error('[Session-Recording] using rrweb when not started.', e);
|
|
427
424
|
return false;
|
|
428
425
|
}
|
|
429
426
|
};
|
|
427
|
+
SessionRecording.prototype._tryAddCustomEvent = function (tag, payload) {
|
|
428
|
+
var _this = this;
|
|
429
|
+
return this._tryRRwebMethod(function () { var _a; return (_a = _this.rrwebRecord) === null || _a === void 0 ? void 0 : _a.addCustomEvent(tag, payload); });
|
|
430
|
+
};
|
|
431
|
+
SessionRecording.prototype._tryTakeFullSnapshot = function () {
|
|
432
|
+
var _this = this;
|
|
433
|
+
return this._tryRRwebMethod(function () { var _a; return (_a = _this.rrwebRecord) === null || _a === void 0 ? void 0 : _a.takeFullSnapshot(); });
|
|
434
|
+
};
|
|
430
435
|
SessionRecording.prototype._onScriptLoaded = function () {
|
|
431
436
|
var e_1, _a;
|
|
432
437
|
var _this = this;
|
|
@@ -504,7 +509,6 @@ var SessionRecording = /** @class */ (function () {
|
|
|
504
509
|
// :TRICKY: rrweb does not capture navigation within SPA-s, so hook into our $pageview events to get access to all events.
|
|
505
510
|
// Dropping the initial event is fine (it's always captured by rrweb).
|
|
506
511
|
this.instance._addCaptureHook(function (eventName) {
|
|
507
|
-
var _a;
|
|
508
512
|
// If anything could go wrong here it has the potential to block the main loop,
|
|
509
513
|
// so we catch all errors.
|
|
510
514
|
try {
|
|
@@ -513,7 +517,7 @@ var SessionRecording = /** @class */ (function () {
|
|
|
513
517
|
if (!href) {
|
|
514
518
|
return;
|
|
515
519
|
}
|
|
516
|
-
|
|
520
|
+
_this._tryAddCustomEvent('$pageview', { href: href });
|
|
517
521
|
}
|
|
518
522
|
}
|
|
519
523
|
catch (e) {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"sessionrecording.js","sourceRoot":"","sources":["../../../../src/extensions/replay/sessionrecording.ts"],"names":[],"mappings":"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","sourcesContent":["import {\n CONSOLE_LOG_RECORDING_ENABLED_SERVER_SIDE,\n SESSION_RECORDING_ENABLED_SERVER_SIDE,\n SESSION_RECORDING_IS_SAMPLED,\n SESSION_RECORDING_NETWORK_PAYLOAD_CAPTURE,\n SESSION_RECORDING_RECORDER_VERSION_SERVER_SIDE,\n} from '../../constants'\nimport {\n FULL_SNAPSHOT_EVENT_TYPE,\n INCREMENTAL_SNAPSHOT_EVENT_TYPE,\n META_EVENT_TYPE,\n MutationRateLimiter,\n recordOptions,\n rrwebRecord,\n truncateLargeConsoleLogs,\n} from './sessionrecording-utils'\nimport { PostHog } from '../../posthog-core'\nimport { DecideResponse, NetworkRecordOptions, NetworkRequest, Properties } from '../../types'\nimport { EventType, type eventWithTime, type listenerHandler } from '@rrweb/types'\nimport Config from '../../config'\nimport { _timestamp, loadScript } from '../../utils'\n\nimport { _isBoolean, _isFunction, _isNull, _isNumber, _isObject, _isString, _isUndefined } from '../../utils/type-utils'\nimport { logger } from '../../utils/logger'\nimport { assignableWindow, window } from '../../utils/globals'\nimport { buildNetworkRequestOptions } from './config'\nimport { isLocalhost } from '../../utils/request-utils'\n\nconst BASE_ENDPOINT = '/s/'\n\nexport const RECORDING_IDLE_ACTIVITY_TIMEOUT_MS = 5 * 60 * 1000 // 5 minutes\nexport const RECORDING_MAX_EVENT_SIZE = 1024 * 1024 * 0.9 // ~1mb (with some wiggle room)\nexport const RECORDING_BUFFER_TIMEOUT = 2000 // 2 seconds\nexport const SESSION_RECORDING_BATCH_KEY = 'recordings'\n\n// NOTE: Importing this type is problematic as we can't safely bundle it to a TS definition so, instead we redefine.\n// import type { record } from 'rrweb2/typings'\n// import type { recordOptions } from 'rrweb/typings/types'\n\n// Copied from rrweb typings to avoid import\nenum IncrementalSource {\n Mutation = 0,\n MouseMove = 1,\n MouseInteraction = 2,\n Scroll = 3,\n ViewportResize = 4,\n Input = 5,\n TouchMove = 6,\n MediaInteraction = 7,\n StyleSheetRule = 8,\n CanvasMutation = 9,\n Font = 10,\n Log = 11,\n Drag = 12,\n StyleDeclaration = 13,\n Selection = 14,\n AdoptedStyleSheet = 15,\n}\n\nconst ACTIVE_SOURCES = [\n IncrementalSource.MouseMove,\n IncrementalSource.MouseInteraction,\n IncrementalSource.Scroll,\n IncrementalSource.ViewportResize,\n IncrementalSource.Input,\n IncrementalSource.TouchMove,\n IncrementalSource.MediaInteraction,\n IncrementalSource.Drag,\n]\n\n/**\n * Session recording starts in buffering mode while waiting for decide response\n * Once the response is received it might be disabled, active or sampled\n * When sampled that means a sample rate is set and the last time the session id was rotated\n * the sample rate determined this session should be sent to the server.\n */\ntype SessionRecordingStatus = 'disabled' | 'sampled' | 'active' | 'buffering'\n\ninterface SnapshotBuffer {\n size: number\n data: any[]\n sessionId: string | null\n windowId: string | null\n}\n\nexport class SessionRecording {\n private instance: PostHog\n private _endpoint: string\n private flushBufferTimer?: any\n private buffer?: SnapshotBuffer\n private mutationRateLimiter?: MutationRateLimiter\n private _captureStarted: boolean\n private stopRrweb: listenerHandler | undefined\n private receivedDecide: boolean\n private rrwebRecord: rrwebRecord | undefined\n private isIdle = false\n\n private _linkedFlagSeen: boolean = false\n private _lastActivityTimestamp: number = Date.now()\n private windowId: string | null = null\n private sessionId: string | null = null\n private _linkedFlag: string | null = null\n private _sampleRate: number | null = null\n private _minimumDuration: number | null = null\n\n // Util to help developers working on this feature manually override\n _forceAllowLocalhostNetworkCapture = false\n\n public get started(): boolean {\n // TODO could we use status instead of _captureStarted?\n return this._captureStarted\n }\n\n private get sessionManager() {\n if (!this.instance.sessionManager) {\n logger.error('Session recording started without valid sessionManager')\n throw new Error('Session recording started without valid sessionManager. This is a bug.')\n }\n\n return this.instance.sessionManager\n }\n\n private get isSampled(): boolean | null {\n if (_isNumber(this._sampleRate)) {\n return this.instance.get_property(SESSION_RECORDING_IS_SAMPLED)\n } else {\n return null\n }\n }\n\n private get sessionDuration(): number | null {\n const mostRecentSnapshot = this.buffer?.data[this.buffer?.data.length - 1]\n const { sessionStartTimestamp } = this.sessionManager.checkAndGetSessionAndWindowId(true)\n return mostRecentSnapshot ? mostRecentSnapshot.timestamp - sessionStartTimestamp : null\n }\n\n private get isRecordingEnabled() {\n const enabled_server_side = !!this.instance.get_property(SESSION_RECORDING_ENABLED_SERVER_SIDE)\n const enabled_client_side = !this.instance.config.disable_session_recording\n return window && enabled_server_side && enabled_client_side\n }\n\n private get isConsoleLogCaptureEnabled() {\n const enabled_server_side = !!this.instance.get_property(CONSOLE_LOG_RECORDING_ENABLED_SERVER_SIDE)\n const enabled_client_side = this.instance.config.enable_recording_console_log\n return enabled_client_side ?? enabled_server_side\n }\n\n private get recordingVersion() {\n const recordingVersion_server_side = this.instance.get_property(SESSION_RECORDING_RECORDER_VERSION_SERVER_SIDE)\n const recordingVersion_client_side = this.instance.config.session_recording?.recorderVersion\n return recordingVersion_client_side || recordingVersion_server_side || 'v1'\n }\n\n // network payload capture config has three parts\n // each can be configured server side or client side\n private get networkPayloadCapture():\n | Pick<NetworkRecordOptions, 'recordHeaders' | 'recordBody' | 'recordPerformance'>\n | undefined {\n const networkPayloadCapture_server_side = this.instance.get_property(SESSION_RECORDING_NETWORK_PAYLOAD_CAPTURE)\n const networkPayloadCapture_client_side = {\n recordHeaders: this.instance.config.session_recording?.recordHeaders,\n recordBody: this.instance.config.session_recording?.recordBody,\n }\n const headersEnabled =\n networkPayloadCapture_client_side?.recordHeaders || networkPayloadCapture_server_side?.recordHeaders\n const bodyEnabled =\n networkPayloadCapture_client_side?.recordBody || networkPayloadCapture_server_side?.recordBody\n const performanceEnabled =\n this.instance.config.capture_performance || networkPayloadCapture_server_side?.capturePerformance\n\n return headersEnabled || bodyEnabled || performanceEnabled\n ? { recordHeaders: headersEnabled, recordBody: bodyEnabled, recordPerformance: performanceEnabled }\n : undefined\n }\n\n /**\n * defaults to buffering mode until a decide response is received\n * once a decide response is received status can be disabled, active or sampled\n */\n private get status(): SessionRecordingStatus {\n if (!this.receivedDecide) {\n return 'buffering'\n }\n\n if (!this.isRecordingEnabled) {\n return 'disabled'\n }\n\n if (_isString(this._linkedFlag) && !this._linkedFlagSeen) {\n return 'buffering'\n }\n\n if (_isBoolean(this.isSampled)) {\n return this.isSampled ? 'sampled' : 'disabled'\n } else {\n return 'active'\n }\n }\n\n constructor(instance: PostHog) {\n this.instance = instance\n this._captureStarted = false\n this._endpoint = BASE_ENDPOINT\n this.stopRrweb = undefined\n this.receivedDecide = false\n\n window?.addEventListener('beforeunload', () => {\n this._flushBuffer()\n })\n\n if (!this.instance.sessionManager) {\n logger.error('Session recording started without valid sessionManager')\n throw new Error('Session recording started without valid sessionManager. This is a bug.')\n }\n\n this.buffer = this.clearBuffer()\n }\n\n startRecordingIfEnabled() {\n if (this.isRecordingEnabled) {\n this.startCaptureAndTrySendingQueuedSnapshots()\n } else {\n this.stopRecording()\n this.clearBuffer()\n }\n }\n\n stopRecording() {\n if (this._captureStarted && this.stopRrweb) {\n this.stopRrweb()\n this.stopRrweb = undefined\n this._captureStarted = false\n }\n }\n\n private makeSamplingDecision(sessionId: string): void {\n const sessionIdChanged = this.sessionId !== sessionId\n\n if (!_isNumber(this._sampleRate)) {\n this.instance.persistence?.register({\n [SESSION_RECORDING_IS_SAMPLED]: null,\n })\n return\n }\n\n const storedIsSampled = this.isSampled\n\n /**\n * if we get this far then we should make a sampling decision.\n * When the session id changes or there is no stored sampling decision for this session id\n * then we should make a new decision.\n *\n * Otherwise, we should use the stored decision.\n */\n let shouldSample: boolean\n if (sessionIdChanged || !_isBoolean(storedIsSampled)) {\n const randomNumber = Math.random()\n shouldSample = randomNumber < this._sampleRate\n } else {\n shouldSample = storedIsSampled\n }\n\n if (!shouldSample) {\n logger.warn(\n `[SessionSampling] Sample rate (${this._sampleRate}) has determined that this sessionId (${sessionId}) will not be sent to the server.`\n )\n }\n\n this.instance.persistence?.register({\n [SESSION_RECORDING_IS_SAMPLED]: shouldSample,\n })\n }\n\n afterDecideResponse(response: DecideResponse) {\n if (this.instance.persistence) {\n this.instance.persistence.register({\n [SESSION_RECORDING_ENABLED_SERVER_SIDE]: !!response['sessionRecording'],\n [CONSOLE_LOG_RECORDING_ENABLED_SERVER_SIDE]: response.sessionRecording?.consoleLogRecordingEnabled,\n [SESSION_RECORDING_RECORDER_VERSION_SERVER_SIDE]: response.sessionRecording?.recorderVersion,\n [SESSION_RECORDING_NETWORK_PAYLOAD_CAPTURE]: {\n capturePerformance: response.capturePerformance,\n ...response.sessionRecording?.networkPayloadCapture,\n },\n })\n }\n\n const receivedSampleRate = response.sessionRecording?.sampleRate\n this._sampleRate =\n _isUndefined(receivedSampleRate) || _isNull(receivedSampleRate) ? null : parseFloat(receivedSampleRate)\n\n const receivedMinimumDuration = response.sessionRecording?.minimumDurationMilliseconds\n this._minimumDuration = _isUndefined(receivedMinimumDuration) ? null : receivedMinimumDuration\n\n this._linkedFlag = response.sessionRecording?.linkedFlag || null\n\n if (response.sessionRecording?.endpoint) {\n this._endpoint = response.sessionRecording?.endpoint\n }\n\n if (_isNumber(this._sampleRate)) {\n this.sessionManager.onSessionId((sessionId) => {\n this.makeSamplingDecision(sessionId)\n })\n }\n\n if (_isString(this._linkedFlag)) {\n const linkedFlag = this._linkedFlag\n this.instance.onFeatureFlags((flags) => {\n this._linkedFlagSeen = flags.includes(linkedFlag)\n })\n }\n\n this.receivedDecide = true\n this.startRecordingIfEnabled()\n }\n\n log(message: string, level: 'log' | 'warn' | 'error' = 'log') {\n this.instance.sessionRecording?.onRRwebEmit({\n type: 6,\n data: {\n plugin: 'rrweb/console@1',\n payload: {\n level,\n trace: [],\n // Even though it is a string we stringify it as that's what rrweb expects\n payload: [JSON.stringify(message)],\n },\n },\n timestamp: _timestamp(),\n })\n }\n\n private startCaptureAndTrySendingQueuedSnapshots() {\n this._startCapture()\n }\n\n private _startCapture() {\n if (_isUndefined(Object.assign)) {\n // According to the rrweb docs, rrweb is not supported on IE11 and below:\n // \"rrweb does not support IE11 and below because it uses the MutationObserver API which was supported by these browsers.\"\n // https://github.com/rrweb-io/rrweb/blob/master/guide.md#compatibility-note\n //\n // However, MutationObserver does exist on IE11, it just doesn't work well and does not detect all changes.\n // Instead, when we load \"recorder.js\", the first JS error is about \"Object.assign\" being undefined.\n // Thus instead of MutationObserver, we look for this function and block recording if it's undefined.\n return\n }\n\n // We do not switch recorder versions midway through a recording.\n if (this._captureStarted || this.instance.config.disable_session_recording) {\n return\n }\n\n this._captureStarted = true\n // We want to ensure the sessionManager is reset if necessary on load of the recorder\n this.sessionManager.checkAndGetSessionAndWindowId()\n\n const recorderJS = this.recordingVersion === 'v2' ? 'recorder-v2.js' : 'recorder.js'\n\n // If recorder.js is already loaded (if array.full.js snippet is used or posthog-js/dist/recorder is\n // imported) or matches the requested recorder version, don't load script. Otherwise, remotely import\n // recorder.js from cdn since it hasn't been loaded.\n if (this.instance.__loaded_recorder_version !== this.recordingVersion) {\n loadScript(this.instance.config.api_host + `/static/${recorderJS}?v=${Config.LIB_VERSION}`, (err) => {\n if (err) {\n return logger.error(`Could not load ${recorderJS}`, err)\n }\n\n this._onScriptLoaded()\n })\n } else {\n this._onScriptLoaded()\n }\n }\n\n private _isInteractiveEvent(event: eventWithTime) {\n return event.type === INCREMENTAL_SNAPSHOT_EVENT_TYPE && ACTIVE_SOURCES.indexOf(event.data?.source) !== -1\n }\n\n private _updateWindowAndSessionIds(event: eventWithTime) {\n // Some recording events are triggered by non-user events (e.g. \"X minutes ago\" text updating on the screen).\n // We don't want to extend the session or trigger a new session in these cases. These events are designated by event\n // type -> incremental update, and source -> mutation.\n\n const isUserInteraction = this._isInteractiveEvent(event)\n\n if (!isUserInteraction && !this.isIdle) {\n // We check if the lastActivityTimestamp is old enough to go idle\n if (event.timestamp - this._lastActivityTimestamp > RECORDING_IDLE_ACTIVITY_TIMEOUT_MS) {\n this.isIdle = true\n this.rrwebRecord?.addCustomEvent('sessionIdle', {\n reason: 'user inactivity',\n timeSinceLastActive: event.timestamp - this._lastActivityTimestamp,\n threshold: RECORDING_IDLE_ACTIVITY_TIMEOUT_MS,\n })\n }\n }\n\n if (isUserInteraction) {\n this._lastActivityTimestamp = event.timestamp\n if (this.isIdle) {\n // Remove the idle state if set and trigger a full snapshot as we will have ignored previous mutations\n this.isIdle = false\n this.rrwebRecord?.addCustomEvent('sessionNoLongerIdle', {\n reason: 'user activity',\n type: event.type,\n })\n this._tryTakeFullSnapshot()\n }\n }\n\n if (this.isIdle) {\n return\n }\n\n // We only want to extend the session if it is an interactive event.\n const { windowId, sessionId } = this.sessionManager.checkAndGetSessionAndWindowId(\n !isUserInteraction,\n event.timestamp\n )\n\n const sessionIdChanged = this.sessionId !== sessionId\n const windowIdChanged = this.windowId !== windowId\n\n if (\n [FULL_SNAPSHOT_EVENT_TYPE, META_EVENT_TYPE].indexOf(event.type) === -1 &&\n (windowIdChanged || sessionIdChanged)\n ) {\n this._tryTakeFullSnapshot()\n }\n\n this.windowId = windowId\n this.sessionId = sessionId\n }\n\n private _tryTakeFullSnapshot(): boolean {\n // TODO this should ignore based on emit?\n if (!this._captureStarted) {\n return false\n }\n try {\n this.rrwebRecord?.takeFullSnapshot()\n return true\n } catch (e) {\n // Sometimes a race can occur where the recorder is not fully started yet, so we can't take a full snapshot.\n logger.error('Error taking full snapshot.', e)\n return false\n }\n }\n\n private _onScriptLoaded() {\n // rrweb config info: https://github.com/rrweb-io/rrweb/blob/7d5d0033258d6c29599fb08412202d9a2c7b9413/src/record/index.ts#L28\n const sessionRecordingOptions: recordOptions<eventWithTime> = {\n // select set of rrweb config options we expose to our users\n // see https://github.com/rrweb-io/rrweb/blob/master/guide.md\n blockClass: 'ph-no-capture',\n blockSelector: undefined,\n ignoreClass: 'ph-ignore-input',\n maskTextClass: 'ph-mask',\n maskTextSelector: undefined,\n maskTextFn: undefined,\n maskAllInputs: true,\n maskInputOptions: {},\n maskInputFn: undefined,\n slimDOMOptions: {},\n collectFonts: false,\n inlineStylesheet: true,\n recordCrossOriginIframes: false,\n }\n // We switched from loading all of rrweb to just the record part, but\n // keep backwards compatibility if someone hasn't upgraded PostHog\n // eslint-disable-next-line @typescript-eslint/ban-ts-comment\n // @ts-ignore\n this.rrwebRecord = window.rrweb ? window.rrweb.record : window.rrwebRecord\n\n // only allows user to set our allow-listed options\n const userSessionRecordingOptions = this.instance.config.session_recording\n for (const [key, value] of Object.entries(userSessionRecordingOptions || {})) {\n if (key in sessionRecordingOptions) {\n // eslint-disable-next-line @typescript-eslint/ban-ts-comment\n // @ts-ignore\n sessionRecordingOptions[key] = value\n }\n }\n\n if (!this.rrwebRecord) {\n logger.error(\n 'onScriptLoaded was called but rrwebRecord is not available. This indicates something has gone wrong.'\n )\n return\n }\n\n this.mutationRateLimiter =\n this.mutationRateLimiter ??\n new MutationRateLimiter(this.rrwebRecord, {\n onBlockedNode: (id, node) => {\n const message = `Too many mutations on node '${id}'. Rate limiting. This could be due to SVG animations or something similar`\n logger.info(message, {\n node: node,\n })\n\n this.log('[PostHog Recorder] ' + message, 'warn')\n },\n })\n\n const plugins = []\n\n if (assignableWindow.rrwebConsoleRecord && this.isConsoleLogCaptureEnabled) {\n plugins.push(assignableWindow.rrwebConsoleRecord.getRecordConsolePlugin())\n }\n if (this.networkPayloadCapture && _isFunction(assignableWindow.getRecordNetworkPlugin)) {\n if (isLocalhost() && !this._forceAllowLocalhostNetworkCapture) {\n logger.info('[SessionReplay-NetworkCapture] not started because we are on localhost.')\n return\n }\n\n plugins.push(\n assignableWindow.getRecordNetworkPlugin(\n buildNetworkRequestOptions(this.instance.config, this.networkPayloadCapture)\n )\n )\n }\n\n this.stopRrweb = this.rrwebRecord({\n emit: (event) => {\n this.onRRwebEmit(event)\n },\n plugins,\n ...sessionRecordingOptions,\n })\n\n // :TRICKY: rrweb does not capture navigation within SPA-s, so hook into our $pageview events to get access to all events.\n // Dropping the initial event is fine (it's always captured by rrweb).\n this.instance._addCaptureHook((eventName) => {\n // If anything could go wrong here it has the potential to block the main loop,\n // so we catch all errors.\n try {\n if (eventName === '$pageview') {\n const href = window ? this._maskUrl(window.location.href) : ''\n if (!href) {\n return\n }\n this.rrwebRecord?.addCustomEvent('$pageview', { href })\n }\n } catch (e) {\n logger.error('Could not add $pageview to rrweb session', e)\n }\n })\n\n // We reset the last activity timestamp, resetting the idle timer\n this._lastActivityTimestamp = Date.now()\n this.isIdle = false\n }\n\n onRRwebEmit(rawEvent: eventWithTime) {\n if (!rawEvent || !_isObject(rawEvent)) {\n return\n }\n\n if (rawEvent.type === EventType.Meta) {\n const href = this._maskUrl(rawEvent.data.href)\n if (!href) {\n return\n }\n rawEvent.data.href = href\n }\n\n const throttledEvent = this.mutationRateLimiter\n ? this.mutationRateLimiter.throttleMutations(rawEvent)\n : rawEvent\n\n if (!throttledEvent) {\n return\n }\n\n // TODO: Re-add ensureMaxMessageSize once we are confident in it\n const event = truncateLargeConsoleLogs(throttledEvent)\n const size = JSON.stringify(event).length\n\n this._updateWindowAndSessionIds(event)\n\n if (this.isIdle) {\n // When in an idle state we keep recording, but don't capture the events\n return\n }\n\n const properties = {\n $snapshot_bytes: size,\n $snapshot_data: event,\n $session_id: this.sessionId,\n $window_id: this.windowId,\n }\n\n if (this.status !== 'disabled') {\n this._captureSnapshotBuffered(properties)\n } else {\n this.clearBuffer()\n }\n }\n\n private _maskUrl(url: string): string | undefined {\n const userSessionRecordingOptions = this.instance.config.session_recording\n\n if (userSessionRecordingOptions.maskNetworkRequestFn) {\n let networkRequest: NetworkRequest | null | undefined = {\n url,\n }\n\n // TODO we should deprecate this and use the same function for this masking and the rrweb/network plugin\n // TODO or deprecate this and provide a new clearer name so this would be `maskURLPerformanceFn` or similar\n networkRequest = userSessionRecordingOptions.maskNetworkRequestFn(networkRequest)\n\n return networkRequest?.url\n }\n\n return url\n }\n\n private clearBuffer(): SnapshotBuffer {\n this.buffer = undefined\n\n return {\n size: 0,\n data: [],\n sessionId: this.sessionId,\n windowId: this.windowId,\n }\n }\n\n // the intention is a buffer that (currently) is used only after a decide response enables session recording\n // it is called ever X seconds using the flushBufferTimer so that we don't have to wait for the buffer to fill up\n // when it is called on a timer it assumes that it can definitely flush\n // it is flushed when the session id changes or the size of the buffered data gets too great (1mb by default)\n // first change: if the recording is in buffering mode,\n // flush buffer simply resets the timer and returns the existing flush buffer\n private _flushBuffer() {\n if (this.flushBufferTimer) {\n clearTimeout(this.flushBufferTimer)\n this.flushBufferTimer = undefined\n }\n\n const minimumDuration = this._minimumDuration\n const sessionDuration = this.sessionDuration\n // if we have old data in the buffer but the session has rotated then the\n // session duration might be negative, in that case we want to flush the buffer\n const isPositiveSessionDuration = _isNumber(sessionDuration) && sessionDuration >= 0\n const isBelowMinimumDuration =\n _isNumber(minimumDuration) && isPositiveSessionDuration && sessionDuration < minimumDuration\n\n if (this.status === 'buffering' || isBelowMinimumDuration) {\n this.flushBufferTimer = setTimeout(() => {\n this._flushBuffer()\n }, RECORDING_BUFFER_TIMEOUT)\n return this.buffer || this.clearBuffer()\n }\n\n if (this.buffer && this.buffer.data.length !== 0) {\n this._captureSnapshot({\n $snapshot_bytes: this.buffer.size,\n $snapshot_data: this.buffer.data,\n $session_id: this.buffer.sessionId,\n $window_id: this.buffer.windowId,\n })\n\n return this.clearBuffer()\n } else {\n return this.buffer || this.clearBuffer()\n }\n }\n\n private _captureSnapshotBuffered(properties: Properties) {\n const additionalBytes = 2 + (this.buffer?.data.length || 0) // 2 bytes for the array brackets and 1 byte for each comma\n if (\n !this.buffer ||\n this.buffer.size + properties.$snapshot_bytes + additionalBytes > RECORDING_MAX_EVENT_SIZE ||\n (!!this.buffer.sessionId && this.buffer.sessionId !== this.sessionId)\n ) {\n this.buffer = this._flushBuffer()\n }\n\n if (_isNull(this.buffer.sessionId) && !_isNull(this.sessionId)) {\n // session id starts null but has now been assigned, update the buffer\n this.buffer.sessionId = this.sessionId\n this.buffer.windowId = this.windowId\n }\n\n this.buffer.size += properties.$snapshot_bytes\n this.buffer.data.push(properties.$snapshot_data)\n\n if (!this.flushBufferTimer) {\n this.flushBufferTimer = setTimeout(() => {\n this._flushBuffer()\n }, RECORDING_BUFFER_TIMEOUT)\n }\n }\n\n private _captureSnapshot(properties: Properties) {\n // :TRICKY: Make sure we batch these requests, use a custom endpoint and don't truncate the strings.\n this.instance.capture('$snapshot', properties, {\n transport: 'XHR',\n method: 'POST',\n endpoint: this._endpoint,\n _noTruncate: true,\n _batchKey: SESSION_RECORDING_BATCH_KEY,\n _metrics: {\n rrweb_full_snapshot: properties.$snapshot_data.type === FULL_SNAPSHOT_EVENT_TYPE,\n },\n })\n }\n}\n"]}
|
|
1
|
+
{"version":3,"file":"sessionrecording.js","sourceRoot":"","sources":["../../../../src/extensions/replay/sessionrecording.ts"],"names":[],"mappings":"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","sourcesContent":["import {\n CONSOLE_LOG_RECORDING_ENABLED_SERVER_SIDE,\n SESSION_RECORDING_ENABLED_SERVER_SIDE,\n SESSION_RECORDING_IS_SAMPLED,\n SESSION_RECORDING_NETWORK_PAYLOAD_CAPTURE,\n SESSION_RECORDING_RECORDER_VERSION_SERVER_SIDE,\n} from '../../constants'\nimport {\n FULL_SNAPSHOT_EVENT_TYPE,\n INCREMENTAL_SNAPSHOT_EVENT_TYPE,\n META_EVENT_TYPE,\n MutationRateLimiter,\n recordOptions,\n rrwebRecord,\n truncateLargeConsoleLogs,\n} from './sessionrecording-utils'\nimport { PostHog } from '../../posthog-core'\nimport { DecideResponse, NetworkRecordOptions, NetworkRequest, Properties } from '../../types'\nimport { EventType, type eventWithTime, type listenerHandler } from '@rrweb/types'\nimport Config from '../../config'\nimport { _timestamp, loadScript } from '../../utils'\n\nimport { _isBoolean, _isFunction, _isNull, _isNumber, _isObject, _isString, _isUndefined } from '../../utils/type-utils'\nimport { logger } from '../../utils/logger'\nimport { assignableWindow, window } from '../../utils/globals'\nimport { buildNetworkRequestOptions } from './config'\nimport { isLocalhost } from '../../utils/request-utils'\n\nconst BASE_ENDPOINT = '/s/'\n\nexport const RECORDING_IDLE_ACTIVITY_TIMEOUT_MS = 5 * 60 * 1000 // 5 minutes\nexport const RECORDING_MAX_EVENT_SIZE = 1024 * 1024 * 0.9 // ~1mb (with some wiggle room)\nexport const RECORDING_BUFFER_TIMEOUT = 2000 // 2 seconds\nexport const SESSION_RECORDING_BATCH_KEY = 'recordings'\n\n// NOTE: Importing this type is problematic as we can't safely bundle it to a TS definition so, instead we redefine.\n// import type { record } from 'rrweb2/typings'\n// import type { recordOptions } from 'rrweb/typings/types'\n\n// Copied from rrweb typings to avoid import\nenum IncrementalSource {\n Mutation = 0,\n MouseMove = 1,\n MouseInteraction = 2,\n Scroll = 3,\n ViewportResize = 4,\n Input = 5,\n TouchMove = 6,\n MediaInteraction = 7,\n StyleSheetRule = 8,\n CanvasMutation = 9,\n Font = 10,\n Log = 11,\n Drag = 12,\n StyleDeclaration = 13,\n Selection = 14,\n AdoptedStyleSheet = 15,\n}\n\nconst ACTIVE_SOURCES = [\n IncrementalSource.MouseMove,\n IncrementalSource.MouseInteraction,\n IncrementalSource.Scroll,\n IncrementalSource.ViewportResize,\n IncrementalSource.Input,\n IncrementalSource.TouchMove,\n IncrementalSource.MediaInteraction,\n IncrementalSource.Drag,\n]\n\n/**\n * Session recording starts in buffering mode while waiting for decide response\n * Once the response is received it might be disabled, active or sampled\n * When sampled that means a sample rate is set and the last time the session id was rotated\n * the sample rate determined this session should be sent to the server.\n */\ntype SessionRecordingStatus = 'disabled' | 'sampled' | 'active' | 'buffering'\n\ninterface SnapshotBuffer {\n size: number\n data: any[]\n sessionId: string | null\n windowId: string | null\n}\n\nexport class SessionRecording {\n private instance: PostHog\n private _endpoint: string\n private flushBufferTimer?: any\n private buffer?: SnapshotBuffer\n private mutationRateLimiter?: MutationRateLimiter\n private _captureStarted: boolean\n private stopRrweb: listenerHandler | undefined\n private receivedDecide: boolean\n private rrwebRecord: rrwebRecord | undefined\n private isIdle = false\n\n private _linkedFlagSeen: boolean = false\n private _lastActivityTimestamp: number = Date.now()\n private windowId: string | null = null\n private sessionId: string | null = null\n private _linkedFlag: string | null = null\n private _sampleRate: number | null = null\n private _minimumDuration: number | null = null\n\n // Util to help developers working on this feature manually override\n _forceAllowLocalhostNetworkCapture = false\n\n public get started(): boolean {\n // TODO could we use status instead of _captureStarted?\n return this._captureStarted\n }\n\n private get sessionManager() {\n if (!this.instance.sessionManager) {\n logger.error('Session recording started without valid sessionManager')\n throw new Error('Session recording started without valid sessionManager. This is a bug.')\n }\n\n return this.instance.sessionManager\n }\n\n private get isSampled(): boolean | null {\n if (_isNumber(this._sampleRate)) {\n return this.instance.get_property(SESSION_RECORDING_IS_SAMPLED)\n } else {\n return null\n }\n }\n\n private get sessionDuration(): number | null {\n const mostRecentSnapshot = this.buffer?.data[this.buffer?.data.length - 1]\n const { sessionStartTimestamp } = this.sessionManager.checkAndGetSessionAndWindowId(true)\n return mostRecentSnapshot ? mostRecentSnapshot.timestamp - sessionStartTimestamp : null\n }\n\n private get isRecordingEnabled() {\n const enabled_server_side = !!this.instance.get_property(SESSION_RECORDING_ENABLED_SERVER_SIDE)\n const enabled_client_side = !this.instance.config.disable_session_recording\n return window && enabled_server_side && enabled_client_side\n }\n\n private get isConsoleLogCaptureEnabled() {\n const enabled_server_side = !!this.instance.get_property(CONSOLE_LOG_RECORDING_ENABLED_SERVER_SIDE)\n const enabled_client_side = this.instance.config.enable_recording_console_log\n return enabled_client_side ?? enabled_server_side\n }\n\n private get recordingVersion() {\n const recordingVersion_server_side = this.instance.get_property(SESSION_RECORDING_RECORDER_VERSION_SERVER_SIDE)\n const recordingVersion_client_side = this.instance.config.session_recording?.recorderVersion\n return recordingVersion_client_side || recordingVersion_server_side || 'v1'\n }\n\n // network payload capture config has three parts\n // each can be configured server side or client side\n private get networkPayloadCapture():\n | Pick<NetworkRecordOptions, 'recordHeaders' | 'recordBody' | 'recordPerformance'>\n | undefined {\n const networkPayloadCapture_server_side = this.instance.get_property(SESSION_RECORDING_NETWORK_PAYLOAD_CAPTURE)\n const networkPayloadCapture_client_side = {\n recordHeaders: this.instance.config.session_recording?.recordHeaders,\n recordBody: this.instance.config.session_recording?.recordBody,\n }\n const headersEnabled =\n networkPayloadCapture_client_side?.recordHeaders || networkPayloadCapture_server_side?.recordHeaders\n const bodyEnabled =\n networkPayloadCapture_client_side?.recordBody || networkPayloadCapture_server_side?.recordBody\n const performanceEnabled =\n this.instance.config.capture_performance || networkPayloadCapture_server_side?.capturePerformance\n\n return headersEnabled || bodyEnabled || performanceEnabled\n ? { recordHeaders: headersEnabled, recordBody: bodyEnabled, recordPerformance: performanceEnabled }\n : undefined\n }\n\n /**\n * defaults to buffering mode until a decide response is received\n * once a decide response is received status can be disabled, active or sampled\n */\n private get status(): SessionRecordingStatus {\n if (!this.receivedDecide) {\n return 'buffering'\n }\n\n if (!this.isRecordingEnabled) {\n return 'disabled'\n }\n\n if (_isString(this._linkedFlag) && !this._linkedFlagSeen) {\n return 'buffering'\n }\n\n if (_isBoolean(this.isSampled)) {\n return this.isSampled ? 'sampled' : 'disabled'\n } else {\n return 'active'\n }\n }\n\n constructor(instance: PostHog) {\n this.instance = instance\n this._captureStarted = false\n this._endpoint = BASE_ENDPOINT\n this.stopRrweb = undefined\n this.receivedDecide = false\n\n window?.addEventListener('beforeunload', () => {\n this._flushBuffer()\n })\n\n if (!this.instance.sessionManager) {\n logger.error('Session recording started without valid sessionManager')\n throw new Error('Session recording started without valid sessionManager. This is a bug.')\n }\n\n this.buffer = this.clearBuffer()\n }\n\n startRecordingIfEnabled() {\n if (this.isRecordingEnabled) {\n this.startCaptureAndTrySendingQueuedSnapshots()\n } else {\n this.stopRecording()\n this.clearBuffer()\n }\n }\n\n stopRecording() {\n if (this._captureStarted && this.stopRrweb) {\n this.stopRrweb()\n this.stopRrweb = undefined\n this._captureStarted = false\n }\n }\n\n private makeSamplingDecision(sessionId: string): void {\n const sessionIdChanged = this.sessionId !== sessionId\n\n if (!_isNumber(this._sampleRate)) {\n this.instance.persistence?.register({\n [SESSION_RECORDING_IS_SAMPLED]: null,\n })\n return\n }\n\n const storedIsSampled = this.isSampled\n\n /**\n * if we get this far then we should make a sampling decision.\n * When the session id changes or there is no stored sampling decision for this session id\n * then we should make a new decision.\n *\n * Otherwise, we should use the stored decision.\n */\n let shouldSample: boolean\n if (sessionIdChanged || !_isBoolean(storedIsSampled)) {\n const randomNumber = Math.random()\n shouldSample = randomNumber < this._sampleRate\n } else {\n shouldSample = storedIsSampled\n }\n\n if (!shouldSample) {\n logger.warn(\n `[SessionSampling] Sample rate (${this._sampleRate}) has determined that this sessionId (${sessionId}) will not be sent to the server.`\n )\n }\n\n this.instance.persistence?.register({\n [SESSION_RECORDING_IS_SAMPLED]: shouldSample,\n })\n }\n\n afterDecideResponse(response: DecideResponse) {\n if (this.instance.persistence) {\n this.instance.persistence.register({\n [SESSION_RECORDING_ENABLED_SERVER_SIDE]: !!response['sessionRecording'],\n [CONSOLE_LOG_RECORDING_ENABLED_SERVER_SIDE]: response.sessionRecording?.consoleLogRecordingEnabled,\n [SESSION_RECORDING_RECORDER_VERSION_SERVER_SIDE]: response.sessionRecording?.recorderVersion,\n [SESSION_RECORDING_NETWORK_PAYLOAD_CAPTURE]: {\n capturePerformance: response.capturePerformance,\n ...response.sessionRecording?.networkPayloadCapture,\n },\n })\n }\n\n const receivedSampleRate = response.sessionRecording?.sampleRate\n this._sampleRate =\n _isUndefined(receivedSampleRate) || _isNull(receivedSampleRate) ? null : parseFloat(receivedSampleRate)\n\n const receivedMinimumDuration = response.sessionRecording?.minimumDurationMilliseconds\n this._minimumDuration = _isUndefined(receivedMinimumDuration) ? null : receivedMinimumDuration\n\n this._linkedFlag = response.sessionRecording?.linkedFlag || null\n\n if (response.sessionRecording?.endpoint) {\n this._endpoint = response.sessionRecording?.endpoint\n }\n\n if (_isNumber(this._sampleRate)) {\n this.sessionManager.onSessionId((sessionId) => {\n this.makeSamplingDecision(sessionId)\n })\n }\n\n if (_isString(this._linkedFlag)) {\n const linkedFlag = this._linkedFlag\n this.instance.onFeatureFlags((flags) => {\n this._linkedFlagSeen = flags.includes(linkedFlag)\n })\n }\n\n this.receivedDecide = true\n this.startRecordingIfEnabled()\n }\n\n log(message: string, level: 'log' | 'warn' | 'error' = 'log') {\n this.instance.sessionRecording?.onRRwebEmit({\n type: 6,\n data: {\n plugin: 'rrweb/console@1',\n payload: {\n level,\n trace: [],\n // Even though it is a string we stringify it as that's what rrweb expects\n payload: [JSON.stringify(message)],\n },\n },\n timestamp: _timestamp(),\n })\n }\n\n private startCaptureAndTrySendingQueuedSnapshots() {\n this._startCapture()\n }\n\n private _startCapture() {\n if (_isUndefined(Object.assign)) {\n // According to the rrweb docs, rrweb is not supported on IE11 and below:\n // \"rrweb does not support IE11 and below because it uses the MutationObserver API which was supported by these browsers.\"\n // https://github.com/rrweb-io/rrweb/blob/master/guide.md#compatibility-note\n //\n // However, MutationObserver does exist on IE11, it just doesn't work well and does not detect all changes.\n // Instead, when we load \"recorder.js\", the first JS error is about \"Object.assign\" being undefined.\n // Thus instead of MutationObserver, we look for this function and block recording if it's undefined.\n return\n }\n\n // We do not switch recorder versions midway through a recording.\n if (this._captureStarted || this.instance.config.disable_session_recording) {\n return\n }\n\n this._captureStarted = true\n // We want to ensure the sessionManager is reset if necessary on load of the recorder\n this.sessionManager.checkAndGetSessionAndWindowId()\n\n const recorderJS = this.recordingVersion === 'v2' ? 'recorder-v2.js' : 'recorder.js'\n\n // If recorder.js is already loaded (if array.full.js snippet is used or posthog-js/dist/recorder is\n // imported) or matches the requested recorder version, don't load script. Otherwise, remotely import\n // recorder.js from cdn since it hasn't been loaded.\n if (this.instance.__loaded_recorder_version !== this.recordingVersion) {\n loadScript(this.instance.config.api_host + `/static/${recorderJS}?v=${Config.LIB_VERSION}`, (err) => {\n if (err) {\n return logger.error(`Could not load ${recorderJS}`, err)\n }\n\n this._onScriptLoaded()\n })\n } else {\n this._onScriptLoaded()\n }\n }\n\n private _isInteractiveEvent(event: eventWithTime) {\n return event.type === INCREMENTAL_SNAPSHOT_EVENT_TYPE && ACTIVE_SOURCES.indexOf(event.data?.source) !== -1\n }\n\n private _updateWindowAndSessionIds(event: eventWithTime) {\n // Some recording events are triggered by non-user events (e.g. \"X minutes ago\" text updating on the screen).\n // We don't want to extend the session or trigger a new session in these cases. These events are designated by event\n // type -> incremental update, and source -> mutation.\n\n const isUserInteraction = this._isInteractiveEvent(event)\n\n if (!isUserInteraction && !this.isIdle) {\n // We check if the lastActivityTimestamp is old enough to go idle\n if (event.timestamp - this._lastActivityTimestamp > RECORDING_IDLE_ACTIVITY_TIMEOUT_MS) {\n this.isIdle = true\n this._tryAddCustomEvent('sessionIdle', {\n reason: 'user inactivity',\n timeSinceLastActive: event.timestamp - this._lastActivityTimestamp,\n threshold: RECORDING_IDLE_ACTIVITY_TIMEOUT_MS,\n })\n }\n }\n\n if (isUserInteraction) {\n this._lastActivityTimestamp = event.timestamp\n if (this.isIdle) {\n // Remove the idle state if set and trigger a full snapshot as we will have ignored previous mutations\n this.isIdle = false\n this._tryAddCustomEvent('sessionNoLongerIdle', {\n reason: 'user activity',\n type: event.type,\n })\n this._tryTakeFullSnapshot()\n }\n }\n\n if (this.isIdle) {\n return\n }\n\n // We only want to extend the session if it is an interactive event.\n const { windowId, sessionId } = this.sessionManager.checkAndGetSessionAndWindowId(\n !isUserInteraction,\n event.timestamp\n )\n\n const sessionIdChanged = this.sessionId !== sessionId\n const windowIdChanged = this.windowId !== windowId\n\n if (\n [FULL_SNAPSHOT_EVENT_TYPE, META_EVENT_TYPE].indexOf(event.type) === -1 &&\n (windowIdChanged || sessionIdChanged)\n ) {\n this._tryTakeFullSnapshot()\n }\n\n this.windowId = windowId\n this.sessionId = sessionId\n }\n\n private _tryRRwebMethod(rrwebMethod: () => void): boolean {\n if (!this._captureStarted) {\n return false\n }\n try {\n rrwebMethod()\n return true\n } catch (e) {\n // Sometimes a race can occur where the recorder is not fully started yet\n logger.error('[Session-Recording] using rrweb when not started.', e)\n return false\n }\n }\n\n private _tryAddCustomEvent(tag: string, payload: any): boolean {\n return this._tryRRwebMethod(() => this.rrwebRecord?.addCustomEvent(tag, payload))\n }\n\n private _tryTakeFullSnapshot(): boolean {\n return this._tryRRwebMethod(() => this.rrwebRecord?.takeFullSnapshot())\n }\n\n private _onScriptLoaded() {\n // rrweb config info: https://github.com/rrweb-io/rrweb/blob/7d5d0033258d6c29599fb08412202d9a2c7b9413/src/record/index.ts#L28\n const sessionRecordingOptions: recordOptions<eventWithTime> = {\n // select set of rrweb config options we expose to our users\n // see https://github.com/rrweb-io/rrweb/blob/master/guide.md\n blockClass: 'ph-no-capture',\n blockSelector: undefined,\n ignoreClass: 'ph-ignore-input',\n maskTextClass: 'ph-mask',\n maskTextSelector: undefined,\n maskTextFn: undefined,\n maskAllInputs: true,\n maskInputOptions: {},\n maskInputFn: undefined,\n slimDOMOptions: {},\n collectFonts: false,\n inlineStylesheet: true,\n recordCrossOriginIframes: false,\n }\n // We switched from loading all of rrweb to just the record part, but\n // keep backwards compatibility if someone hasn't upgraded PostHog\n // eslint-disable-next-line @typescript-eslint/ban-ts-comment\n // @ts-ignore\n this.rrwebRecord = window.rrweb ? window.rrweb.record : window.rrwebRecord\n\n // only allows user to set our allow-listed options\n const userSessionRecordingOptions = this.instance.config.session_recording\n for (const [key, value] of Object.entries(userSessionRecordingOptions || {})) {\n if (key in sessionRecordingOptions) {\n // eslint-disable-next-line @typescript-eslint/ban-ts-comment\n // @ts-ignore\n sessionRecordingOptions[key] = value\n }\n }\n\n if (!this.rrwebRecord) {\n logger.error(\n 'onScriptLoaded was called but rrwebRecord is not available. This indicates something has gone wrong.'\n )\n return\n }\n\n this.mutationRateLimiter =\n this.mutationRateLimiter ??\n new MutationRateLimiter(this.rrwebRecord, {\n onBlockedNode: (id, node) => {\n const message = `Too many mutations on node '${id}'. Rate limiting. This could be due to SVG animations or something similar`\n logger.info(message, {\n node: node,\n })\n\n this.log('[PostHog Recorder] ' + message, 'warn')\n },\n })\n\n const plugins = []\n\n if (assignableWindow.rrwebConsoleRecord && this.isConsoleLogCaptureEnabled) {\n plugins.push(assignableWindow.rrwebConsoleRecord.getRecordConsolePlugin())\n }\n if (this.networkPayloadCapture && _isFunction(assignableWindow.getRecordNetworkPlugin)) {\n if (isLocalhost() && !this._forceAllowLocalhostNetworkCapture) {\n logger.info('[SessionReplay-NetworkCapture] not started because we are on localhost.')\n return\n }\n\n plugins.push(\n assignableWindow.getRecordNetworkPlugin(\n buildNetworkRequestOptions(this.instance.config, this.networkPayloadCapture)\n )\n )\n }\n\n this.stopRrweb = this.rrwebRecord({\n emit: (event) => {\n this.onRRwebEmit(event)\n },\n plugins,\n ...sessionRecordingOptions,\n })\n\n // :TRICKY: rrweb does not capture navigation within SPA-s, so hook into our $pageview events to get access to all events.\n // Dropping the initial event is fine (it's always captured by rrweb).\n this.instance._addCaptureHook((eventName) => {\n // If anything could go wrong here it has the potential to block the main loop,\n // so we catch all errors.\n try {\n if (eventName === '$pageview') {\n const href = window ? this._maskUrl(window.location.href) : ''\n if (!href) {\n return\n }\n this._tryAddCustomEvent('$pageview', { href })\n }\n } catch (e) {\n logger.error('Could not add $pageview to rrweb session', e)\n }\n })\n\n // We reset the last activity timestamp, resetting the idle timer\n this._lastActivityTimestamp = Date.now()\n this.isIdle = false\n }\n\n onRRwebEmit(rawEvent: eventWithTime) {\n if (!rawEvent || !_isObject(rawEvent)) {\n return\n }\n\n if (rawEvent.type === EventType.Meta) {\n const href = this._maskUrl(rawEvent.data.href)\n if (!href) {\n return\n }\n rawEvent.data.href = href\n }\n\n const throttledEvent = this.mutationRateLimiter\n ? this.mutationRateLimiter.throttleMutations(rawEvent)\n : rawEvent\n\n if (!throttledEvent) {\n return\n }\n\n // TODO: Re-add ensureMaxMessageSize once we are confident in it\n const event = truncateLargeConsoleLogs(throttledEvent)\n const size = JSON.stringify(event).length\n\n this._updateWindowAndSessionIds(event)\n\n if (this.isIdle) {\n // When in an idle state we keep recording, but don't capture the events\n return\n }\n\n const properties = {\n $snapshot_bytes: size,\n $snapshot_data: event,\n $session_id: this.sessionId,\n $window_id: this.windowId,\n }\n\n if (this.status !== 'disabled') {\n this._captureSnapshotBuffered(properties)\n } else {\n this.clearBuffer()\n }\n }\n\n private _maskUrl(url: string): string | undefined {\n const userSessionRecordingOptions = this.instance.config.session_recording\n\n if (userSessionRecordingOptions.maskNetworkRequestFn) {\n let networkRequest: NetworkRequest | null | undefined = {\n url,\n }\n\n // TODO we should deprecate this and use the same function for this masking and the rrweb/network plugin\n // TODO or deprecate this and provide a new clearer name so this would be `maskURLPerformanceFn` or similar\n networkRequest = userSessionRecordingOptions.maskNetworkRequestFn(networkRequest)\n\n return networkRequest?.url\n }\n\n return url\n }\n\n private clearBuffer(): SnapshotBuffer {\n this.buffer = undefined\n\n return {\n size: 0,\n data: [],\n sessionId: this.sessionId,\n windowId: this.windowId,\n }\n }\n\n // the intention is a buffer that (currently) is used only after a decide response enables session recording\n // it is called ever X seconds using the flushBufferTimer so that we don't have to wait for the buffer to fill up\n // when it is called on a timer it assumes that it can definitely flush\n // it is flushed when the session id changes or the size of the buffered data gets too great (1mb by default)\n // first change: if the recording is in buffering mode,\n // flush buffer simply resets the timer and returns the existing flush buffer\n private _flushBuffer() {\n if (this.flushBufferTimer) {\n clearTimeout(this.flushBufferTimer)\n this.flushBufferTimer = undefined\n }\n\n const minimumDuration = this._minimumDuration\n const sessionDuration = this.sessionDuration\n // if we have old data in the buffer but the session has rotated then the\n // session duration might be negative, in that case we want to flush the buffer\n const isPositiveSessionDuration = _isNumber(sessionDuration) && sessionDuration >= 0\n const isBelowMinimumDuration =\n _isNumber(minimumDuration) && isPositiveSessionDuration && sessionDuration < minimumDuration\n\n if (this.status === 'buffering' || isBelowMinimumDuration) {\n this.flushBufferTimer = setTimeout(() => {\n this._flushBuffer()\n }, RECORDING_BUFFER_TIMEOUT)\n return this.buffer || this.clearBuffer()\n }\n\n if (this.buffer && this.buffer.data.length !== 0) {\n this._captureSnapshot({\n $snapshot_bytes: this.buffer.size,\n $snapshot_data: this.buffer.data,\n $session_id: this.buffer.sessionId,\n $window_id: this.buffer.windowId,\n })\n\n return this.clearBuffer()\n } else {\n return this.buffer || this.clearBuffer()\n }\n }\n\n private _captureSnapshotBuffered(properties: Properties) {\n const additionalBytes = 2 + (this.buffer?.data.length || 0) // 2 bytes for the array brackets and 1 byte for each comma\n if (\n !this.buffer ||\n this.buffer.size + properties.$snapshot_bytes + additionalBytes > RECORDING_MAX_EVENT_SIZE ||\n (!!this.buffer.sessionId && this.buffer.sessionId !== this.sessionId)\n ) {\n this.buffer = this._flushBuffer()\n }\n\n if (_isNull(this.buffer.sessionId) && !_isNull(this.sessionId)) {\n // session id starts null but has now been assigned, update the buffer\n this.buffer.sessionId = this.sessionId\n this.buffer.windowId = this.windowId\n }\n\n this.buffer.size += properties.$snapshot_bytes\n this.buffer.data.push(properties.$snapshot_data)\n\n if (!this.flushBufferTimer) {\n this.flushBufferTimer = setTimeout(() => {\n this._flushBuffer()\n }, RECORDING_BUFFER_TIMEOUT)\n }\n }\n\n private _captureSnapshot(properties: Properties) {\n // :TRICKY: Make sure we batch these requests, use a custom endpoint and don't truncate the strings.\n this.instance.capture('$snapshot', properties, {\n transport: 'XHR',\n method: 'POST',\n endpoint: this._endpoint,\n _noTruncate: true,\n _batchKey: SESSION_RECORDING_BATCH_KEY,\n _metrics: {\n rrweb_full_snapshot: properties.$snapshot_data.type === FULL_SNAPSHOT_EVENT_TYPE,\n },\n })\n }\n}\n"]}
|
package/lib/src/types.d.ts
CHANGED
|
@@ -70,6 +70,7 @@ export interface PostHogConfig {
|
|
|
70
70
|
upgrade: boolean;
|
|
71
71
|
disable_session_recording: boolean;
|
|
72
72
|
disable_persistence: boolean;
|
|
73
|
+
/** @deprecated - use `disable_persistence` instead */
|
|
73
74
|
disable_cookie: boolean;
|
|
74
75
|
enable_recording_console_log?: boolean;
|
|
75
76
|
secure_cookie: boolean;
|
package/lib/src/types.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"types.js","sourceRoot":"","sources":["../../src/types.ts"],"names":[],"mappings":"AAsLA,MAAM,CAAN,IAAY,WAGX;AAHD,WAAY,WAAW;IACnB,iCAAkB,CAAA;IAClB,gCAAiB,CAAA;AACrB,CAAC,EAHW,WAAW,KAAX,WAAW,QAGtB","sourcesContent":["import type { MaskInputOptions, SlimDOMOptions } from 'rrweb-snapshot'\nimport { PostHog } from './posthog-core'\nimport { RetryQueue } from './retry-queue'\n\nexport type Property = any\nexport type Properties = Record<string, Property>\n\nexport interface CaptureResult {\n uuid: string\n event: string\n properties: Properties\n $set?: Properties\n $set_once?: Properties\n timestamp?: Date\n}\nexport type CaptureCallback = (response: any, data: any) => void\n\nexport type AutocaptureCompatibleElement = 'a' | 'button' | 'form' | 'input' | 'select' | 'textarea' | 'label'\nexport type DomAutocaptureEvents = 'click' | 'change' | 'submit'\n\n/**\n * If an array is passed for an allowlist, autocapture events will only be sent for elements matching\n * at least one of the elements in the array. Multiple allowlists can be used\n */\nexport interface AutocaptureConfig {\n /**\n * List of URLs to allow autocapture on, can be strings to match\n * or regexes e.g. ['https://example.com', 'test.com/.*']\n */\n url_allowlist?: (string | RegExp)[]\n\n /**\n * List of DOM events to allow autocapture on e.g. ['click', 'change', 'submit']\n */\n dom_event_allowlist?: DomAutocaptureEvents[]\n\n /**\n * List of DOM elements to allow autocapture on\n * e.g. ['a', 'button', 'form', 'input', 'select', 'textarea', 'label']\n */\n element_allowlist?: AutocaptureCompatibleElement[]\n\n /**\n * List of CSS selectors to allow autocapture on\n * e.g. ['[ph-capture]']\n */\n css_selector_allowlist?: string[]\n\n /**\n * Exclude certain element attributes from autocapture\n * E.g. ['aria-label'] or [data-attr-pii]\n */\n element_attribute_ignorelist?: string[]\n}\n\nexport type UUIDVersion = 'og' | 'v7'\n\nexport interface PostHogConfig {\n api_host: string\n api_method: string\n api_transport: string\n ui_host: string | null\n token: string\n autocapture: boolean | AutocaptureConfig\n rageclick: boolean\n cross_subdomain_cookie: boolean\n persistence: 'localStorage' | 'cookie' | 'memory' | 'localStorage+cookie' | 'sessionStorage'\n persistence_name: string\n cookie_name: string\n loaded: (posthog_instance: PostHog) => void\n store_google: boolean\n custom_campaign_params: string[]\n // a list of strings to be tested against navigator.userAgent to determine if the source is a bot\n // this is **added to** the default list of bots that we check\n // defaults to the empty array\n custom_blocked_useragents: string[]\n save_referrer: boolean\n verbose: boolean\n capture_pageview: boolean\n capture_pageleave: boolean\n debug: boolean\n cookie_expiration: number\n upgrade: boolean\n disable_session_recording: boolean\n disable_persistence: boolean\n disable_cookie: boolean\n enable_recording_console_log?: boolean\n secure_cookie: boolean\n ip: boolean\n opt_out_capturing_by_default: boolean\n opt_out_persistence_by_default: boolean\n opt_out_capturing_persistence_type: 'localStorage' | 'cookie'\n opt_out_capturing_cookie_prefix: string | null\n opt_in_site_apps: boolean\n respect_dnt: boolean\n property_blacklist: string[]\n xhr_headers: { [header_name: string]: string }\n on_xhr_error: (failedRequest: XMLHttpRequest) => void\n inapp_protocol: string\n inapp_link_new_window: boolean\n request_batching: boolean\n sanitize_properties: ((properties: Properties, event_name: string) => Properties) | null\n properties_string_max_length: number\n session_recording: SessionRecordingOptions\n session_idle_timeout_seconds: number\n mask_all_element_attributes: boolean\n mask_all_text: boolean\n advanced_disable_decide: boolean\n advanced_disable_feature_flags: boolean\n advanced_disable_feature_flags_on_first_load: boolean\n advanced_disable_toolbar_metrics: boolean\n get_device_id: (uuid: string) => string\n name: string\n callback_fn: string\n _onCapture: (eventName: string, eventData: CaptureResult) => void\n capture_performance?: boolean\n // Should only be used for testing. Could negatively impact performance.\n disable_compression: boolean\n bootstrap: {\n distinctID?: string\n isIdentifiedID?: boolean\n featureFlags?: Record<string, boolean | string>\n featureFlagPayloads?: Record<string, JsonType>\n }\n segment?: any\n __preview_measure_pageview_stats?: boolean\n __preview_send_client_session_params?: boolean\n}\n\nexport interface OptInOutCapturingOptions {\n capture: (event: string, properties: Properties, options: CaptureOptions) => void\n capture_event_name: string\n capture_properties: Properties\n enable_persistence: boolean\n clear_persistence: boolean\n persistence_type: 'cookie' | 'localStorage' | 'localStorage+cookie'\n cookie_prefix: string\n cookie_expiration: number\n cross_subdomain_cookie: boolean\n secure_cookie: boolean\n}\n\nexport interface isFeatureEnabledOptions {\n send_event: boolean\n}\n\nexport interface SessionRecordingOptions {\n blockClass?: string | RegExp\n blockSelector?: string | null\n ignoreClass?: string\n maskTextClass?: string | RegExp\n maskTextSelector?: string | null\n maskTextFn?: ((text: string) => string) | null\n maskAllInputs?: boolean\n maskInputOptions?: MaskInputOptions\n maskInputFn?: ((text: string, element?: HTMLElement) => string) | null\n slimDOMOptions?: SlimDOMOptions | 'all' | true\n collectFonts?: boolean\n inlineStylesheet?: boolean\n recorderVersion?: 'v1' | 'v2'\n recordCrossOriginIframes?: boolean\n /** @deprecated - use maskCapturedNetworkRequestFn instead */\n maskNetworkRequestFn?: ((data: NetworkRequest) => NetworkRequest | null | undefined) | null\n /** Modify the network request before it is captured. Returning null or undefined stops it being captured */\n maskCapturedNetworkRequestFn?: ((data: CapturedNetworkRequest) => CapturedNetworkRequest | null | undefined) | null\n // properties below here are ALPHA, don't rely on them, they may change without notice\n // TODO which of these do we actually expose?\n // if this isn't provided a default will be used\n // this only applies to the payload recorder\n // TODO I guess it should apply to the other recorder to\n initiatorTypes?: InitiatorType[]\n recordHeaders?: boolean | { request: boolean; response: boolean }\n // true means record all bodies\n // false means record no bodies\n // string[] means record bodies matching the provided content-type headers\n recordBody?: boolean | string[] | { request: boolean | string[]; response: boolean | string[] }\n // I can't think why you wouldn't want this... so\n // recordInitialRequests?: boolean\n}\n\nexport type SessionIdChangedCallback = (sessionId: string, windowId: string | null | undefined) => void\n\nexport enum Compression {\n GZipJS = 'gzip-js',\n Base64 = 'base64',\n}\n\nexport interface XHROptions {\n transport?: 'XHR' | 'sendBeacon'\n method?: 'POST' | 'GET'\n urlQueryArgs?: { compression: Compression }\n verbose?: boolean\n blob?: boolean\n sendBeacon?: boolean\n}\n\nexport interface CaptureOptions extends XHROptions {\n $set?: Properties /** used with $identify */\n $set_once?: Properties /** used with $identify */\n _batchKey?: string /** key of queue, e.g. 'sessionRecording' vs 'event' */\n _metrics?: Properties\n _noTruncate?: boolean /** if set, overrides and disables config.properties_string_max_length */\n endpoint?: string /** defaults to '/e/' */\n send_instantly?: boolean /** if set skips the batched queue */\n timestamp?: Date\n}\n\nexport interface RetryQueueElement {\n retryAt: Date\n requestData: QueuedRequestData\n}\nexport interface QueuedRequestData {\n url: string\n data: Properties\n options: CaptureOptions\n headers?: Properties\n callback?: RequestCallback\n retriesPerformedSoFar?: number\n}\n\nexport interface XHRParams extends QueuedRequestData {\n retryQueue: RetryQueue\n onXHRError: (req: XMLHttpRequest) => void\n timeout?: number\n onResponse?: (req: XMLHttpRequest) => void\n}\n\nexport interface DecideResponse {\n status: number\n supportedCompression: Compression[]\n config: {\n enable_collect_everything: boolean\n }\n custom_properties: AutoCaptureCustomProperty[] // TODO: delete, not sent\n featureFlags: Record<string, string | boolean>\n featureFlagPayloads: Record<string, JsonType>\n errorsWhileComputingFlags: boolean\n autocapture_opt_out?: boolean\n capturePerformance?: boolean\n analytics?: {\n endpoint?: string\n }\n elementsChainAsString?: boolean\n // this is currently in development and may have breaking changes without a major version bump\n autocaptureExceptions?:\n | boolean\n | {\n endpoint?: string\n errors_to_ignore: string[]\n }\n sessionRecording?: {\n endpoint?: string\n consoleLogRecordingEnabled?: boolean\n recorderVersion?: 'v1' | 'v2'\n // the API returns a decimal between 0 and 1 as a string\n sampleRate?: string | null\n minimumDurationMilliseconds?: number\n linkedFlag?: string | null\n networkPayloadCapture?: Pick<NetworkRecordOptions, 'recordBody' | 'recordHeaders'>\n }\n surveys?: boolean\n toolbarParams: ToolbarParams\n editorParams?: ToolbarParams /** @deprecated, renamed to toolbarParams, still present on older API responses */\n toolbarVersion: 'toolbar' /** @deprecated, moved to toolbarParams */\n isAuthenticated: boolean\n siteApps: { id: number; url: string }[]\n}\n\nexport type FeatureFlagsCallback = (flags: string[], variants: Record<string, string | boolean>) => void\n\n// TODO: delete custom_properties after changeless typescript refactor\nexport interface AutoCaptureCustomProperty {\n name: string\n css_selector: string\n event_selectors: string[]\n}\n\nexport interface CompressionData {\n data: string\n compression?: Compression\n}\n\nexport interface GDPROptions {\n capture?: (\n event: string,\n properties: Properties,\n options: CaptureOptions\n ) => void /** function used for capturing a PostHog event to record the opt-in action */\n captureEventName?: string /** event name to be used for capturing the opt-in action */\n captureProperties?: Properties /** set of properties to be captured along with the opt-in action */\n /** persistence mechanism used */\n persistenceType?: 'cookie' | 'localStorage' | 'localStorage+cookie'\n persistencePrefix?: string /** [__ph_opt_in_out] - custom prefix to be used in the cookie/localstorage name */\n cookieExpiration?: number /** number of days until the opt-in cookie expires */\n crossSubdomainCookie?: boolean /** whether the opt-in cookie is set as cross-subdomain or not */\n secureCookie?: boolean /** whether the opt-in cookie is set as secure or not */\n respectDnt?: boolean\n window?: Window\n}\n\nexport type RequestCallback = (response: Record<string, any>, data?: Properties) => void\n\nexport interface PersistentStore {\n is_supported: () => boolean\n error: (error: any) => void\n parse: (name: string) => any\n get: (name: string) => any\n set: (name: string, value: any, expire_days?: number | null, cross_subdomain?: boolean, secure?: boolean) => void\n remove: (name: string, cross_subdomain?: boolean) => void\n}\n\n// eslint-disable-next-line @typescript-eslint/ban-types\nexport type Breaker = {}\nexport type EventHandler = (event: Event) => boolean | void\n\nexport type ToolbarUserIntent = 'add-action' | 'edit-action'\nexport type ToolbarSource = 'url' | 'localstorage'\nexport type ToolbarVersion = 'toolbar'\n\n/* sync with posthog */\nexport interface ToolbarParams {\n token?: string /** public posthog-js token */\n temporaryToken?: string /** private temporary user token */\n actionId?: number\n userIntent?: ToolbarUserIntent\n source?: ToolbarSource\n toolbarVersion?: ToolbarVersion\n instrument?: boolean\n distinctId?: string\n userEmail?: string\n dataAttributes?: string[]\n featureFlags?: Record<string, string | boolean>\n}\n\nexport interface PostData {\n buffer?: BlobPart\n compression?: Compression\n data?: string\n}\n\nexport interface JSC {\n (): void\n [key: string]: (response: any) => void\n}\n\nexport type SnippetArrayItem = [method: string, ...args: any[]]\n\nexport type JsonType = string | number | boolean | null | { [key: string]: JsonType } | Array<JsonType>\n\n/** A feature that isn't publicly available yet.*/\nexport interface EarlyAccessFeature {\n // Sync this with the backend's EarlyAccessFeatureSerializer!\n name: string\n description: string\n stage: 'concept' | 'alpha' | 'beta'\n documentationUrl: string | null\n flagKey: string | null\n}\n\nexport type EarlyAccessFeatureCallback = (earlyAccessFeatures: EarlyAccessFeature[]) => void\n\nexport interface EarlyAccessFeatureResponse {\n earlyAccessFeatures: EarlyAccessFeature[]\n}\n\nexport type Headers = Record<string, string>\n\nexport type Body =\n | string\n | Document\n | Blob\n | ArrayBufferView\n | ArrayBuffer\n | FormData\n // rrweb uses URLSearchParams and ReadableStream<Uint8Array>\n // as part of the union for this type\n // because they don't support IE11\n // but, we do 🫠\n // what's going to happen here in IE11?\n | URLSearchParams\n | ReadableStream<Uint8Array>\n | null\n\n/* for rrweb/network@1\n ** when that is released as part of rrweb this can be removed\n ** don't rely on this type, it may change without notice\n */\nexport type InitiatorType =\n | 'audio'\n | 'beacon'\n | 'body'\n | 'css'\n | 'early-hint'\n | 'embed'\n | 'fetch'\n | 'frame'\n | 'iframe'\n | 'icon'\n | 'image'\n | 'img'\n | 'input'\n | 'link'\n | 'navigation'\n | 'object'\n | 'ping'\n | 'script'\n | 'track'\n | 'video'\n | 'xmlhttprequest'\n\nexport type NetworkRecordOptions = {\n initiatorTypes?: InitiatorType[]\n maskRequestFn?: (data: CapturedNetworkRequest) => CapturedNetworkRequest | undefined\n recordHeaders?: boolean | { request: boolean; response: boolean }\n recordBody?: boolean | string[] | { request: boolean | string[]; response: boolean | string[] }\n recordInitialRequests?: boolean\n // whether to record PerformanceEntry events for network requests\n recordPerformance?: boolean\n // the PerformanceObserver will only observe these entry types\n performanceEntryTypeToObserve: string[]\n // the maximum size of the request/response body to record\n // NB this will be at most 1MB even if set larger\n payloadSizeLimitBytes: number\n}\n\n/** @deprecated - use CapturedNetworkRequest instead */\nexport type NetworkRequest = {\n url: string\n}\n\n// In rrweb this is called NetworkRequest, but we already exposed that as having only URL\n// we also want to vary from the rrweb NetworkRequest because we want to include\n// all PerformanceEntry properties too.\n// that has 4 required properties\n// readonly duration: DOMHighResTimeStamp;\n// readonly entryType: string;\n// readonly name: string;\n// readonly startTime: DOMHighResTimeStamp;\n// NB: properties below here are ALPHA, don't rely on them, they may change without notice\nexport type CapturedNetworkRequest = Omit<PerformanceEntry, 'toJSON'> & {\n // properties below here are ALPHA, don't rely on them, they may change without notice\n method?: string\n initiatorType?: InitiatorType\n status?: number\n timeOrigin?: number\n timestamp?: number\n startTime?: number\n endTime?: number\n requestHeaders?: Headers\n requestBody?: Body\n responseHeaders?: Headers\n responseBody?: Body\n // was this captured before fetch/xhr could have been wrapped\n isInitial?: boolean\n}\n"]}
|
|
1
|
+
{"version":3,"file":"types.js","sourceRoot":"","sources":["../../src/types.ts"],"names":[],"mappings":"AAuLA,MAAM,CAAN,IAAY,WAGX;AAHD,WAAY,WAAW;IACnB,iCAAkB,CAAA;IAClB,gCAAiB,CAAA;AACrB,CAAC,EAHW,WAAW,KAAX,WAAW,QAGtB","sourcesContent":["import type { MaskInputOptions, SlimDOMOptions } from 'rrweb-snapshot'\nimport { PostHog } from './posthog-core'\nimport { RetryQueue } from './retry-queue'\n\nexport type Property = any\nexport type Properties = Record<string, Property>\n\nexport interface CaptureResult {\n uuid: string\n event: string\n properties: Properties\n $set?: Properties\n $set_once?: Properties\n timestamp?: Date\n}\nexport type CaptureCallback = (response: any, data: any) => void\n\nexport type AutocaptureCompatibleElement = 'a' | 'button' | 'form' | 'input' | 'select' | 'textarea' | 'label'\nexport type DomAutocaptureEvents = 'click' | 'change' | 'submit'\n\n/**\n * If an array is passed for an allowlist, autocapture events will only be sent for elements matching\n * at least one of the elements in the array. Multiple allowlists can be used\n */\nexport interface AutocaptureConfig {\n /**\n * List of URLs to allow autocapture on, can be strings to match\n * or regexes e.g. ['https://example.com', 'test.com/.*']\n */\n url_allowlist?: (string | RegExp)[]\n\n /**\n * List of DOM events to allow autocapture on e.g. ['click', 'change', 'submit']\n */\n dom_event_allowlist?: DomAutocaptureEvents[]\n\n /**\n * List of DOM elements to allow autocapture on\n * e.g. ['a', 'button', 'form', 'input', 'select', 'textarea', 'label']\n */\n element_allowlist?: AutocaptureCompatibleElement[]\n\n /**\n * List of CSS selectors to allow autocapture on\n * e.g. ['[ph-capture]']\n */\n css_selector_allowlist?: string[]\n\n /**\n * Exclude certain element attributes from autocapture\n * E.g. ['aria-label'] or [data-attr-pii]\n */\n element_attribute_ignorelist?: string[]\n}\n\nexport type UUIDVersion = 'og' | 'v7'\n\nexport interface PostHogConfig {\n api_host: string\n api_method: string\n api_transport: string\n ui_host: string | null\n token: string\n autocapture: boolean | AutocaptureConfig\n rageclick: boolean\n cross_subdomain_cookie: boolean\n persistence: 'localStorage' | 'cookie' | 'memory' | 'localStorage+cookie' | 'sessionStorage'\n persistence_name: string\n cookie_name: string\n loaded: (posthog_instance: PostHog) => void\n store_google: boolean\n custom_campaign_params: string[]\n // a list of strings to be tested against navigator.userAgent to determine if the source is a bot\n // this is **added to** the default list of bots that we check\n // defaults to the empty array\n custom_blocked_useragents: string[]\n save_referrer: boolean\n verbose: boolean\n capture_pageview: boolean\n capture_pageleave: boolean\n debug: boolean\n cookie_expiration: number\n upgrade: boolean\n disable_session_recording: boolean\n disable_persistence: boolean\n /** @deprecated - use `disable_persistence` instead */\n disable_cookie: boolean\n enable_recording_console_log?: boolean\n secure_cookie: boolean\n ip: boolean\n opt_out_capturing_by_default: boolean\n opt_out_persistence_by_default: boolean\n opt_out_capturing_persistence_type: 'localStorage' | 'cookie'\n opt_out_capturing_cookie_prefix: string | null\n opt_in_site_apps: boolean\n respect_dnt: boolean\n property_blacklist: string[]\n xhr_headers: { [header_name: string]: string }\n on_xhr_error: (failedRequest: XMLHttpRequest) => void\n inapp_protocol: string\n inapp_link_new_window: boolean\n request_batching: boolean\n sanitize_properties: ((properties: Properties, event_name: string) => Properties) | null\n properties_string_max_length: number\n session_recording: SessionRecordingOptions\n session_idle_timeout_seconds: number\n mask_all_element_attributes: boolean\n mask_all_text: boolean\n advanced_disable_decide: boolean\n advanced_disable_feature_flags: boolean\n advanced_disable_feature_flags_on_first_load: boolean\n advanced_disable_toolbar_metrics: boolean\n get_device_id: (uuid: string) => string\n name: string\n callback_fn: string\n _onCapture: (eventName: string, eventData: CaptureResult) => void\n capture_performance?: boolean\n // Should only be used for testing. Could negatively impact performance.\n disable_compression: boolean\n bootstrap: {\n distinctID?: string\n isIdentifiedID?: boolean\n featureFlags?: Record<string, boolean | string>\n featureFlagPayloads?: Record<string, JsonType>\n }\n segment?: any\n __preview_measure_pageview_stats?: boolean\n __preview_send_client_session_params?: boolean\n}\n\nexport interface OptInOutCapturingOptions {\n capture: (event: string, properties: Properties, options: CaptureOptions) => void\n capture_event_name: string\n capture_properties: Properties\n enable_persistence: boolean\n clear_persistence: boolean\n persistence_type: 'cookie' | 'localStorage' | 'localStorage+cookie'\n cookie_prefix: string\n cookie_expiration: number\n cross_subdomain_cookie: boolean\n secure_cookie: boolean\n}\n\nexport interface isFeatureEnabledOptions {\n send_event: boolean\n}\n\nexport interface SessionRecordingOptions {\n blockClass?: string | RegExp\n blockSelector?: string | null\n ignoreClass?: string\n maskTextClass?: string | RegExp\n maskTextSelector?: string | null\n maskTextFn?: ((text: string) => string) | null\n maskAllInputs?: boolean\n maskInputOptions?: MaskInputOptions\n maskInputFn?: ((text: string, element?: HTMLElement) => string) | null\n slimDOMOptions?: SlimDOMOptions | 'all' | true\n collectFonts?: boolean\n inlineStylesheet?: boolean\n recorderVersion?: 'v1' | 'v2'\n recordCrossOriginIframes?: boolean\n /** @deprecated - use maskCapturedNetworkRequestFn instead */\n maskNetworkRequestFn?: ((data: NetworkRequest) => NetworkRequest | null | undefined) | null\n /** Modify the network request before it is captured. Returning null or undefined stops it being captured */\n maskCapturedNetworkRequestFn?: ((data: CapturedNetworkRequest) => CapturedNetworkRequest | null | undefined) | null\n // properties below here are ALPHA, don't rely on them, they may change without notice\n // TODO which of these do we actually expose?\n // if this isn't provided a default will be used\n // this only applies to the payload recorder\n // TODO I guess it should apply to the other recorder to\n initiatorTypes?: InitiatorType[]\n recordHeaders?: boolean | { request: boolean; response: boolean }\n // true means record all bodies\n // false means record no bodies\n // string[] means record bodies matching the provided content-type headers\n recordBody?: boolean | string[] | { request: boolean | string[]; response: boolean | string[] }\n // I can't think why you wouldn't want this... so\n // recordInitialRequests?: boolean\n}\n\nexport type SessionIdChangedCallback = (sessionId: string, windowId: string | null | undefined) => void\n\nexport enum Compression {\n GZipJS = 'gzip-js',\n Base64 = 'base64',\n}\n\nexport interface XHROptions {\n transport?: 'XHR' | 'sendBeacon'\n method?: 'POST' | 'GET'\n urlQueryArgs?: { compression: Compression }\n verbose?: boolean\n blob?: boolean\n sendBeacon?: boolean\n}\n\nexport interface CaptureOptions extends XHROptions {\n $set?: Properties /** used with $identify */\n $set_once?: Properties /** used with $identify */\n _batchKey?: string /** key of queue, e.g. 'sessionRecording' vs 'event' */\n _metrics?: Properties\n _noTruncate?: boolean /** if set, overrides and disables config.properties_string_max_length */\n endpoint?: string /** defaults to '/e/' */\n send_instantly?: boolean /** if set skips the batched queue */\n timestamp?: Date\n}\n\nexport interface RetryQueueElement {\n retryAt: Date\n requestData: QueuedRequestData\n}\nexport interface QueuedRequestData {\n url: string\n data: Properties\n options: CaptureOptions\n headers?: Properties\n callback?: RequestCallback\n retriesPerformedSoFar?: number\n}\n\nexport interface XHRParams extends QueuedRequestData {\n retryQueue: RetryQueue\n onXHRError: (req: XMLHttpRequest) => void\n timeout?: number\n onResponse?: (req: XMLHttpRequest) => void\n}\n\nexport interface DecideResponse {\n status: number\n supportedCompression: Compression[]\n config: {\n enable_collect_everything: boolean\n }\n custom_properties: AutoCaptureCustomProperty[] // TODO: delete, not sent\n featureFlags: Record<string, string | boolean>\n featureFlagPayloads: Record<string, JsonType>\n errorsWhileComputingFlags: boolean\n autocapture_opt_out?: boolean\n capturePerformance?: boolean\n analytics?: {\n endpoint?: string\n }\n elementsChainAsString?: boolean\n // this is currently in development and may have breaking changes without a major version bump\n autocaptureExceptions?:\n | boolean\n | {\n endpoint?: string\n errors_to_ignore: string[]\n }\n sessionRecording?: {\n endpoint?: string\n consoleLogRecordingEnabled?: boolean\n recorderVersion?: 'v1' | 'v2'\n // the API returns a decimal between 0 and 1 as a string\n sampleRate?: string | null\n minimumDurationMilliseconds?: number\n linkedFlag?: string | null\n networkPayloadCapture?: Pick<NetworkRecordOptions, 'recordBody' | 'recordHeaders'>\n }\n surveys?: boolean\n toolbarParams: ToolbarParams\n editorParams?: ToolbarParams /** @deprecated, renamed to toolbarParams, still present on older API responses */\n toolbarVersion: 'toolbar' /** @deprecated, moved to toolbarParams */\n isAuthenticated: boolean\n siteApps: { id: number; url: string }[]\n}\n\nexport type FeatureFlagsCallback = (flags: string[], variants: Record<string, string | boolean>) => void\n\n// TODO: delete custom_properties after changeless typescript refactor\nexport interface AutoCaptureCustomProperty {\n name: string\n css_selector: string\n event_selectors: string[]\n}\n\nexport interface CompressionData {\n data: string\n compression?: Compression\n}\n\nexport interface GDPROptions {\n capture?: (\n event: string,\n properties: Properties,\n options: CaptureOptions\n ) => void /** function used for capturing a PostHog event to record the opt-in action */\n captureEventName?: string /** event name to be used for capturing the opt-in action */\n captureProperties?: Properties /** set of properties to be captured along with the opt-in action */\n /** persistence mechanism used */\n persistenceType?: 'cookie' | 'localStorage' | 'localStorage+cookie'\n persistencePrefix?: string /** [__ph_opt_in_out] - custom prefix to be used in the cookie/localstorage name */\n cookieExpiration?: number /** number of days until the opt-in cookie expires */\n crossSubdomainCookie?: boolean /** whether the opt-in cookie is set as cross-subdomain or not */\n secureCookie?: boolean /** whether the opt-in cookie is set as secure or not */\n respectDnt?: boolean\n window?: Window\n}\n\nexport type RequestCallback = (response: Record<string, any>, data?: Properties) => void\n\nexport interface PersistentStore {\n is_supported: () => boolean\n error: (error: any) => void\n parse: (name: string) => any\n get: (name: string) => any\n set: (name: string, value: any, expire_days?: number | null, cross_subdomain?: boolean, secure?: boolean) => void\n remove: (name: string, cross_subdomain?: boolean) => void\n}\n\n// eslint-disable-next-line @typescript-eslint/ban-types\nexport type Breaker = {}\nexport type EventHandler = (event: Event) => boolean | void\n\nexport type ToolbarUserIntent = 'add-action' | 'edit-action'\nexport type ToolbarSource = 'url' | 'localstorage'\nexport type ToolbarVersion = 'toolbar'\n\n/* sync with posthog */\nexport interface ToolbarParams {\n token?: string /** public posthog-js token */\n temporaryToken?: string /** private temporary user token */\n actionId?: number\n userIntent?: ToolbarUserIntent\n source?: ToolbarSource\n toolbarVersion?: ToolbarVersion\n instrument?: boolean\n distinctId?: string\n userEmail?: string\n dataAttributes?: string[]\n featureFlags?: Record<string, string | boolean>\n}\n\nexport interface PostData {\n buffer?: BlobPart\n compression?: Compression\n data?: string\n}\n\nexport interface JSC {\n (): void\n [key: string]: (response: any) => void\n}\n\nexport type SnippetArrayItem = [method: string, ...args: any[]]\n\nexport type JsonType = string | number | boolean | null | { [key: string]: JsonType } | Array<JsonType>\n\n/** A feature that isn't publicly available yet.*/\nexport interface EarlyAccessFeature {\n // Sync this with the backend's EarlyAccessFeatureSerializer!\n name: string\n description: string\n stage: 'concept' | 'alpha' | 'beta'\n documentationUrl: string | null\n flagKey: string | null\n}\n\nexport type EarlyAccessFeatureCallback = (earlyAccessFeatures: EarlyAccessFeature[]) => void\n\nexport interface EarlyAccessFeatureResponse {\n earlyAccessFeatures: EarlyAccessFeature[]\n}\n\nexport type Headers = Record<string, string>\n\nexport type Body =\n | string\n | Document\n | Blob\n | ArrayBufferView\n | ArrayBuffer\n | FormData\n // rrweb uses URLSearchParams and ReadableStream<Uint8Array>\n // as part of the union for this type\n // because they don't support IE11\n // but, we do 🫠\n // what's going to happen here in IE11?\n | URLSearchParams\n | ReadableStream<Uint8Array>\n | null\n\n/* for rrweb/network@1\n ** when that is released as part of rrweb this can be removed\n ** don't rely on this type, it may change without notice\n */\nexport type InitiatorType =\n | 'audio'\n | 'beacon'\n | 'body'\n | 'css'\n | 'early-hint'\n | 'embed'\n | 'fetch'\n | 'frame'\n | 'iframe'\n | 'icon'\n | 'image'\n | 'img'\n | 'input'\n | 'link'\n | 'navigation'\n | 'object'\n | 'ping'\n | 'script'\n | 'track'\n | 'video'\n | 'xmlhttprequest'\n\nexport type NetworkRecordOptions = {\n initiatorTypes?: InitiatorType[]\n maskRequestFn?: (data: CapturedNetworkRequest) => CapturedNetworkRequest | undefined\n recordHeaders?: boolean | { request: boolean; response: boolean }\n recordBody?: boolean | string[] | { request: boolean | string[]; response: boolean | string[] }\n recordInitialRequests?: boolean\n // whether to record PerformanceEntry events for network requests\n recordPerformance?: boolean\n // the PerformanceObserver will only observe these entry types\n performanceEntryTypeToObserve: string[]\n // the maximum size of the request/response body to record\n // NB this will be at most 1MB even if set larger\n payloadSizeLimitBytes: number\n}\n\n/** @deprecated - use CapturedNetworkRequest instead */\nexport type NetworkRequest = {\n url: string\n}\n\n// In rrweb this is called NetworkRequest, but we already exposed that as having only URL\n// we also want to vary from the rrweb NetworkRequest because we want to include\n// all PerformanceEntry properties too.\n// that has 4 required properties\n// readonly duration: DOMHighResTimeStamp;\n// readonly entryType: string;\n// readonly name: string;\n// readonly startTime: DOMHighResTimeStamp;\n// NB: properties below here are ALPHA, don't rely on them, they may change without notice\nexport type CapturedNetworkRequest = Omit<PerformanceEntry, 'toJSON'> & {\n // properties below here are ALPHA, don't rely on them, they may change without notice\n method?: string\n initiatorType?: InitiatorType\n status?: number\n timeOrigin?: number\n timestamp?: number\n startTime?: number\n endTime?: number\n requestHeaders?: Headers\n requestBody?: Body\n responseHeaders?: Headers\n responseBody?: Body\n // was this captured before fetch/xhr could have been wrapped\n isInitial?: boolean\n}\n"]}
|
package/package.json
CHANGED