posthog-js 1.76.0 → 1.77.1

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.
Files changed (129) hide show
  1. package/dist/array.full.js +2 -2
  2. package/dist/array.full.js.map +1 -1
  3. package/dist/array.js +2 -2
  4. package/dist/array.js.map +1 -1
  5. package/dist/es.js +2 -2
  6. package/dist/es.js.map +1 -1
  7. package/dist/module.d.ts +38 -6
  8. package/dist/module.js +2 -2
  9. package/dist/module.js.map +1 -1
  10. package/lib/package.json +8 -6
  11. package/lib/src/autocapture-utils.d.ts +15 -0
  12. package/lib/src/autocapture-utils.js +303 -0
  13. package/lib/src/autocapture-utils.js.map +1 -0
  14. package/lib/src/autocapture.d.ts +27 -0
  15. package/lib/src/autocapture.js +290 -0
  16. package/lib/src/autocapture.js.map +1 -0
  17. package/lib/src/base-request-queue.d.ts +12 -0
  18. package/lib/src/base-request-queue.js +33 -0
  19. package/lib/src/base-request-queue.js.map +1 -0
  20. package/lib/src/compression.d.ts +3 -0
  21. package/lib/src/compression.js +35 -0
  22. package/lib/src/compression.js.map +1 -0
  23. package/lib/src/config.d.ts +5 -0
  24. package/lib/src/config.js +9 -0
  25. package/lib/src/config.js.map +1 -0
  26. package/lib/src/constants.d.ts +19 -0
  27. package/lib/src/constants.js +41 -0
  28. package/lib/src/constants.js.map +1 -0
  29. package/lib/src/decide.d.ts +8 -0
  30. package/lib/src/decide.js +118 -0
  31. package/lib/src/decide.js.map +1 -0
  32. package/lib/src/extensions/cloud.d.ts +1 -0
  33. package/lib/src/extensions/cloud.js +2 -0
  34. package/lib/src/extensions/cloud.js.map +1 -0
  35. package/lib/src/extensions/exceptions/error-conversion.d.ts +26 -0
  36. package/lib/src/extensions/exceptions/error-conversion.js +204 -0
  37. package/lib/src/extensions/exceptions/error-conversion.js.map +1 -0
  38. package/lib/src/extensions/exceptions/exception-autocapture.d.ts +24 -0
  39. package/lib/src/extensions/exceptions/exception-autocapture.js +164 -0
  40. package/lib/src/extensions/exceptions/exception-autocapture.js.map +1 -0
  41. package/lib/src/extensions/exceptions/stack-trace.d.ts +31 -0
  42. package/lib/src/extensions/exceptions/stack-trace.js +259 -0
  43. package/lib/src/extensions/exceptions/stack-trace.js.map +1 -0
  44. package/lib/src/extensions/exceptions/type-checking.d.ts +10 -0
  45. package/lib/src/extensions/exceptions/type-checking.js +43 -0
  46. package/lib/src/extensions/exceptions/type-checking.js.map +1 -0
  47. package/lib/src/extensions/rageclick.d.ts +10 -0
  48. package/lib/src/extensions/rageclick.js +33 -0
  49. package/lib/src/extensions/rageclick.js.map +1 -0
  50. package/lib/src/extensions/segment-integration.d.ts +44 -0
  51. package/lib/src/extensions/segment-integration.js +34 -0
  52. package/lib/src/extensions/segment-integration.js.map +1 -0
  53. package/lib/src/extensions/sentry-integration.d.ts +30 -0
  54. package/lib/src/extensions/sentry-integration.js +63 -0
  55. package/lib/src/extensions/sentry-integration.js.map +1 -0
  56. package/lib/src/extensions/sessionrecording-utils.d.ts +67 -0
  57. package/lib/src/extensions/sessionrecording-utils.js +192 -0
  58. package/lib/src/extensions/sessionrecording-utils.js.map +1 -0
  59. package/lib/src/extensions/sessionrecording.d.ts +45 -0
  60. package/lib/src/extensions/sessionrecording.js +430 -0
  61. package/lib/src/extensions/sessionrecording.js.map +1 -0
  62. package/lib/src/extensions/toolbar.d.ts +18 -0
  63. package/lib/src/extensions/toolbar.js +151 -0
  64. package/lib/src/extensions/toolbar.js.map +1 -0
  65. package/lib/src/extensions/web-performance.d.ts +20 -0
  66. package/lib/src/extensions/web-performance.js +245 -0
  67. package/lib/src/extensions/web-performance.js.map +1 -0
  68. package/lib/src/gdpr-utils.d.ts +80 -0
  69. package/lib/src/gdpr-utils.js +236 -0
  70. package/lib/src/gdpr-utils.js.map +1 -0
  71. package/lib/src/loader-globals-full.d.ts +1 -0
  72. package/lib/src/loader-globals-full.js +5 -0
  73. package/lib/src/loader-globals-full.js.map +1 -0
  74. package/lib/src/loader-globals.d.ts +1 -0
  75. package/lib/src/loader-globals.js +3 -0
  76. package/lib/src/loader-globals.js.map +1 -0
  77. package/lib/src/loader-module.d.ts +4 -0
  78. package/lib/src/loader-module.js +6 -0
  79. package/lib/src/loader-module.js.map +1 -0
  80. package/lib/src/loader-recorder-v2.d.ts +2 -0
  81. package/lib/src/loader-recorder-v2.js +15 -0
  82. package/lib/src/loader-recorder-v2.js.map +1 -0
  83. package/lib/src/loader-recorder.d.ts +2 -0
  84. package/lib/src/loader-recorder.js +15 -0
  85. package/lib/src/loader-recorder.js.map +1 -0
  86. package/lib/src/page-view.d.ts +38 -0
  87. package/lib/src/page-view.js +127 -0
  88. package/lib/src/page-view.js.map +1 -0
  89. package/lib/src/posthog-core.d.ts +701 -0
  90. package/lib/src/posthog-core.js +1916 -0
  91. package/lib/src/posthog-core.js.map +1 -0
  92. package/lib/src/posthog-featureflags.d.ts +70 -0
  93. package/lib/src/posthog-featureflags.js +438 -0
  94. package/lib/src/posthog-featureflags.js.map +1 -0
  95. package/lib/src/posthog-persistence.d.ts +57 -0
  96. package/lib/src/posthog-persistence.js +256 -0
  97. package/lib/src/posthog-persistence.js.map +1 -0
  98. package/lib/src/posthog-surveys.d.ts +57 -0
  99. package/lib/src/posthog-surveys.js +76 -0
  100. package/lib/src/posthog-surveys.js.map +1 -0
  101. package/lib/src/rate-limiter.d.ts +5 -0
  102. package/lib/src/rate-limiter.js +66 -0
  103. package/lib/src/rate-limiter.js.map +1 -0
  104. package/lib/src/request-queue.d.ts +10 -0
  105. package/lib/src/request-queue.js +146 -0
  106. package/lib/src/request-queue.js.map +1 -0
  107. package/lib/src/retry-queue.d.ts +28 -0
  108. package/lib/src/retry-queue.js +198 -0
  109. package/lib/src/retry-queue.js.map +1 -0
  110. package/lib/src/send-request.d.ts +6 -0
  111. package/lib/src/send-request.js +125 -0
  112. package/lib/src/send-request.js.map +1 -0
  113. package/lib/src/sessionid.d.ts +28 -0
  114. package/lib/src/sessionid.js +205 -0
  115. package/lib/src/sessionid.js.map +1 -0
  116. package/lib/src/storage.d.ts +7 -0
  117. package/lib/src/storage.js +291 -0
  118. package/lib/src/storage.js.map +1 -0
  119. package/lib/src/types.d.ts +294 -0
  120. package/lib/src/types.js +6 -0
  121. package/lib/src/types.js.map +1 -0
  122. package/lib/src/utils.d.ts +89 -0
  123. package/lib/src/utils.js +868 -0
  124. package/lib/src/utils.js.map +1 -0
  125. package/lib/src/uuidv7.d.ts +42 -0
  126. package/lib/src/uuidv7.js +228 -0
  127. package/lib/src/uuidv7.js.map +1 -0
  128. package/package.json +8 -6
  129. package/CHANGELOG.md +0 -1145
