@posthog/browser-common 0.9.3 → 0.9.5

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/logs.mjs ADDED
@@ -0,0 +1,428 @@
1
+ import { PostHogLogs, PostHogPersistedProperty, buildOtlpLogsPayload, buildResourceAttributes, isNullish } from "@posthog/core";
2
+ import { continueWith } from "./utils/promise-utils.mjs";
3
+ import { addEventListener } from "./utils/general-utils.mjs";
4
+ import { createLogger } from "./utils/logger.mjs";
5
+ import { resolveLogsConfig } from "./logs-config.mjs";
6
+ import { BUFFERED_CONSOLE_LEVELS } from "./logs-types.mjs";
7
+ import { patch } from "./utils/patch.mjs";
8
+ import { originalConsoleMethod } from "./utils/console-original.mjs";
9
+ import { isStatusZeroFailureCircuitBreakerTripped, updateStatusZeroFailureCount } from "./utils/request-reachability.mjs";
10
+ const RECORDER_MAX_AGE_MS = 30000;
11
+ const CONSOLE_SCOPE_NAME = 'console';
12
+ const LOGS_SEND_TIMEOUT_MS = 90000;
13
+ const MAX_CONSECUTIVE_STATUS_ZERO_FAILURES = 3;
14
+ const HANDLED_LOGS_REQUEST_ERROR = '__posthogHandledLogsRequestError';
15
+ const markLogsRequestErrorAsHandled = (error, fallbackMessage)=>{
16
+ const handledError = error instanceof Error ? error : new Error(fallbackMessage);
17
+ handledError[HANDLED_LOGS_REQUEST_ERROR] = true;
18
+ return handledError;
19
+ };
20
+ const isHandledLogsRequestError = (error)=>!!error && 'object' == typeof error && true === error[HANDLED_LOGS_REQUEST_ERROR];
21
+ class logs_PostHogLogs {
22
+ get _coreLogger() {
23
+ return {
24
+ ...this._logger,
25
+ error: (...args)=>{
26
+ if (!args.some(isHandledLogsRequestError)) this._logger.error(...args);
27
+ }
28
+ };
29
+ }
30
+ constructor(_configSource, _getSdkContext){
31
+ this._configSource = _configSource;
32
+ this._getSdkContext = _getSdkContext;
33
+ this.name = 'logs';
34
+ this._isLogsEnabled = false;
35
+ this._isLoaded = false;
36
+ this._isLoading = false;
37
+ this._logger = createLogger('[logs]');
38
+ this._queue = [];
39
+ this._consoleQueue = [];
40
+ this._consecutiveStatusZeroFailures = 0;
41
+ this._setupStarted = false;
42
+ this._disposed = false;
43
+ this._consoleBuffer = [];
44
+ this._consoleRecorderUnpatchers = [];
45
+ this._isRecordingConsole = false;
46
+ this._isRecordingConsoleEntry = false;
47
+ this._listeningForReconnect = false;
48
+ this._onReconnect = ()=>{
49
+ if (this._disposed) return;
50
+ this._consecutiveStatusZeroFailures = 0;
51
+ this._core?.onReconnect();
52
+ this._consoleCore?.onReconnect();
53
+ };
54
+ this._isLogsEnabled = !!_configSource.get()?.captureConsoleLogs;
55
+ }
56
+ get _isRequestReady() {
57
+ return true;
58
+ }
59
+ _getConsoleLoader() {}
60
+ _listenForReconnect() {
61
+ if (this._listeningForReconnect) return;
62
+ try {
63
+ this._window = "u" < typeof window ? void 0 : window;
64
+ } catch {
65
+ this._window = void 0;
66
+ }
67
+ if (this._window) {
68
+ addEventListener(this._window, 'online', this._onReconnect);
69
+ this._listeningForReconnect = true;
70
+ }
71
+ }
72
+ _buildCore(getQueue, setQueue, opts, scopeName) {
73
+ this._listenForReconnect();
74
+ const config = resolveLogsConfig(this._configSource.get(), opts);
75
+ const core = new PostHogLogs(this._createHost(getQueue, setQueue), config, this._coreLogger, ()=>this._getSdkContext(), (fn)=>fn(), void 0, scopeName);
76
+ return [
77
+ core,
78
+ config
79
+ ];
80
+ }
81
+ _getCore() {
82
+ const logsConfig = this._configSource.get();
83
+ if (!this._core || this._resolvedFrom !== logsConfig) {
84
+ this._core?.reset();
85
+ this._resolvedFrom = logsConfig;
86
+ [this._core, this._resolvedConfig] = this._buildCore(()=>this._queue, (q)=>{
87
+ this._queue = q;
88
+ });
89
+ }
90
+ return this._core;
91
+ }
92
+ _getConsoleCore() {
93
+ const logsConfig = this._configSource.get();
94
+ if (!this._consoleCore || this._consoleResolvedFrom !== logsConfig) {
95
+ this._consoleCore?.reset();
96
+ this._consoleResolvedFrom = logsConfig;
97
+ [this._consoleCore, this._consoleResolvedConfig] = this._buildCore(()=>this._consoleQueue, (q)=>{
98
+ this._consoleQueue = q;
99
+ }, {
100
+ serviceNameDefault: 'posthog-browser-logs',
101
+ consoleCapture: true
102
+ }, CONSOLE_SCOPE_NAME);
103
+ }
104
+ return this._consoleCore;
105
+ }
106
+ setup(client) {
107
+ if (this._disposed || this._setupStarted) return;
108
+ this._setupStarted = true;
109
+ this._client = client;
110
+ this._logger = client.logger.createLogger('[logs]');
111
+ return continueWith(client.kv.initialize(), ()=>{
112
+ if (!this._disposed) this._finishSetup(client);
113
+ });
114
+ }
115
+ _finishSetup(client) {
116
+ this._listenForReconnect();
117
+ if (this._configSource.get()?.captureConsoleLogs) this._isLogsEnabled = true;
118
+ if (this._isLogsEnabled || this._configSource.remoteConfigWillArrive && client.kv.get(this._configSource.captureHintKey)) this._startConsoleRecorder();
119
+ let replayedEnabledConfig = false;
120
+ const subscription = client.onRemoteConfig((result)=>{
121
+ replayedEnabledConfig = result.ok && result.config.logs?.captureConsoleLogs === true;
122
+ this.onRemoteConfig(result);
123
+ });
124
+ if (this._disposed) return void subscription.dispose();
125
+ this._remoteConfigSubscription = subscription;
126
+ if (!replayedEnabledConfig) this.loadIfEnabled();
127
+ }
128
+ dispose() {
129
+ if (this._disposed) return;
130
+ this._disposed = true;
131
+ this._stopConsoleRecorder();
132
+ this._remoteConfigSubscription?.dispose();
133
+ this._remoteConfigSubscription = void 0;
134
+ this._client = void 0;
135
+ this._isLoading = false;
136
+ this._window?.removeEventListener('online', this._onReconnect);
137
+ this._consoleLogsDispose?.();
138
+ this._consoleLogsDispose = void 0;
139
+ this._core?.clearQueue();
140
+ this._consoleCore?.clearQueue();
141
+ this._core?.reset();
142
+ this._consoleCore?.reset();
143
+ }
144
+ onRemoteConfig(result) {
145
+ if (this._disposed) return;
146
+ const logCapture = result.ok ? result.config.logs?.captureConsoleLogs : void 0;
147
+ if (isNullish(logCapture)) return void this._stopRecorderStartedByPersistedHint();
148
+ this._client?.kv.set(this._configSource.captureHintKey, !!logCapture);
149
+ if (!logCapture) return void this._stopRecorderStartedByPersistedHint();
150
+ this._isLogsEnabled = true;
151
+ if (!this._isLoaded) this._startConsoleRecorder();
152
+ this.loadIfEnabled();
153
+ }
154
+ reset() {
155
+ this._stopConsoleRecorder();
156
+ this._core?.clearQueue();
157
+ this._queue = [];
158
+ this._core?.reset();
159
+ this._consoleCore?.clearQueue();
160
+ this._consoleQueue = [];
161
+ this._consoleCore?.reset();
162
+ this._consecutiveStatusZeroFailures = 0;
163
+ }
164
+ captureLog(options) {
165
+ if (!this._disposed && this._client) this._getCore().captureLog(options);
166
+ }
167
+ captureConsoleLog(options) {
168
+ if (!this._disposed && this._client) this._getConsoleCore().captureLog(options);
169
+ }
170
+ captureBufferedConsoleLog(options, context, occurredAtMs) {
171
+ if (!this._disposed && this._client) this._getConsoleCore().captureLog(options, {
172
+ context,
173
+ occurredAtMs
174
+ });
175
+ }
176
+ _onOptOut() {
177
+ this._stopConsoleRecorder();
178
+ this._consoleCore?.clearQueue();
179
+ this._consoleQueue = [];
180
+ }
181
+ _stopRecorderStartedByPersistedHint() {
182
+ if (this._isLogsEnabled) return;
183
+ this._stopConsoleRecorder();
184
+ }
185
+ _startConsoleRecorder() {
186
+ if (this._isRecordingConsole || !this._window?.console) return;
187
+ const maxBufferSize = resolveLogsConfig(this._configSource.get()).maxBufferSize;
188
+ let active = true;
189
+ this._consoleRecorderUnpatchers.push(()=>{
190
+ active = false;
191
+ });
192
+ for (const level of BUFFERED_CONSOLE_LEVELS){
193
+ let trueOriginal;
194
+ try {
195
+ trueOriginal = originalConsoleMethod(this._window.console[level]);
196
+ } catch {
197
+ continue;
198
+ }
199
+ if (trueOriginal) this._consoleRecorderUnpatchers.push(patch(this._window.console, level, (next)=>{
200
+ const wrapped = (...args)=>{
201
+ try {
202
+ if (active) this._recordConsoleEntry(level, args, maxBufferSize);
203
+ } catch {}
204
+ return next.apply(this._window.console, args);
205
+ };
206
+ wrapped.__rrweb_original__ = trueOriginal;
207
+ return wrapped;
208
+ }));
209
+ }
210
+ this._isRecordingConsole = true;
211
+ this._consoleRecorderTimeout = setTimeout(()=>{
212
+ this._stopConsoleRecorder();
213
+ }, RECORDER_MAX_AGE_MS);
214
+ }
215
+ _recordConsoleEntry(level, args, maxBufferSize) {
216
+ if (!this._isRecordingConsole || this._isRecordingConsoleEntry || 0 === args.length) return;
217
+ if (!this._client?.canCapture) return void this._stopConsoleRecorder();
218
+ if (this._consoleBuffer.length >= maxBufferSize) return;
219
+ this._isRecordingConsoleEntry = true;
220
+ try {
221
+ this._consoleBuffer.push({
222
+ level,
223
+ args,
224
+ occurredAtMs: Date.now(),
225
+ context: this._getSdkContext()
226
+ });
227
+ } finally{
228
+ this._isRecordingConsoleEntry = false;
229
+ }
230
+ }
231
+ _stopConsoleRecorder() {
232
+ this._consoleBuffer = [];
233
+ if (!this._isRecordingConsole) return;
234
+ this._isRecordingConsole = false;
235
+ if (this._consoleRecorderTimeout) {
236
+ clearTimeout(this._consoleRecorderTimeout);
237
+ this._consoleRecorderTimeout = void 0;
238
+ }
239
+ for (const unpatch of this._consoleRecorderUnpatchers)unpatch();
240
+ this._consoleRecorderUnpatchers = [];
241
+ }
242
+ _takeConsoleBuffer() {
243
+ const buffered = this._consoleBuffer;
244
+ this._stopConsoleRecorder();
245
+ return buffered;
246
+ }
247
+ get logger() {
248
+ if (!this._capture_logger) this._capture_logger = {
249
+ trace: (body, attributes)=>this.captureLog({
250
+ body,
251
+ level: 'trace',
252
+ attributes
253
+ }),
254
+ debug: (body, attributes)=>this.captureLog({
255
+ body,
256
+ level: 'debug',
257
+ attributes
258
+ }),
259
+ info: (body, attributes)=>this.captureLog({
260
+ body,
261
+ level: 'info',
262
+ attributes
263
+ }),
264
+ warn: (body, attributes)=>this.captureLog({
265
+ body,
266
+ level: 'warn',
267
+ attributes
268
+ }),
269
+ error: (body, attributes)=>this.captureLog({
270
+ body,
271
+ level: 'error',
272
+ attributes
273
+ }),
274
+ fatal: (body, attributes)=>this.captureLog({
275
+ body,
276
+ level: 'fatal',
277
+ attributes
278
+ })
279
+ };
280
+ return this._capture_logger;
281
+ }
282
+ flushLogs(transport) {
283
+ if (!this._client) return;
284
+ if (transport) return void this._flushViaTransport(transport);
285
+ if (this._core) this._core.flush().catch((err)=>this._logFlushError(err));
286
+ if (this._consoleCore) this._consoleCore.flush().catch((err)=>this._logFlushError(err));
287
+ }
288
+ async flush() {
289
+ const programmatic = this._core?.flush().catch((error)=>this._logFlushError(error));
290
+ const console = this._consoleCore?.flush().catch((error)=>this._logFlushError(error));
291
+ await programmatic;
292
+ await console;
293
+ }
294
+ _logFlushError(error) {
295
+ if (!isHandledLogsRequestError(error)) this._logger.error('PostHog logs flush failed:', error);
296
+ }
297
+ loadIfEnabled() {
298
+ if (this._disposed || !this._isLogsEnabled || this._isLoaded || this._isLoading) return;
299
+ const loadConsole = this._getConsoleLoader();
300
+ if (!loadConsole) return void this._stopConsoleRecorder();
301
+ this._isLoading = true;
302
+ try {
303
+ loadConsole((err, logsExtension)=>{
304
+ this._isLoading = false;
305
+ if (this._disposed || !this._isLogsEnabled) return;
306
+ if (err || !logsExtension) {
307
+ this._logger.error("Could not load logs script", err);
308
+ this._stopConsoleRecorder();
309
+ } else {
310
+ const buffered = this._takeConsoleBuffer();
311
+ this._consoleLogsDispose = logsExtension.initialize(this._client);
312
+ this._isLoaded = true;
313
+ if (buffered.length > 0) logsExtension.replay(this._client, buffered);
314
+ }
315
+ });
316
+ } catch (error) {
317
+ this._isLoading = false;
318
+ throw error;
319
+ }
320
+ }
321
+ _createHost(getQueue, setQueue) {
322
+ const client = this._client;
323
+ return {
324
+ get isDisabled () {
325
+ return false;
326
+ },
327
+ get optedOut () {
328
+ return !client.canCapture;
329
+ },
330
+ getPersistedProperty: (key)=>key === PostHogPersistedProperty.LogsQueue ? getQueue() : void 0,
331
+ setPersistedProperty: (key, value)=>{
332
+ if (key === PostHogPersistedProperty.LogsQueue) setQueue(value ?? []);
333
+ },
334
+ _sendLogsBatch: (payload)=>this._sendLogsBatch(payload),
335
+ getLibraryId: ()=>client.library.name,
336
+ getLibraryVersion: ()=>client.library.version
337
+ };
338
+ }
339
+ _sendLogsBatch(payload) {
340
+ return new Promise((resolve)=>{
341
+ if (isStatusZeroFailureCircuitBreakerTripped(this._consecutiveStatusZeroFailures, MAX_CONSECUTIVE_STATUS_ZERO_FAILURES)) return void resolve({
342
+ kind: 'fatal',
343
+ error: markLogsRequestErrorAsHandled(void 0, 'logs endpoint is unreachable, dropping batch')
344
+ });
345
+ let settled = false;
346
+ const settle = (outcome)=>{
347
+ if (settled) return;
348
+ settled = true;
349
+ clearTimeout(timer);
350
+ resolve(outcome);
351
+ };
352
+ const timer = setTimeout(()=>{
353
+ this._logger.warn('Logs request timed out before receiving a response');
354
+ settle({
355
+ kind: 'retry-later',
356
+ error: markLogsRequestErrorAsHandled(void 0, 'logs request timed out')
357
+ });
358
+ }, LOGS_SEND_TIMEOUT_MS);
359
+ const isRequestReady = this._isRequestReady;
360
+ this._client.sendRequest('/i/v1/logs', {
361
+ method: 'POST',
362
+ query: {
363
+ token: this._client.projectToken
364
+ },
365
+ body: payload,
366
+ compression: 'best-available',
367
+ timeoutMs: 60000
368
+ }).then((response)=>{
369
+ const status = response.statusCode;
370
+ this._trackEndpointReachability(status, isRequestReady);
371
+ if (status >= 200 && status < 300) settle({
372
+ kind: 'ok'
373
+ });
374
+ else if (413 === status) settle({
375
+ kind: 'too-large'
376
+ });
377
+ else if (0 === status || 408 === status || 429 === status || status >= 500) if (0 === status) {
378
+ if (!response.error) this._logger.warn('Logs request failed before receiving an HTTP response');
379
+ settle({
380
+ kind: 'retry-later',
381
+ error: markLogsRequestErrorAsHandled(response.error, 'logs request failed before receiving an HTTP response')
382
+ });
383
+ } else settle({
384
+ kind: 'retry-later',
385
+ error: response.error ?? new Error(`logs request failed with status ${status}`)
386
+ });
387
+ else settle({
388
+ kind: 'fatal',
389
+ error: new Error(`logs request failed with status ${status}`)
390
+ });
391
+ }, (error)=>{
392
+ settle({
393
+ kind: 'retry-later',
394
+ error
395
+ });
396
+ });
397
+ });
398
+ }
399
+ _trackEndpointReachability(statusCode, isRequestReady) {
400
+ if (0 === statusCode && !isRequestReady) return;
401
+ this._consecutiveStatusZeroFailures = updateStatusZeroFailureCount(statusCode, this._consecutiveStatusZeroFailures, MAX_CONSECUTIVE_STATUS_ZERO_FAILURES, ()=>this._logger.warn('Log requests are failing before receiving an HTTP response; this can happen due to network issues, CORS, browser blocking, or ad blockers. Stopped sending logs; will try again when connectivity changes.'));
402
+ }
403
+ _flushViaTransport(transport) {
404
+ if (this._queue.length > 0) this._drainQueueViaTransport(transport, this._queue, this._resolvedConfig, this._client.library.name, (q)=>{
405
+ this._queue = q;
406
+ });
407
+ if (this._consoleQueue.length > 0) this._drainQueueViaTransport(transport, this._consoleQueue, this._consoleResolvedConfig, CONSOLE_SCOPE_NAME, (q)=>{
408
+ this._consoleQueue = q;
409
+ });
410
+ }
411
+ _drainQueueViaTransport(transport, queue, config, scopeName, setQueue) {
412
+ if (0 === queue.length) return;
413
+ const records = queue.map((e)=>e.record);
414
+ setQueue([]);
415
+ const payload = buildOtlpLogsPayload(records, buildResourceAttributes(config, this._client.library.name, this._client.library.version), scopeName, this._client.library.version);
416
+ this._client.sendRequest('/i/v1/logs', {
417
+ method: 'POST',
418
+ query: {
419
+ token: this._client.projectToken
420
+ },
421
+ body: payload,
422
+ compression: 'best-available',
423
+ transport,
424
+ timeoutMs: 60000
425
+ }).catch((error)=>this._logFlushError(error));
426
+ }
427
+ }
428
+ export { RECORDER_MAX_AGE_MS, logs_PostHogLogs as PostHogLogs };
package/dist/token.d.ts CHANGED
@@ -6,7 +6,7 @@ declare const extensionTokenType: unique symbol;
6
6
  * Tokens are plain strings at runtime, so independently compiled scripts can