@@ -0,0 +1,67 @@
1
+ import type { KeepIframeSrcFn, RecordPlugin, SamplingStrategy, blockClass, eventWithTime, hooksParam, listenerHandler, maskTextClass } from '@rrweb/types';
2
+ import type { Mirror, MaskInputOptions, MaskInputFn, MaskTextFn, SlimDOMOptions, DataURLOptions } from 'rrweb-snapshot';
3
+ export declare const replacementImageURI = "data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMTYiIGhlaWdodD0iMTYiIHZpZXdCb3g9IjAgMCAxNiAxNiIgZmlsbD0ibm9uZSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj4KPHJlY3Qgd2lkdGg9IjE2IiBoZWlnaHQ9IjE2IiBmaWxsPSJibGFjayIvPgo8cGF0aCBkPSJNOCAwSDE2TDAgMTZWOEw4IDBaIiBmaWxsPSIjMkQyRDJEIi8+CjxwYXRoIGQ9Ik0xNiA4VjE2SDhMMTYgOFoiIGZpbGw9IiMyRDJEMkQiLz4KPC9zdmc+Cg==";
4
+ export declare const FULL_SNAPSHOT_EVENT_TYPE = 2;
5
+ export declare const META_EVENT_TYPE = 4;
6
+ export declare const INCREMENTAL_SNAPSHOT_EVENT_TYPE = 3;
7
+ export declare const PLUGIN_EVENT_TYPE = 6;
8
+ export declare const MUTATION_SOURCE_TYPE = 0;
9
+ export declare const MAX_MESSAGE_SIZE = 5000000;
10
+ export declare type rrwebRecord = {
11
+ (options: recordOptions<eventWithTime>): listenerHandler;
12
+ addCustomEvent: (tag: string, payload: any) => void;
13
+ takeFullSnapshot: () => void;
14
+ mirror: Mirror;
15
+ };
16
+ export declare type recordOptions<T> = {
17
+ emit?: (e: T, isCheckout?: boolean) => void;
18
+ checkoutEveryNth?: number;
19
+ checkoutEveryNms?: number;
20
+ blockClass?: blockClass;
21
+ blockSelector?: string;
22
+ ignoreClass?: string;
23
+ maskTextClass?: maskTextClass;
24
+ maskTextSelector?: string;
25
+ maskAllInputs?: boolean;
26
+ maskInputOptions?: MaskInputOptions;
27
+ maskInputFn?: MaskInputFn;
28
+ maskTextFn?: MaskTextFn;
29
+ slimDOMOptions?: SlimDOMOptions | 'all' | true;
30
+ ignoreCSSAttributes?: Set<string>;
31
+ inlineStylesheet?: boolean;
32
+ hooks?: hooksParam;
33
+ sampling?: SamplingStrategy;
34
+ dataURLOptions?: DataURLOptions;
35
+ recordCanvas?: boolean;
36
+ recordCrossOriginIframes?: boolean;
37
+ recordAfter?: 'DOMContentLoaded' | 'load';
38
+ userTriggeredOnInput?: boolean;
39
+ collectFonts?: boolean;
40
+ inlineImages?: boolean;
41
+ plugins?: RecordPlugin[];
42
+ mousemoveWait?: number;
43
+ keepIframeSrcFn?: KeepIframeSrcFn;
44
+ };
45
+ export declare function ensureMaxMessageSize(data: eventWithTime): {
46
+ event: eventWithTime;
47
+ size: number;
48
+ };
49
+ export declare const CONSOLE_LOG_PLUGIN_NAME = "rrweb/console@1";
50
+ export declare function truncateLargeConsoleLogs(_event: eventWithTime): eventWithTime;
51
+ export declare class MutationRateLimiter {
52
+ private readonly rrweb;
53
+ private readonly options;
54
+ private bucketSize;
55
+ private refillRate;
56
+ private mutationBuckets;
57
+ private loggedTracker;
58
+ constructor(rrweb: rrwebRecord, options?: {
59
+ bucketSize?: number;
60
+ refillRate?: number;
61
+ onBlockedNode?: (id: number, node: Node | null) => void;
62
+ });
63
+ private refillBuckets;
64
+ private getNodeOrRelevantParent;
65
+ private numberOfChanges;
66
+ throttleMutations: (event: eventWithTime) => eventWithTime | undefined;
67
+ }
@@ -0,0 +1,192 @@
1
+ var __values = (this && this.__values) || function(o) {
2
+ var s = typeof Symbol === "function" && Symbol.iterator, m = s && o[s], i = 0;
3
+ if (m) return m.call(o);
4
+ if (o && typeof o.length === "number") return {
5
+ next: function () {
6
+ if (o && i >= o.length) o = void 0;
7
+ return { value: o && o[i++], done: !o };
8
+ }
9
+ };
10
+ throw new TypeError(s ? "Object is not iterable." : "Symbol.iterator is not defined.");
11
+ };
12
+ var __read = (this && this.__read) || function (o, n) {
13
+ var m = typeof Symbol === "function" && o[Symbol.iterator];
14
+ if (!m) return o;
15
+ var i = m.call(o), r, ar = [], e;
16
+ try {
17
+ while ((n === void 0 || n-- > 0) && !(r = i.next()).done) ar.push(r.value);
18
+ }
19
+ catch (error) { e = { error: error }; }
20
+ finally {
21
+ try {
22
+ if (r && !r.done && (m = i["return"])) m.call(i);
23
+ }
24
+ finally { if (e) throw e.error; }
25
+ }
26
+ return ar;
27
+ };
28
+ export var replacementImageURI = 'data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMTYiIGhlaWdodD0iMTYiIHZpZXdCb3g9IjAgMCAxNiAxNiIgZmlsbD0ibm9uZSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj4KPHJlY3Qgd2lkdGg9IjE2IiBoZWlnaHQ9IjE2IiBmaWxsPSJibGFjayIvPgo8cGF0aCBkPSJNOCAwSDE2TDAgMTZWOEw4IDBaIiBmaWxsPSIjMkQyRDJEIi8+CjxwYXRoIGQ9Ik0xNiA4VjE2SDhMMTYgOFoiIGZpbGw9IiMyRDJEMkQiLz4KPC9zdmc+Cg==';
29
+ export var FULL_SNAPSHOT_EVENT_TYPE = 2;
30
+ export var META_EVENT_TYPE = 4;
31
+ export var INCREMENTAL_SNAPSHOT_EVENT_TYPE = 3;
32
+ export var PLUGIN_EVENT_TYPE = 6;
33
+ export var MUTATION_SOURCE_TYPE = 0;
34
+ export var MAX_MESSAGE_SIZE = 5000000; // ~5mb
35
+ /*
36
+ * Check whether a data payload is nearing 5mb. If it is, it checks the data for
37
+ * data URIs (the likely culprit for large payloads). If it finds data URIs, it either replaces
38
+ * it with a generic image (if it's an image) or removes it.
39
+ * @data {object} the rr-web data object
40
+ * @returns {object} the rr-web data object with data uris filtered out
41
+ */
42
+ export function ensureMaxMessageSize(data) {
43
+ var e_1, _a;
44
+ var stringifiedData = JSON.stringify(data);
45
+ // Note: with compression, this limit may be able to be increased
46
+ // but we're assuming most of the size is from a data uri which
47
+ // is unlikely to be compressed further
48
+ if (stringifiedData.length > MAX_MESSAGE_SIZE) {
49
+ // Regex that matches the pattern for a dataURI with the shape 'data:{mime type};{encoding},{data}'. It:
50
+ // 1) Checks if the pattern starts with 'data:' (potentially, not at the start of the string)
51
+ // 2) Extracts the mime type of the data uri in the first group
52
+ // 3) Determines when the data URI ends.Depending on if it's used in the src tag or css, it can end with a ) or "
53
+ var dataURIRegex = /data:([\w/\-.]+);(\w+),([^)"]*)/gim;
54
+ var matches = stringifiedData.matchAll(dataURIRegex);
55
+ try {
56
+ for (var matches_1 = __values(matches), matches_1_1 = matches_1.next(); !matches_1_1.done; matches_1_1 = matches_1.next()) {
57
+ var match = matches_1_1.value;
58
+ if (match[1].toLocaleLowerCase().slice(0, 6) === 'image/') {
59
+ stringifiedData = stringifiedData.replace(match[0], replacementImageURI);
60
+ }
61
+ else {
62
+ stringifiedData = stringifiedData.replace(match[0], '');
63
+ }
64
+ }
65
+ }
66
+ catch (e_1_1) { e_1 = { error: e_1_1 }; }
67
+ finally {
68
+ try {
69
+ if (matches_1_1 && !matches_1_1.done && (_a = matches_1.return)) _a.call(matches_1);
70
+ }
71
+ finally { if (e_1) throw e_1.error; }
72
+ }
73
+ }
74
+ return { event: JSON.parse(stringifiedData), size: stringifiedData.length };
75
+ }
76
+ export var CONSOLE_LOG_PLUGIN_NAME = 'rrweb/console@1'; // The name of the rr-web plugin that emits console logs
77
+ // Console logs can be really large. This function truncates large logs
78
+ // It's a simple function that just truncates long strings.
79
+ // TODO: Ideally this function would have better handling of objects + lists,
80
+ // so they could still be rendered in a pretty way after truncation.
81
+ export function truncateLargeConsoleLogs(_event) {
82
+ var event = _event;
83
+ var MAX_STRING_SIZE = 2000; // Maximum number of characters allowed in a string
84
+ var MAX_STRINGS_PER_LOG = 10; // A log can consist of multiple strings (e.g. consol.log('string1', 'string2'))
85
+ if (event &&
86
+ typeof event === 'object' &&
87
+ event.type === PLUGIN_EVENT_TYPE &&
88
+ typeof event.data === 'object' &&
89
+ event.data.plugin === CONSOLE_LOG_PLUGIN_NAME) {
90
+ // Note: event.data.payload.payload comes from rr-web, and is an array of strings
91
+ if (event.data.payload.payload.length > MAX_STRINGS_PER_LOG) {
92
+ event.data.payload.payload = event.data.payload.payload.slice(0, MAX_STRINGS_PER_LOG);
93
+ event.data.payload.payload.push('...[truncated]');
94
+ }
95
+ var updatedPayload = [];
96
+ for (var i = 0; i < event.data.payload.payload.length; i++) {
97
+ if (event.data.payload.payload[i] && // Value can be null
98
+ event.data.payload.payload[i].length > MAX_STRING_SIZE) {
99
+ updatedPayload.push(event.data.payload.payload[i].slice(0, MAX_STRING_SIZE) + '...[truncated]');
100
+ }
101
+ else {
102
+ updatedPayload.push(event.data.payload.payload[i]);
103
+ }
104
+ }
105
+ event.data.payload.payload = updatedPayload;
106
+ // Return original type
107
+ return _event;
108
+ }
109
+ return _event;
110
+ }
111
+ var MutationRateLimiter = /** @class */ (function () {
112
+ function MutationRateLimiter(rrweb, options) {
113
+ if (options === void 0) { options = {}; }
114
+ var _this = this;
115
+ var _a, _b;
116
+ this.rrweb = rrweb;
117
+ this.options = options;
118
+ this.bucketSize = 100;
119
+ this.refillRate = 10;
120
+ this.mutationBuckets = {};
121
+ this.loggedTracker = {};
122
+ this.refillBuckets = function () {
123
+ Object.keys(_this.mutationBuckets).forEach(function (key) {
124
+ _this.mutationBuckets[key] = _this.mutationBuckets[key] + _this.refillRate;
125
+ if (_this.mutationBuckets[key] >= _this.bucketSize) {
126
+ delete _this.mutationBuckets[key];
127
+ }
128
+ });
129
+ };
130
+ this.getNodeOrRelevantParent = function (id) {
131
+ // For some nodes we know they are part of a larger tree such as an SVG.
132
+ // For those we want to block the entire node, not just the specific attribute
133
+ var node = _this.rrweb.mirror.getNode(id);
134
+ // Check if the node is an Element and then find the closest parent that is an SVG
135
+ if ((node === null || node === void 0 ? void 0 : node.nodeName) !== 'svg' && node instanceof Element) {
136
+ var closestSVG = node.closest('svg');
137
+ if (closestSVG) {
138
+ return [_this.rrweb.mirror.getId(closestSVG), closestSVG];
139
+ }
140
+ }
141
+ return [id, node];
142
+ };
143
+ this.numberOfChanges = function (data) {
144
+ var _a, _b, _c, _d, _e, _f, _g, _h;
145
+ return (((_b = (_a = data.removes) === null || _a === void 0 ? void 0 : _a.length) !== null && _b !== void 0 ? _b : 0) +
146
+ ((_d = (_c = data.attributes) === null || _c === void 0 ? void 0 : _c.length) !== null && _d !== void 0 ? _d : 0) +
147
+ ((_f = (_e = data.texts) === null || _e === void 0 ? void 0 : _e.length) !== null && _f !== void 0 ? _f : 0) +
148
+ ((_h = (_g = data.adds) === null || _g === void 0 ? void 0 : _g.length) !== null && _h !== void 0 ? _h : 0));
149
+ };
150
+ this.throttleMutations = function (event) {
151
+ if (event.type !== INCREMENTAL_SNAPSHOT_EVENT_TYPE || event.data.source !== MUTATION_SOURCE_TYPE) {
152
+ return event;
153
+ }
154
+ var data = event.data;
155
+ var initialMutationCount = _this.numberOfChanges(data);
156
+ if (data.attributes) {
157
+ // Most problematic mutations come from attrs where the style or minor properties are changed rapidly
158
+ data.attributes = data.attributes.filter(function (attr) {
159
+ var _a, _b, _c;
160
+ var _d = __read(_this.getNodeOrRelevantParent(attr.id), 2), nodeId = _d[0], node = _d[1];
161
+ if (_this.mutationBuckets[nodeId] === 0) {
162
+ return false;
163
+ }
164
+ _this.mutationBuckets[nodeId] = (_a = _this.mutationBuckets[nodeId]) !== null && _a !== void 0 ? _a : _this.bucketSize;
165
+ _this.mutationBuckets[nodeId] = Math.max(_this.mutationBuckets[nodeId] - 1, 0);
166
+ if (_this.mutationBuckets[nodeId] === 0) {
167
+ if (!_this.loggedTracker[nodeId]) {
168
+ _this.loggedTracker[nodeId] = true;
169
+ (_c = (_b = _this.options).onBlockedNode) === null || _c === void 0 ? void 0 : _c.call(_b, nodeId, node);
170
+ }
171
+ }
172
+ return attr;
173
+ });
174
+ }
175
+ // Check if every part of the mutation is empty in which case there is nothing to do
176
+ var mutationCount = _this.numberOfChanges(data);
177
+ if (mutationCount === 0 && initialMutationCount !== mutationCount) {
178
+ // If we have modified the mutation count and the remaining count is 0, then we don't need the event.
179
+ return;
180
+ }
181
+ return event;
182
+ };
183
+ this.refillRate = (_a = this.options.refillRate) !== null && _a !== void 0 ? _a : this.refillRate;
184
+ this.bucketSize = (_b = this.options.bucketSize) !== null && _b !== void 0 ? _b : this.bucketSize;
185
+ setInterval(function () {
186
+ _this.refillBuckets();
187
+ }, 1000);
188
+ }
189
+ return MutationRateLimiter;
190
+ }());
191
+ export { MutationRateLimiter };
192
+ //# sourceMappingURL=sessionrecording-utils.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"sessionrecording-utils.js","sourceRoot":"","sources":["../../../src/extensions/sessionrecording-utils.ts"],"names":[],"mappings":"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","sourcesContent":["import type {\n KeepIframeSrcFn,\n RecordPlugin,\n SamplingStrategy,\n blockClass,\n eventWithTime,\n hooksParam,\n listenerHandler,\n maskTextClass,\n pluginEvent,\n mutationCallbackParam,\n} from '@rrweb/types'\nimport type { Mirror, MaskInputOptions, MaskInputFn, MaskTextFn, SlimDOMOptions, DataURLOptions } from 'rrweb-snapshot'\n\nexport const replacementImageURI =\n 'data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMTYiIGhlaWdodD0iMTYiIHZpZXdCb3g9IjAgMCAxNiAxNiIgZmlsbD0ibm9uZSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj4KPHJlY3Qgd2lkdGg9IjE2IiBoZWlnaHQ9IjE2IiBmaWxsPSJibGFjayIvPgo8cGF0aCBkPSJNOCAwSDE2TDAgMTZWOEw4IDBaIiBmaWxsPSIjMkQyRDJEIi8+CjxwYXRoIGQ9Ik0xNiA4VjE2SDhMMTYgOFoiIGZpbGw9IiMyRDJEMkQiLz4KPC9zdmc+Cg=='\n\nexport const FULL_SNAPSHOT_EVENT_TYPE = 2\nexport const META_EVENT_TYPE = 4\nexport const INCREMENTAL_SNAPSHOT_EVENT_TYPE = 3\nexport const PLUGIN_EVENT_TYPE = 6\nexport const MUTATION_SOURCE_TYPE = 0\n\nexport const MAX_MESSAGE_SIZE = 5000000 // ~5mb\n\nexport type rrwebRecord = {\n (options: recordOptions<eventWithTime>): listenerHandler\n addCustomEvent: (tag: string, payload: any) => void\n takeFullSnapshot: () => void\n mirror: Mirror\n}\n\nexport declare type recordOptions<T> = {\n emit?: (e: T, isCheckout?: boolean) => void\n checkoutEveryNth?: number\n checkoutEveryNms?: number\n blockClass?: blockClass\n blockSelector?: string\n ignoreClass?: string\n maskTextClass?: maskTextClass\n maskTextSelector?: string\n maskAllInputs?: boolean\n maskInputOptions?: MaskInputOptions\n maskInputFn?: MaskInputFn\n maskTextFn?: MaskTextFn\n slimDOMOptions?: SlimDOMOptions | 'all' | true\n ignoreCSSAttributes?: Set<string>\n inlineStylesheet?: boolean\n hooks?: hooksParam\n // packFn?: PackFn\n sampling?: SamplingStrategy\n dataURLOptions?: DataURLOptions\n recordCanvas?: boolean\n recordCrossOriginIframes?: boolean\n recordAfter?: 'DOMContentLoaded' | 'load'\n userTriggeredOnInput?: boolean\n collectFonts?: boolean\n inlineImages?: boolean\n plugins?: RecordPlugin[]\n mousemoveWait?: number\n keepIframeSrcFn?: KeepIframeSrcFn\n // errorHandler?: ErrorHandler\n}\n\n/*\n * Check whether a data payload is nearing 5mb. If it is, it checks the data for\n * data URIs (the likely culprit for large payloads). If it finds data URIs, it either replaces\n * it with a generic image (if it's an image) or removes it.\n * @data {object} the rr-web data object\n * @returns {object} the rr-web data object with data uris filtered out\n */\nexport function ensureMaxMessageSize(data: eventWithTime): { event: eventWithTime; size: number } {\n let stringifiedData = JSON.stringify(data)\n // Note: with compression, this limit may be able to be increased\n // but we're assuming most of the size is from a data uri which\n // is unlikely to be compressed further\n if (stringifiedData.length > MAX_MESSAGE_SIZE) {\n // Regex that matches the pattern for a dataURI with the shape 'data:{mime type};{encoding},{data}'. It:\n // 1) Checks if the pattern starts with 'data:' (potentially, not at the start of the string)\n // 2) Extracts the mime type of the data uri in the first group\n // 3) Determines when the data URI ends.Depending on if it's used in the src tag or css, it can end with a ) or \"\n const dataURIRegex = /data:([\\w/\\-.]+);(\\w+),([^)\"]*)/gim\n const matches = stringifiedData.matchAll(dataURIRegex)\n for (const match of matches) {\n if (match[1].toLocaleLowerCase().slice(0, 6) === 'image/') {\n stringifiedData = stringifiedData.replace(match[0], replacementImageURI)\n } else {\n stringifiedData = stringifiedData.replace(match[0], '')\n }\n }\n }\n return { event: JSON.parse(stringifiedData), size: stringifiedData.length }\n}\n\nexport const CONSOLE_LOG_PLUGIN_NAME = 'rrweb/console@1' // The name of the rr-web plugin that emits console logs\n\n// Console logs can be really large. This function truncates large logs\n// It's a simple function that just truncates long strings.\n// TODO: Ideally this function would have better handling of objects + lists,\n// so they could still be rendered in a pretty way after truncation.\nexport function truncateLargeConsoleLogs(_event: eventWithTime) {\n const event = _event as pluginEvent<{ payload: string[] }>\n\n const MAX_STRING_SIZE = 2000 // Maximum number of characters allowed in a string\n const MAX_STRINGS_PER_LOG = 10 // A log can consist of multiple strings (e.g. consol.log('string1', 'string2'))\n\n if (\n event &&\n typeof event === 'object' &&\n event.type === PLUGIN_EVENT_TYPE &&\n typeof event.data === 'object' &&\n event.data.plugin === CONSOLE_LOG_PLUGIN_NAME\n ) {\n // Note: event.data.payload.payload comes from rr-web, and is an array of strings\n if (event.data.payload.payload.length > MAX_STRINGS_PER_LOG) {\n event.data.payload.payload = event.data.payload.payload.slice(0, MAX_STRINGS_PER_LOG)\n event.data.payload.payload.push('...[truncated]')\n }\n const updatedPayload = []\n for (let i = 0; i < event.data.payload.payload.length; i++) {\n if (\n event.data.payload.payload[i] && // Value can be null\n event.data.payload.payload[i].length > MAX_STRING_SIZE\n ) {\n updatedPayload.push(event.data.payload.payload[i].slice(0, MAX_STRING_SIZE) + '...[truncated]')\n } else {\n updatedPayload.push(event.data.payload.payload[i])\n }\n }\n event.data.payload.payload = updatedPayload\n // Return original type\n return _event\n }\n return _event\n}\n\nexport class MutationRateLimiter {\n private bucketSize = 100\n private refillRate = 10\n private mutationBuckets: Record<string, number> = {}\n private loggedTracker: Record<string, boolean> = {}\n\n constructor(\n private readonly rrweb: rrwebRecord,\n private readonly options: {\n bucketSize?: number\n refillRate?: number\n onBlockedNode?: (id: number, node: Node | null) => void\n } = {}\n ) {\n this.refillRate = this.options.refillRate ?? this.refillRate\n this.bucketSize = this.options.bucketSize ?? this.bucketSize\n setInterval(() => {\n this.refillBuckets()\n }, 1000)\n }\n\n private refillBuckets = () => {\n Object.keys(this.mutationBuckets).forEach((key) => {\n this.mutationBuckets[key] = this.mutationBuckets[key] + this.refillRate\n\n if (this.mutationBuckets[key] >= this.bucketSize) {\n delete this.mutationBuckets[key]\n }\n })\n }\n\n private getNodeOrRelevantParent = (id: number): [number, Node | null] => {\n // For some nodes we know they are part of a larger tree such as an SVG.\n // For those we want to block the entire node, not just the specific attribute\n\n const node = this.rrweb.mirror.getNode(id)\n\n // Check if the node is an Element and then find the closest parent that is an SVG\n if (node?.nodeName !== 'svg' && node instanceof Element) {\n const closestSVG = node.closest('svg')\n\n if (closestSVG) {\n return [this.rrweb.mirror.getId(closestSVG), closestSVG]\n }\n }\n\n return [id, node]\n }\n\n private numberOfChanges = (data: Partial<mutationCallbackParam>) => {\n return (\n (data.removes?.length ?? 0) +\n (data.attributes?.length ?? 0) +\n (data.texts?.length ?? 0) +\n (data.adds?.length ?? 0)\n )\n }\n\n public throttleMutations = (event: eventWithTime) => {\n if (event.type !== INCREMENTAL_SNAPSHOT_EVENT_TYPE || event.data.source !== MUTATION_SOURCE_TYPE) {\n return event\n }\n\n const data = event.data as Partial<mutationCallbackParam>\n const initialMutationCount = this.numberOfChanges(data)\n\n if (data.attributes) {\n // Most problematic mutations come from attrs where the style or minor properties are changed rapidly\n data.attributes = data.attributes.filter((attr) => {\n const [nodeId, node] = this.getNodeOrRelevantParent(attr.id)\n\n if (this.mutationBuckets[nodeId] === 0) {\n return false\n }\n\n this.mutationBuckets[nodeId] = this.mutationBuckets[nodeId] ?? this.bucketSize\n this.mutationBuckets[nodeId] = Math.max(this.mutationBuckets[nodeId] - 1, 0)\n\n if (this.mutationBuckets[nodeId] === 0) {\n if (!this.loggedTracker[nodeId]) {\n this.loggedTracker[nodeId] = true\n this.options.onBlockedNode?.(nodeId, node)\n }\n }\n\n return attr\n })\n }\n\n // Check if every part of the mutation is empty in which case there is nothing to do\n const mutationCount = this.numberOfChanges(data)\n\n if (mutationCount === 0 && initialMutationCount !== mutationCount) {\n // If we have modified the mutation count and the remaining count is 0, then we don't need the event.\n return\n }\n return event\n }\n}\n"]}
@@ -0,0 +1,45 @@
1
+ import { rrwebRecord } from './sessionrecording-utils';
2
+ import { PostHog } from '../posthog-core';
3
+ import { DecideResponse } from '../types';
4
+ import type { eventWithTime, listenerHandler } from '@rrweb/types';
5
+ export declare const RECORDING_IDLE_ACTIVITY_TIMEOUT_MS: number;
6
+ export declare const RECORDING_MAX_EVENT_SIZE: number;
7
+ export declare const RECORDING_BUFFER_TIMEOUT = 2000;
8
+ export declare const SESSION_RECORDING_BATCH_KEY = "sessionRecording";
9
+ export declare class SessionRecording {
10
+ private instance;
11
+ private emit;
12
+ private endpoint;
13
+ private windowId;
14
+ private sessionId;
15
+ private lastActivityTimestamp;
16
+ private flushBufferTimer?;
17
+ private buffer?;
18
+ private mutationRateLimiter?;
19
+ captureStarted: boolean;
20
+ snapshots: any[];
21
+ stopRrweb: listenerHandler | undefined;
22
+ receivedDecide: boolean;
23
+ rrwebRecord: rrwebRecord | undefined;
24
+ recorderVersion?: string;
25
+ isIdle: boolean;
26
+ constructor(instance: PostHog);
27
+ startRecordingIfEnabled(): void;
28
+ started(): boolean;
29
+ stopRecording(): void;
30
+ isRecordingEnabled(): boolean;
31
+ isConsoleLogCaptureEnabled(): boolean;
32
+ getRecordingVersion(): any;
33
+ afterDecideResponse(response: DecideResponse): void;
34
+ log(message: string, level?: 'log' | 'warn' | 'error'): void;
35
+ private startCaptureAndTrySendingQueuedSnapshots;
36
+ private _startCapture;
37
+ private _isInteractiveEvent;
38
+ private _updateWindowAndSessionIds;
39
+ private _tryTakeFullSnapshot;
40
+ private _onScriptLoaded;
41
+ onRRwebEmit(rawEvent: eventWithTime): void;
42
+ private _flushBuffer;
43
+ private _captureSnapshotBuffered;
44
+ private _captureSnapshot;
45
+ }