7
7
  * share them without a registry or object-identity contract. The generic brand
8
8
  * lets `Client.getExtension` infer the extension type. A token's string
9
- * value must exactly match its extension's stable `name`.
9
+ * value must match an installed extension's stable `name` or one of its `bindings` keys.
10
10
  */
11
11
  export type ExtensionToken<T> = string & {
12
12
  readonly [extensionTokenType]: T;
@@ -0,0 +1,6 @@
1
+ /**
2
+ * Walks the `__rrweb_original__` markers console plugins leave behind to reach the
3
+ * real console method. Shared by the main bundle's recorder and the logs entrypoint
4
+ * so a change to the marker protocol can't be applied to only one of them.
5
+ */
6
+ export declare const originalConsoleMethod: (method: any) => any;
@@ -0,0 +1,43 @@
1
+ "use strict";
2
+ var __webpack_require__ = {};
3
+ (()=>{
4
+ __webpack_require__.d = (exports1, getters, values)=>{
5
+ var define = (defs, kind)=>{
6
+ for(var key in defs)if (__webpack_require__.o(defs, key) && !__webpack_require__.o(exports1, key)) Object.defineProperty(exports1, key, {
7
+ enumerable: true,
8
+ [kind]: defs[key]
9
+ });
10
+ };
11
+ define(getters, "get");
12
+ define(values, "value");
13
+ };
14
+ })();
15
+ (()=>{
16
+ __webpack_require__.o = (obj, prop)=>Object.prototype.hasOwnProperty.call(obj, prop);
17
+ })();
18
+ (()=>{
19
+ __webpack_require__.r = (exports1)=>{
20
+ if ("u" > typeof Symbol && Symbol.toStringTag) Object.defineProperty(exports1, Symbol.toStringTag, {
21
+ value: 'Module'
22
+ });
23
+ Object.defineProperty(exports1, '__esModule', {
24
+ value: true
25
+ });
26
+ };
27
+ })();
28
+ var __webpack_exports__ = {};
29
+ __webpack_require__.r(__webpack_exports__);
30
+ const originalConsoleMethod = (method)=>{
31
+ while(method?.__rrweb_original__)method = method.__rrweb_original__;
32
+ return method;
33
+ };
34
+ __webpack_require__.d(__webpack_exports__, {}, {
35
+ originalConsoleMethod: originalConsoleMethod
36
+ });
37
+ exports.originalConsoleMethod = __webpack_exports__.originalConsoleMethod;
38
+ for(var __rspack_i in __webpack_exports__)if (-1 === [
39
+ "originalConsoleMethod"
40
+ ].indexOf(__rspack_i)) exports[__rspack_i] = __webpack_exports__[__rspack_i];
41
+ Object.defineProperty(exports, '__esModule', {
42
+ value: true
43
+ });
@@ -0,0 +1,5 @@
1
+ const originalConsoleMethod = (method)=>{
2
+ while(method?.__rrweb_original__)method = method.__rrweb_original__;
3
+ return method;
4
+ };
5
+ export { originalConsoleMethod };
@@ -84,6 +84,7 @@ const PERSONAL_DATA_CAMPAIGN_PARAMS = [
84
84
  'qclid',
85
85
  'sccid',
86
86
  'oppref',
87
+ 'bfcid',
87
88
  'irclid',
88
89
  '_kx'
89
90
  ];
@@ -24,6 +24,7 @@ const PERSONAL_DATA_CAMPAIGN_PARAMS = [
24
24
  'qclid',
25
25
  'sccid',
26
26
  'oppref',
27
+ 'bfcid',
27
28
  'irclid',
28
29
  '_kx'
29
30
  ];
@@ -0,0 +1,3 @@
1
+ export declare function patch(source: {
2
+ [key: string]: any;
3
+ }, name: string, replacement: (...args: unknown[]) => unknown): () => void;
@@ -0,0 +1,90 @@
1
+ "use strict";
2
+ var __webpack_require__ = {};
3
+ (()=>{
4
+ __webpack_require__.d = (exports1, getters, values)=>{
5
+ var define = (defs, kind)=>{
6
+ for(var key in defs)if (__webpack_require__.o(defs, key) && !__webpack_require__.o(exports1, key)) Object.defineProperty(exports1, key, {
7
+ enumerable: true,
8
+ [kind]: defs[key]
9
+ });
10
+ };
11
+ define(getters, "get");
12
+ define(values, "value");
13
+ };
14
+ })();
15
+ (()=>{
16
+ __webpack_require__.o = (obj, prop)=>Object.prototype.hasOwnProperty.call(obj, prop);
17
+ })();
18
+ (()=>{
19
+ __webpack_require__.r = (exports1)=>{
20
+ if ("u" > typeof Symbol && Symbol.toStringTag) Object.defineProperty(exports1, Symbol.toStringTag, {
21
+ value: 'Module'
22
+ });
23
+ Object.defineProperty(exports1, '__esModule', {
24
+ value: true
25
+ });
26
+ };
27
+ })();
28
+ var __webpack_exports__ = {};
29
+ __webpack_require__.r(__webpack_exports__);
30
+ __webpack_require__.d(__webpack_exports__, {
31
+ patch: ()=>patch
32
+ });
33
+ const core_namespaceObject = require("@posthog/core");
34
+ const noop = ()=>{};
35
+ const spliceableLayer = (method)=>{
36
+ if (!(0, core_namespaceObject.isFunction)(method)) return;
37
+ return method.__posthog_layer__ ?? method.__rrweb_layer__;
38
+ };
39
+ function patch(source, name, replacement) {
40
+ try {
41
+ if (!(name in source)) return noop;
42
+ const original = source[name];
43
+ const layer = {
44
+ next: original
45
+ };
46
+ const callNext = function(...args) {
47
+ return layer.next.apply(this, args);
48
+ };
49
+ const wrapped = replacement(callNext);
50
+ if ((0, core_namespaceObject.isFunction)(wrapped)) {
51
+ wrapped.prototype = wrapped.prototype || {};
52
+ Object.defineProperties(wrapped, {
53
+ __posthog_wrapped__: {
54
+ enumerable: false,
55
+ value: true
56
+ },
57
+ __posthog_layer__: {
58
+ enumerable: false,
59
+ value: layer
60
+ }
61
+ });
62
+ }
63
+ source[name] = wrapped;
64
+ return ()=>{
65
+ if (source[name] === wrapped) {
66
+ source[name] = layer.next;
67
+ return;
68
+ }
69
+ let current = source[name];
70
+ let currentLayer = spliceableLayer(current);
71
+ while(currentLayer){
72
+ if (currentLayer.next === wrapped) {
73
+ currentLayer.next = layer.next;
74
+ return;
75
+ }
76
+ current = currentLayer.next;
77
+ currentLayer = spliceableLayer(current);
78
+ }
79
+ };
80
+ } catch {
81
+ return noop;
82
+ }
83
+ }
84
+ exports.patch = __webpack_exports__.patch;
85
+ for(var __rspack_i in __webpack_exports__)if (-1 === [
86
+ "patch"
87
+ ].indexOf(__rspack_i)) exports[__rspack_i] = __webpack_exports__[__rspack_i];
88
+ Object.defineProperty(exports, '__esModule', {
89
+ value: true
90
+ });
@@ -0,0 +1,52 @@
1
+ import { isFunction } from "@posthog/core";
2
+ const noop = ()=>{};
3
+ const spliceableLayer = (method)=>{
4
+ if (!isFunction(method)) return;
5
+ return method.__posthog_layer__ ?? method.__rrweb_layer__;
6
+ };
7
+ function patch(source, name, replacement) {
8
+ try {
9
+ if (!(name in source)) return noop;
10
+ const original = source[name];
11
+ const layer = {
12
+ next: original
13
+ };
14
+ const callNext = function(...args) {
15
+ return layer.next.apply(this, args);
16
+ };
17
+ const wrapped = replacement(callNext);
18
+ if (isFunction(wrapped)) {
19
+ wrapped.prototype = wrapped.prototype || {};
20
+ Object.defineProperties(wrapped, {
21
+ __posthog_wrapped__: {
22
+ enumerable: false,
23
+ value: true
24
+ },
25
+ __posthog_layer__: {
26
+ enumerable: false,
27
+ value: layer
28
+ }
29
+ });
30
+ }
31
+ source[name] = wrapped;
32
+ return ()=>{
33
+ if (source[name] === wrapped) {
34
+ source[name] = layer.next;
35
+ return;
36
+ }
37
+ let current = source[name];
38
+ let currentLayer = spliceableLayer(current);
39
+ while(currentLayer){
40
+ if (currentLayer.next === wrapped) {
41
+ currentLayer.next = layer.next;
42
+ return;
43
+ }
44
+ current = currentLayer.next;
45
+ currentLayer = spliceableLayer(current);
46
+ }
47
+ };
48
+ } catch {
49
+ return noop;
50
+ }
51
+ }
52
+ export { patch };
@@ -0,0 +1,11 @@
1
+ /** Selects the URL components retained for capture. */
2
+ export interface UrlCaptureOptions {
3
+ /** Retain the pathname. Defaults to true. */
4
+ path?: boolean;
5
+ /** Retain query parameters. Defaults to false. */
6
+ search?: boolean;
7
+ /** Retain the fragment. Defaults to false. */
8
+ hash?: boolean;
9
+ }
10
+ /** Shape an absolute URL for capture without modifying the input. Invalid URLs are omitted. */
11
+ export declare function sanitizeUrl(url: URL | string, options: UrlCaptureOptions): string | undefined;