posthog-js-lite 3.5.0 → 3.6.0
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/CHANGELOG.md +13 -0
- package/lib/{index.cjs.js → index.cjs} +380 -173
- package/lib/index.cjs.map +1 -0
- package/lib/index.d.ts +668 -642
- package/lib/{index.esm.js → index.mjs} +380 -173
- package/lib/index.mjs.map +1 -0
- package/package.json +3 -3
- package/src/context.ts +1 -1
- package/src/patch.ts +50 -0
- package/src/posthog-web.ts +9 -7
- package/src/types.ts +1 -1
- package/tsconfig.json +1 -0
- package/lib/index.cjs.js.map +0 -1
- package/lib/index.esm.js.map +0 -1
- package/lib/posthog-core/src/eventemitter.d.ts +0 -8
- package/lib/posthog-core/src/featureFlagUtils.d.ts +0 -34
- package/lib/posthog-core/src/index.d.ts +0 -239
- package/lib/posthog-core/src/lz-string.d.ts +0 -8
- package/lib/posthog-core/src/patch.d.ts +0 -3
- package/lib/posthog-core/src/types.d.ts +0 -422
- package/lib/posthog-core/src/utils.d.ts +0 -19
- package/lib/posthog-core/src/vendor/uuidv7.d.ts +0 -179
- package/lib/posthog-web/index.d.ts +0 -3
- package/lib/posthog-web/src/context.d.ts +0 -1
- package/lib/posthog-web/src/posthog-web.d.ts +0 -19
- package/lib/posthog-web/src/storage.d.ts +0 -10
- package/lib/posthog-web/src/types.d.ts +0 -7
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
var version = "3.6.0";
|
|
2
|
+
|
|
1
3
|
var PostHogPersistedProperty;
|
|
2
4
|
(function (PostHogPersistedProperty) {
|
|
3
5
|
PostHogPersistedProperty["AnonymousId"] = "anonymous_id";
|
|
@@ -13,6 +15,7 @@ var PostHogPersistedProperty;
|
|
|
13
15
|
PostHogPersistedProperty["Queue"] = "queue";
|
|
14
16
|
PostHogPersistedProperty["OptedOut"] = "opted_out";
|
|
15
17
|
PostHogPersistedProperty["SessionId"] = "session_id";
|
|
18
|
+
PostHogPersistedProperty["SessionStartTimestamp"] = "session_start_timestamp";
|
|
16
19
|
PostHogPersistedProperty["SessionLastTimestamp"] = "session_timestamp";
|
|
17
20
|
PostHogPersistedProperty["PersonProperties"] = "person_properties";
|
|
18
21
|
PostHogPersistedProperty["GroupProperties"] = "group_properties";
|
|
@@ -287,6 +290,7 @@ const NEW_FLAGS_EXCLUDED_HASHES = new Set([
|
|
|
287
290
|
'fc80b8e2',
|
|
288
291
|
'75cc0998',
|
|
289
292
|
]);
|
|
293
|
+
const STRING_FORMAT = 'utf8';
|
|
290
294
|
function assert(truthyValue, message) {
|
|
291
295
|
if (!truthyValue || typeof truthyValue !== 'string' || isEmpty(truthyValue)) {
|
|
292
296
|
throw new Error(message);
|
|
@@ -339,12 +343,8 @@ const isError = (x) => {
|
|
|
339
343
|
return x instanceof Error;
|
|
340
344
|
};
|
|
341
345
|
function getFetch() {
|
|
342
|
-
return typeof fetch !== 'undefined' ? fetch : typeof
|
|
346
|
+
return typeof fetch !== 'undefined' ? fetch : typeof globalThis.fetch !== 'undefined' ? globalThis.fetch : undefined;
|
|
343
347
|
}
|
|
344
|
-
// copied from: https://github.com/PostHog/posthog-js/blob/main/react/src/utils/type-utils.ts#L4
|
|
345
|
-
const isFunction = function (f) {
|
|
346
|
-
return typeof f === 'function';
|
|
347
|
-
};
|
|
348
348
|
// FNV-1a hash function
|
|
349
349
|
// https://en.wikipedia.org/wiki/Fowler%E2%80%93Noll%E2%80%93Vo_hash_function
|
|
350
350
|
// I know, I know, I'm rolling my own hash function, but I didn't want to take on
|
|
@@ -368,6 +368,9 @@ function isTokenInRollout(token, percentage = 0, excludedHashes) {
|
|
|
368
368
|
const hashInt = parseInt(tokenHash, 16);
|
|
369
369
|
const hashFloat = hashInt / 0xffffffff;
|
|
370
370
|
return hashFloat < percentage;
|
|
371
|
+
}
|
|
372
|
+
function allSettled(promises) {
|
|
373
|
+
return Promise.all(promises.map((p) => (p ?? Promise.resolve()).then((value) => ({ status: 'fulfilled', value }), (reason) => ({ status: 'rejected', reason }))));
|
|
371
374
|
}
|
|
372
375
|
|
|
373
376
|
// Copyright (c) 2013 Pieroxy <pieroxy@pieroxy.net>
|
|
@@ -1232,11 +1235,21 @@ const uuidv7 = () => uuidv7obj().toString();
|
|
|
1232
1235
|
const uuidv7obj = () => (defaultGenerator || (defaultGenerator = new V7Generator())).generate();
|
|
1233
1236
|
|
|
1234
1237
|
class PostHogFetchHttpError extends Error {
|
|
1235
|
-
constructor(response) {
|
|
1236
|
-
super('HTTP error while fetching PostHog: ' + response.status);
|
|
1238
|
+
constructor(response, reqByteLength) {
|
|
1239
|
+
super('HTTP error while fetching PostHog: status=' + response.status + ', reqByteLength=' + reqByteLength);
|
|
1237
1240
|
this.response = response;
|
|
1241
|
+
this.reqByteLength = reqByteLength;
|
|
1238
1242
|
this.name = 'PostHogFetchHttpError';
|
|
1239
1243
|
}
|
|
1244
|
+
get status() {
|
|
1245
|
+
return this.response.status;
|
|
1246
|
+
}
|
|
1247
|
+
get text() {
|
|
1248
|
+
return this.response.text();
|
|
1249
|
+
}
|
|
1250
|
+
get json() {
|
|
1251
|
+
return this.response.json();
|
|
1252
|
+
}
|
|
1240
1253
|
}
|
|
1241
1254
|
class PostHogFetchNetworkError extends Error {
|
|
1242
1255
|
constructor(error) {
|
|
@@ -1248,9 +1261,27 @@ class PostHogFetchNetworkError extends Error {
|
|
|
1248
1261
|
this.name = 'PostHogFetchNetworkError';
|
|
1249
1262
|
}
|
|
1250
1263
|
}
|
|
1264
|
+
const maybeAdd = (key, value) => value !== undefined ? { [key]: value } : {};
|
|
1265
|
+
async function logFlushError(err) {
|
|
1266
|
+
if (err instanceof PostHogFetchHttpError) {
|
|
1267
|
+
let text = '';
|
|
1268
|
+
try {
|
|
1269
|
+
text = await err.text;
|
|
1270
|
+
}
|
|
1271
|
+
catch { }
|
|
1272
|
+
console.error(`Error while flushing PostHog: message=${err.message}, response body=${text}`, err);
|
|
1273
|
+
}
|
|
1274
|
+
else {
|
|
1275
|
+
console.error('Error while flushing PostHog', err);
|
|
1276
|
+
}
|
|
1277
|
+
return Promise.resolve();
|
|
1278
|
+
}
|
|
1251
1279
|
function isPostHogFetchError(err) {
|
|
1252
1280
|
return typeof err === 'object' && (err instanceof PostHogFetchHttpError || err instanceof PostHogFetchNetworkError);
|
|
1253
1281
|
}
|
|
1282
|
+
function isPostHogFetchContentTooLargeError(err) {
|
|
1283
|
+
return typeof err === 'object' && err instanceof PostHogFetchHttpError && err.status === 413;
|
|
1284
|
+
}
|
|
1254
1285
|
var QuotaLimitedFeature;
|
|
1255
1286
|
(function (QuotaLimitedFeature) {
|
|
1256
1287
|
QuotaLimitedFeature["FeatureFlags"] = "feature_flags";
|
|
@@ -1259,6 +1290,7 @@ var QuotaLimitedFeature;
|
|
|
1259
1290
|
class PostHogCoreStateless {
|
|
1260
1291
|
constructor(apiKey, options) {
|
|
1261
1292
|
this.flushPromise = null;
|
|
1293
|
+
this.shutdownPromise = null;
|
|
1262
1294
|
this.pendingPromises = {};
|
|
1263
1295
|
// internal
|
|
1264
1296
|
this._events = new SimpleEventEmitter();
|
|
@@ -1381,12 +1413,26 @@ class PostHogCoreStateless {
|
|
|
1381
1413
|
this.enqueue('identify', payload, options);
|
|
1382
1414
|
});
|
|
1383
1415
|
}
|
|
1416
|
+
async identifyStatelessImmediate(distinctId, properties, options) {
|
|
1417
|
+
const payload = {
|
|
1418
|
+
...this.buildPayload({
|
|
1419
|
+
distinct_id: distinctId,
|
|
1420
|
+
event: '$identify',
|
|
1421
|
+
properties,
|
|
1422
|
+
}),
|
|
1423
|
+
};
|
|
1424
|
+
await this.sendImmediate('identify', payload, options);
|
|
1425
|
+
}
|
|
1384
1426
|
captureStateless(distinctId, event, properties, options) {
|
|
1385
1427
|
this.wrap(() => {
|
|
1386
1428
|
const payload = this.buildPayload({ distinct_id: distinctId, event, properties });
|
|
1387
1429
|
this.enqueue('capture', payload, options);
|
|
1388
1430
|
});
|
|
1389
1431
|
}
|
|
1432
|
+
async captureStatelessImmediate(distinctId, event, properties, options) {
|
|
1433
|
+
const payload = this.buildPayload({ distinct_id: distinctId, event, properties });
|
|
1434
|
+
await this.sendImmediate('capture', payload, options);
|
|
1435
|
+
}
|
|
1390
1436
|
aliasStateless(alias, distinctId, properties, options) {
|
|
1391
1437
|
this.wrap(() => {
|
|
1392
1438
|
const payload = this.buildPayload({
|
|
@@ -1401,6 +1447,18 @@ class PostHogCoreStateless {
|
|
|
1401
1447
|
this.enqueue('alias', payload, options);
|
|
1402
1448
|
});
|
|
1403
1449
|
}
|
|
1450
|
+
async aliasStatelessImmediate(alias, distinctId, properties, options) {
|
|
1451
|
+
const payload = this.buildPayload({
|
|
1452
|
+
event: '$create_alias',
|
|
1453
|
+
distinct_id: distinctId,
|
|
1454
|
+
properties: {
|
|
1455
|
+
...(properties || {}),
|
|
1456
|
+
distinct_id: distinctId,
|
|
1457
|
+
alias,
|
|
1458
|
+
},
|
|
1459
|
+
});
|
|
1460
|
+
await this.sendImmediate('alias', payload, options);
|
|
1461
|
+
}
|
|
1404
1462
|
/***
|
|
1405
1463
|
*** GROUPS
|
|
1406
1464
|
***/
|
|
@@ -1464,6 +1522,7 @@ class PostHogCoreStateless {
|
|
|
1464
1522
|
...extraPayload,
|
|
1465
1523
|
}),
|
|
1466
1524
|
};
|
|
1525
|
+
this.logMsgIfDebug(() => console.log('PostHog Debug', 'Decide URL', url));
|
|
1467
1526
|
// Don't retry /decide API calls
|
|
1468
1527
|
return this.fetchWithRetry(url, fetchOptions, { retryCount: 0 }, this.featureFlagsRequestTimeoutMs)
|
|
1469
1528
|
.then((response) => response.json())
|
|
@@ -1581,7 +1640,7 @@ class PostHogCoreStateless {
|
|
|
1581
1640
|
async getSurveysStateless() {
|
|
1582
1641
|
await this._initPromise;
|
|
1583
1642
|
if (this.disableSurveys === true) {
|
|
1584
|
-
this.logMsgIfDebug(() => console.log('Loading surveys is disabled.'));
|
|
1643
|
+
this.logMsgIfDebug(() => console.log('PostHog Debug', 'Loading surveys is disabled.'));
|
|
1585
1644
|
return [];
|
|
1586
1645
|
}
|
|
1587
1646
|
const url = `${this.host}/api/surveys/?token=${this.apiKey}`;
|
|
@@ -1611,6 +1670,30 @@ class PostHogCoreStateless {
|
|
|
1611
1670
|
}
|
|
1612
1671
|
return newSurveys ?? [];
|
|
1613
1672
|
}
|
|
1673
|
+
get props() {
|
|
1674
|
+
if (!this._props) {
|
|
1675
|
+
this._props = this.getPersistedProperty(PostHogPersistedProperty.Props);
|
|
1676
|
+
}
|
|
1677
|
+
return this._props || {};
|
|
1678
|
+
}
|
|
1679
|
+
set props(val) {
|
|
1680
|
+
this._props = val;
|
|
1681
|
+
}
|
|
1682
|
+
async register(properties) {
|
|
1683
|
+
this.wrap(() => {
|
|
1684
|
+
this.props = {
|
|
1685
|
+
...this.props,
|
|
1686
|
+
...properties,
|
|
1687
|
+
};
|
|
1688
|
+
this.setPersistedProperty(PostHogPersistedProperty.Props, this.props);
|
|
1689
|
+
});
|
|
1690
|
+
}
|
|
1691
|
+
async unregister(property) {
|
|
1692
|
+
this.wrap(() => {
|
|
1693
|
+
delete this.props[property];
|
|
1694
|
+
this.setPersistedProperty(PostHogPersistedProperty.Props, this.props);
|
|
1695
|
+
});
|
|
1696
|
+
}
|
|
1614
1697
|
/***
|
|
1615
1698
|
*** QUEUEING AND FLUSHING
|
|
1616
1699
|
***/
|
|
@@ -1620,25 +1703,7 @@ class PostHogCoreStateless {
|
|
|
1620
1703
|
this._events.emit(type, `Library is disabled. Not sending event. To re-enable, call posthog.optIn()`);
|
|
1621
1704
|
return;
|
|
1622
1705
|
}
|
|
1623
|
-
const message =
|
|
1624
|
-
..._message,
|
|
1625
|
-
type: type,
|
|
1626
|
-
library: this.getLibraryId(),
|
|
1627
|
-
library_version: this.getLibraryVersion(),
|
|
1628
|
-
timestamp: options?.timestamp ? options?.timestamp : currentISOTime(),
|
|
1629
|
-
uuid: options?.uuid ? options.uuid : uuidv7(),
|
|
1630
|
-
};
|
|
1631
|
-
const addGeoipDisableProperty = options?.disableGeoip ?? this.disableGeoip;
|
|
1632
|
-
if (addGeoipDisableProperty) {
|
|
1633
|
-
if (!message.properties) {
|
|
1634
|
-
message.properties = {};
|
|
1635
|
-
}
|
|
1636
|
-
message['properties']['$geoip_disable'] = true;
|
|
1637
|
-
}
|
|
1638
|
-
if (message.distinctId) {
|
|
1639
|
-
message.distinct_id = message.distinctId;
|
|
1640
|
-
delete message.distinctId;
|
|
1641
|
-
}
|
|
1706
|
+
const message = this.prepareMessage(type, _message, options);
|
|
1642
1707
|
const queue = this.getPersistedProperty(PostHogPersistedProperty.Queue) || [];
|
|
1643
1708
|
if (queue.length >= this.maxQueueSize) {
|
|
1644
1709
|
queue.shift();
|
|
@@ -1656,6 +1721,72 @@ class PostHogCoreStateless {
|
|
|
1656
1721
|
}
|
|
1657
1722
|
});
|
|
1658
1723
|
}
|
|
1724
|
+
async sendImmediate(type, _message, options) {
|
|
1725
|
+
if (this.disabled) {
|
|
1726
|
+
this.logMsgIfDebug(() => console.warn('[PostHog] The client is disabled'));
|
|
1727
|
+
return;
|
|
1728
|
+
}
|
|
1729
|
+
if (!this._isInitialized) {
|
|
1730
|
+
await this._initPromise;
|
|
1731
|
+
}
|
|
1732
|
+
if (this.optedOut) {
|
|
1733
|
+
this._events.emit(type, `Library is disabled. Not sending event. To re-enable, call posthog.optIn()`);
|
|
1734
|
+
return;
|
|
1735
|
+
}
|
|
1736
|
+
const data = {
|
|
1737
|
+
api_key: this.apiKey,
|
|
1738
|
+
batch: [this.prepareMessage(type, _message, options)],
|
|
1739
|
+
sent_at: currentISOTime(),
|
|
1740
|
+
};
|
|
1741
|
+
if (this.historicalMigration) {
|
|
1742
|
+
data.historical_migration = true;
|
|
1743
|
+
}
|
|
1744
|
+
const payload = JSON.stringify(data);
|
|
1745
|
+
const url = this.captureMode === 'form'
|
|
1746
|
+
? `${this.host}/e/?ip=1&_=${currentTimestamp()}&v=${this.getLibraryVersion()}`
|
|
1747
|
+
: `${this.host}/batch/`;
|
|
1748
|
+
const fetchOptions = this.captureMode === 'form'
|
|
1749
|
+
? {
|
|
1750
|
+
method: 'POST',
|
|
1751
|
+
mode: 'no-cors',
|
|
1752
|
+
credentials: 'omit',
|
|
1753
|
+
headers: { ...this.getCustomHeaders(), 'Content-Type': 'application/x-www-form-urlencoded' },
|
|
1754
|
+
body: `data=${encodeURIComponent(LZString.compressToBase64(payload))}&compression=lz64`,
|
|
1755
|
+
}
|
|
1756
|
+
: {
|
|
1757
|
+
method: 'POST',
|
|
1758
|
+
headers: { ...this.getCustomHeaders(), 'Content-Type': 'application/json' },
|
|
1759
|
+
body: payload,
|
|
1760
|
+
};
|
|
1761
|
+
try {
|
|
1762
|
+
await this.fetchWithRetry(url, fetchOptions);
|
|
1763
|
+
}
|
|
1764
|
+
catch (err) {
|
|
1765
|
+
this._events.emit('error', err);
|
|
1766
|
+
}
|
|
1767
|
+
}
|
|
1768
|
+
prepareMessage(type, _message, options) {
|
|
1769
|
+
const message = {
|
|
1770
|
+
..._message,
|
|
1771
|
+
type: type,
|
|
1772
|
+
library: this.getLibraryId(),
|
|
1773
|
+
library_version: this.getLibraryVersion(),
|
|
1774
|
+
timestamp: options?.timestamp ? options?.timestamp : currentISOTime(),
|
|
1775
|
+
uuid: options?.uuid ? options.uuid : uuidv7(),
|
|
1776
|
+
};
|
|
1777
|
+
const addGeoipDisableProperty = options?.disableGeoip ?? this.disableGeoip;
|
|
1778
|
+
if (addGeoipDisableProperty) {
|
|
1779
|
+
if (!message.properties) {
|
|
1780
|
+
message.properties = {};
|
|
1781
|
+
}
|
|
1782
|
+
message['properties']['$geoip_disable'] = true;
|
|
1783
|
+
}
|
|
1784
|
+
if (message.distinctId) {
|
|
1785
|
+
message.distinct_id = message.distinctId;
|
|
1786
|
+
delete message.distinctId;
|
|
1787
|
+
}
|
|
1788
|
+
return message;
|
|
1789
|
+
}
|
|
1659
1790
|
clearFlushTimer() {
|
|
1660
1791
|
if (this._flushTimer) {
|
|
1661
1792
|
clearTimeout(this._flushTimer);
|
|
@@ -1667,16 +1798,49 @@ class PostHogCoreStateless {
|
|
|
1667
1798
|
* Avoids unnecessary promise errors
|
|
1668
1799
|
*/
|
|
1669
1800
|
flushBackground() {
|
|
1670
|
-
void this.flush().catch(() => {
|
|
1801
|
+
void this.flush().catch(async (err) => {
|
|
1802
|
+
await logFlushError(err);
|
|
1803
|
+
});
|
|
1671
1804
|
}
|
|
1805
|
+
/**
|
|
1806
|
+
* Flushes the queue
|
|
1807
|
+
*
|
|
1808
|
+
* This function will return a promise that will resolve when the flush is complete,
|
|
1809
|
+
* or reject if there was an error (for example if the server or network is down).
|
|
1810
|
+
*
|
|
1811
|
+
* If there is already a flush in progress, this function will wait for that flush to complete.
|
|
1812
|
+
*
|
|
1813
|
+
* It's recommended to do error handling in the callback of the promise.
|
|
1814
|
+
*
|
|
1815
|
+
* @example
|
|
1816
|
+
* posthog.flush().then(() => {
|
|
1817
|
+
* console.log('Flush complete')
|
|
1818
|
+
* }).catch((err) => {
|
|
1819
|
+
* console.error('Flush failed', err)
|
|
1820
|
+
* })
|
|
1821
|
+
*
|
|
1822
|
+
*
|
|
1823
|
+
* @throws PostHogFetchHttpError
|
|
1824
|
+
* @throws PostHogFetchNetworkError
|
|
1825
|
+
* @throws Error
|
|
1826
|
+
*/
|
|
1672
1827
|
async flush() {
|
|
1673
|
-
|
|
1674
|
-
|
|
1828
|
+
// Wait for the current flush operation to finish (regardless of success or failure), then try to flush again.
|
|
1829
|
+
// Use allSettled instead of finally to be defensive around flush throwing errors immediately rather than rejecting.
|
|
1830
|
+
// Use a custom allSettled implementation to avoid issues with patching Promise on RN
|
|
1831
|
+
const nextFlushPromise = allSettled([this.flushPromise]).then(() => {
|
|
1832
|
+
return this._flush();
|
|
1833
|
+
});
|
|
1834
|
+
this.flushPromise = nextFlushPromise;
|
|
1835
|
+
void this.addPendingPromise(nextFlushPromise);
|
|
1836
|
+
allSettled([nextFlushPromise]).then(() => {
|
|
1837
|
+
// If there are no others waiting to flush, clear the promise.
|
|
1838
|
+
// We don't strictly need to do this, but it could make debugging easier
|
|
1839
|
+
if (this.flushPromise === nextFlushPromise) {
|
|
1675
1840
|
this.flushPromise = null;
|
|
1676
|
-
}
|
|
1677
|
-
|
|
1678
|
-
|
|
1679
|
-
return this.flushPromise;
|
|
1841
|
+
}
|
|
1842
|
+
});
|
|
1843
|
+
return nextFlushPromise;
|
|
1680
1844
|
}
|
|
1681
1845
|
getCustomHeaders() {
|
|
1682
1846
|
// Don't set the user agent if we're not on a browser. The latest spec allows
|
|
@@ -1693,56 +1857,79 @@ class PostHogCoreStateless {
|
|
|
1693
1857
|
async _flush() {
|
|
1694
1858
|
this.clearFlushTimer();
|
|
1695
1859
|
await this._initPromise;
|
|
1696
|
-
|
|
1860
|
+
let queue = this.getPersistedProperty(PostHogPersistedProperty.Queue) || [];
|
|
1697
1861
|
if (!queue.length) {
|
|
1698
|
-
return
|
|
1699
|
-
}
|
|
1700
|
-
const items = queue.slice(0, this.maxBatchSize);
|
|
1701
|
-
const messages = items.map((item) => item.message);
|
|
1702
|
-
const persistQueueChange = () => {
|
|
1703
|
-
const refreshedQueue = this.getPersistedProperty(PostHogPersistedProperty.Queue) || [];
|
|
1704
|
-
this.setPersistedProperty(PostHogPersistedProperty.Queue, refreshedQueue.slice(items.length));
|
|
1705
|
-
};
|
|
1706
|
-
const data = {
|
|
1707
|
-
api_key: this.apiKey,
|
|
1708
|
-
batch: messages,
|
|
1709
|
-
sent_at: currentISOTime(),
|
|
1710
|
-
};
|
|
1711
|
-
if (this.historicalMigration) {
|
|
1712
|
-
data.historical_migration = true;
|
|
1862
|
+
return;
|
|
1713
1863
|
}
|
|
1714
|
-
const
|
|
1715
|
-
const
|
|
1716
|
-
|
|
1717
|
-
|
|
1718
|
-
|
|
1719
|
-
|
|
1720
|
-
|
|
1721
|
-
|
|
1722
|
-
|
|
1723
|
-
|
|
1724
|
-
|
|
1864
|
+
const sentMessages = [];
|
|
1865
|
+
const originalQueueLength = queue.length;
|
|
1866
|
+
while (queue.length > 0 && sentMessages.length < originalQueueLength) {
|
|
1867
|
+
const batchItems = queue.slice(0, this.maxBatchSize);
|
|
1868
|
+
const batchMessages = batchItems.map((item) => item.message);
|
|
1869
|
+
const persistQueueChange = () => {
|
|
1870
|
+
const refreshedQueue = this.getPersistedProperty(PostHogPersistedProperty.Queue) || [];
|
|
1871
|
+
const newQueue = refreshedQueue.slice(batchItems.length);
|
|
1872
|
+
this.setPersistedProperty(PostHogPersistedProperty.Queue, newQueue);
|
|
1873
|
+
queue = newQueue;
|
|
1874
|
+
};
|
|
1875
|
+
const data = {
|
|
1876
|
+
api_key: this.apiKey,
|
|
1877
|
+
batch: batchMessages,
|
|
1878
|
+
sent_at: currentISOTime(),
|
|
1879
|
+
};
|
|
1880
|
+
if (this.historicalMigration) {
|
|
1881
|
+
data.historical_migration = true;
|
|
1725
1882
|
}
|
|
1726
|
-
|
|
1727
|
-
|
|
1728
|
-
|
|
1729
|
-
|
|
1883
|
+
const payload = JSON.stringify(data);
|
|
1884
|
+
const url = this.captureMode === 'form'
|
|
1885
|
+
? `${this.host}/e/?ip=1&_=${currentTimestamp()}&v=${this.getLibraryVersion()}`
|
|
1886
|
+
: `${this.host}/batch/`;
|
|
1887
|
+
const fetchOptions = this.captureMode === 'form'
|
|
1888
|
+
? {
|
|
1889
|
+
method: 'POST',
|
|
1890
|
+
mode: 'no-cors',
|
|
1891
|
+
credentials: 'omit',
|
|
1892
|
+
headers: { ...this.getCustomHeaders(), 'Content-Type': 'application/x-www-form-urlencoded' },
|
|
1893
|
+
body: `data=${encodeURIComponent(LZString.compressToBase64(payload))}&compression=lz64`,
|
|
1894
|
+
}
|
|
1895
|
+
: {
|
|
1896
|
+
method: 'POST',
|
|
1897
|
+
headers: { ...this.getCustomHeaders(), 'Content-Type': 'application/json' },
|
|
1898
|
+
body: payload,
|
|
1899
|
+
};
|
|
1900
|
+
const retryOptions = {
|
|
1901
|
+
retryCheck: (err) => {
|
|
1902
|
+
// don't automatically retry on 413 errors, we want to reduce the batch size first
|
|
1903
|
+
if (isPostHogFetchContentTooLargeError(err)) {
|
|
1904
|
+
return false;
|
|
1905
|
+
}
|
|
1906
|
+
// otherwise, retry on network errors
|
|
1907
|
+
return isPostHogFetchError(err);
|
|
1908
|
+
},
|
|
1730
1909
|
};
|
|
1731
|
-
|
|
1732
|
-
|
|
1733
|
-
}
|
|
1734
|
-
catch (err) {
|
|
1735
|
-
// depending on the error type, eg a malformed JSON or broken queue, it'll always return an error
|
|
1736
|
-
// and this will be an endless loop, in this case, if the error isn't a network issue, we always remove the items from the queue
|
|
1737
|
-
if (!(err instanceof PostHogFetchNetworkError)) {
|
|
1738
|
-
persistQueueChange();
|
|
1910
|
+
try {
|
|
1911
|
+
await this.fetchWithRetry(url, fetchOptions, retryOptions);
|
|
1739
1912
|
}
|
|
1740
|
-
|
|
1741
|
-
|
|
1913
|
+
catch (err) {
|
|
1914
|
+
if (isPostHogFetchContentTooLargeError(err) && batchMessages.length > 1) {
|
|
1915
|
+
// if we get a 413 error, we want to reduce the batch size and try again
|
|
1916
|
+
this.maxBatchSize = Math.max(1, Math.floor(batchMessages.length / 2));
|
|
1917
|
+
this.logMsgIfDebug(() => console.warn(`Received 413 when sending batch of size ${batchMessages.length}, reducing batch size to ${this.maxBatchSize}`));
|
|
1918
|
+
// do not persist the queue change, we want to retry the same batch
|
|
1919
|
+
continue;
|
|
1920
|
+
}
|
|
1921
|
+
// depending on the error type, eg a malformed JSON or broken queue, it'll always return an error
|
|
1922
|
+
// and this will be an endless loop, in this case, if the error isn't a network issue, we always remove the items from the queue
|
|
1923
|
+
if (!(err instanceof PostHogFetchNetworkError)) {
|
|
1924
|
+
persistQueueChange();
|
|
1925
|
+
}
|
|
1926
|
+
this._events.emit('error', err);
|
|
1927
|
+
throw err;
|
|
1928
|
+
}
|
|
1929
|
+
persistQueueChange();
|
|
1930
|
+
sentMessages.push(...batchMessages);
|
|
1742
1931
|
}
|
|
1743
|
-
|
|
1744
|
-
this._events.emit('flush', messages);
|
|
1745
|
-
return messages;
|
|
1932
|
+
this._events.emit('flush', sentMessages);
|
|
1746
1933
|
}
|
|
1747
1934
|
async fetchWithRetry(url, options, retryOptions, requestTimeout) {
|
|
1748
1935
|
var _a;
|
|
@@ -1751,6 +1938,15 @@ class PostHogCoreStateless {
|
|
|
1751
1938
|
setTimeout(() => ctrl.abort(), ms);
|
|
1752
1939
|
return ctrl.signal;
|
|
1753
1940
|
});
|
|
1941
|
+
const body = options.body ? options.body : '';
|
|
1942
|
+
let reqByteLength = -1;
|
|
1943
|
+
try {
|
|
1944
|
+
reqByteLength = Buffer.byteLength(body, STRING_FORMAT);
|
|
1945
|
+
}
|
|
1946
|
+
catch {
|
|
1947
|
+
const encoded = new TextEncoder().encode(body);
|
|
1948
|
+
reqByteLength = encoded.length;
|
|
1949
|
+
}
|
|
1754
1950
|
return await retriable(async () => {
|
|
1755
1951
|
let res = null;
|
|
1756
1952
|
try {
|
|
@@ -1768,12 +1964,12 @@ class PostHogCoreStateless {
|
|
|
1768
1964
|
// https://developer.mozilla.org/en-US/docs/Web/API/Request/mode#no-cors
|
|
1769
1965
|
const isNoCors = options.mode === 'no-cors';
|
|
1770
1966
|
if (!isNoCors && (res.status < 200 || res.status >= 400)) {
|
|
1771
|
-
throw new PostHogFetchHttpError(res);
|
|
1967
|
+
throw new PostHogFetchHttpError(res, reqByteLength);
|
|
1772
1968
|
}
|
|
1773
1969
|
return res;
|
|
1774
1970
|
}, { ...this._retryOptions, ...retryOptions });
|
|
1775
1971
|
}
|
|
1776
|
-
async
|
|
1972
|
+
async _shutdown(shutdownTimeoutMs = 30000) {
|
|
1777
1973
|
// A little tricky - we want to have a max shutdown time and enforce it, even if that means we have some
|
|
1778
1974
|
// dangling promises. We'll keep track of the timeout and resolve/reject based on that.
|
|
1779
1975
|
await this._initPromise;
|
|
@@ -1800,7 +1996,7 @@ class PostHogCoreStateless {
|
|
|
1800
1996
|
if (!isPostHogFetchError(e)) {
|
|
1801
1997
|
throw e;
|
|
1802
1998
|
}
|
|
1803
|
-
|
|
1999
|
+
await logFlushError(e);
|
|
1804
2000
|
}
|
|
1805
2001
|
};
|
|
1806
2002
|
return Promise.race([
|
|
@@ -1814,6 +2010,22 @@ class PostHogCoreStateless {
|
|
|
1814
2010
|
doShutdown(),
|
|
1815
2011
|
]);
|
|
1816
2012
|
}
|
|
2013
|
+
/**
|
|
2014
|
+
* Call shutdown() once before the node process exits, so ensure that all events have been sent and all promises
|
|
2015
|
+
* have resolved. Do not use this function if you intend to keep using this PostHog instance after calling it.
|
|
2016
|
+
* @param shutdownTimeoutMs
|
|
2017
|
+
*/
|
|
2018
|
+
async shutdown(shutdownTimeoutMs = 30000) {
|
|
2019
|
+
if (this.shutdownPromise) {
|
|
2020
|
+
this.logMsgIfDebug(() => console.warn('shutdown() called while already shutting down. shutdown() is meant to be called once before process exit - use flush() for per-request cleanup'));
|
|
2021
|
+
}
|
|
2022
|
+
else {
|
|
2023
|
+
this.shutdownPromise = this._shutdown(shutdownTimeoutMs).finally(() => {
|
|
2024
|
+
this.shutdownPromise = null;
|
|
2025
|
+
});
|
|
2026
|
+
}
|
|
2027
|
+
return this.shutdownPromise;
|
|
2028
|
+
}
|
|
1817
2029
|
}
|
|
1818
2030
|
class PostHogCore extends PostHogCoreStateless {
|
|
1819
2031
|
constructor(apiKey, options) {
|
|
@@ -1823,6 +2035,7 @@ class PostHogCore extends PostHogCoreStateless {
|
|
|
1823
2035
|
const featureFlagsRequestTimeoutMs = options?.featureFlagsRequestTimeoutMs ?? 10000; // 10 seconds
|
|
1824
2036
|
super(apiKey, { ...options, disableGeoip: disableGeoipOption, featureFlagsRequestTimeoutMs });
|
|
1825
2037
|
this.flagCallReported = {};
|
|
2038
|
+
this._sessionMaxLengthSeconds = 24 * 60 * 60; // 24 hours
|
|
1826
2039
|
this.sessionProps = {};
|
|
1827
2040
|
this.sendFeatureFlagEvent = options?.sendFeatureFlagEvent ?? true;
|
|
1828
2041
|
this._sessionExpirationTimeSeconds = options?.sessionExpirationTimeSeconds ?? 1800; // 30 minutes
|
|
@@ -1866,16 +2079,6 @@ class PostHogCore extends PostHogCoreStateless {
|
|
|
1866
2079
|
}
|
|
1867
2080
|
}
|
|
1868
2081
|
}
|
|
1869
|
-
// NOTE: Props are lazy loaded from localstorage hence the complex getter setter logic
|
|
1870
|
-
get props() {
|
|
1871
|
-
if (!this._props) {
|
|
1872
|
-
this._props = this.getPersistedProperty(PostHogPersistedProperty.Props);
|
|
1873
|
-
}
|
|
1874
|
-
return this._props || {};
|
|
1875
|
-
}
|
|
1876
|
-
set props(val) {
|
|
1877
|
-
this._props = val;
|
|
1878
|
-
}
|
|
1879
2082
|
clearProps() {
|
|
1880
2083
|
this.props = undefined;
|
|
1881
2084
|
this.sessionProps = {};
|
|
@@ -1906,7 +2109,7 @@ class PostHogCore extends PostHogCoreStateless {
|
|
|
1906
2109
|
}
|
|
1907
2110
|
}
|
|
1908
2111
|
return {
|
|
1909
|
-
$active_feature_flags
|
|
2112
|
+
...maybeAdd('$active_feature_flags', featureFlags ? Object.keys(featureFlags) : undefined),
|
|
1910
2113
|
...featureVariantProperties,
|
|
1911
2114
|
...super.getCommonEventProperties(),
|
|
1912
2115
|
};
|
|
@@ -1928,18 +2131,26 @@ class PostHogCore extends PostHogCoreStateless {
|
|
|
1928
2131
|
return '';
|
|
1929
2132
|
}
|
|
1930
2133
|
let sessionId = this.getPersistedProperty(PostHogPersistedProperty.SessionId);
|
|
1931
|
-
const
|
|
1932
|
-
|
|
2134
|
+
const sessionLastTimestamp = this.getPersistedProperty(PostHogPersistedProperty.SessionLastTimestamp) || 0;
|
|
2135
|
+
const sessionStartTimestamp = this.getPersistedProperty(PostHogPersistedProperty.SessionStartTimestamp) || 0;
|
|
2136
|
+
const now = Date.now();
|
|
2137
|
+
const sessionLastDif = now - sessionLastTimestamp;
|
|
2138
|
+
const sessionStartDif = now - sessionStartTimestamp;
|
|
2139
|
+
if (!sessionId ||
|
|
2140
|
+
sessionLastDif > this._sessionExpirationTimeSeconds * 1000 ||
|
|
2141
|
+
sessionStartDif > this._sessionMaxLengthSeconds * 1000) {
|
|
1933
2142
|
sessionId = uuidv7();
|
|
1934
2143
|
this.setPersistedProperty(PostHogPersistedProperty.SessionId, sessionId);
|
|
2144
|
+
this.setPersistedProperty(PostHogPersistedProperty.SessionStartTimestamp, now);
|
|
1935
2145
|
}
|
|
1936
|
-
this.setPersistedProperty(PostHogPersistedProperty.SessionLastTimestamp,
|
|
2146
|
+
this.setPersistedProperty(PostHogPersistedProperty.SessionLastTimestamp, now);
|
|
1937
2147
|
return sessionId;
|
|
1938
2148
|
}
|
|
1939
2149
|
resetSessionId() {
|
|
1940
2150
|
this.wrap(() => {
|
|
1941
2151
|
this.setPersistedProperty(PostHogPersistedProperty.SessionId, null);
|
|
1942
2152
|
this.setPersistedProperty(PostHogPersistedProperty.SessionLastTimestamp, null);
|
|
2153
|
+
this.setPersistedProperty(PostHogPersistedProperty.SessionStartTimestamp, null);
|
|
1943
2154
|
});
|
|
1944
2155
|
}
|
|
1945
2156
|
/**
|
|
@@ -1965,21 +2176,6 @@ class PostHogCore extends PostHogCoreStateless {
|
|
|
1965
2176
|
}
|
|
1966
2177
|
return this.getPersistedProperty(PostHogPersistedProperty.DistinctId) || this.getAnonymousId();
|
|
1967
2178
|
}
|
|
1968
|
-
async unregister(property) {
|
|
1969
|
-
this.wrap(() => {
|
|
1970
|
-
delete this.props[property];
|
|
1971
|
-
this.setPersistedProperty(PostHogPersistedProperty.Props, this.props);
|
|
1972
|
-
});
|
|
1973
|
-
}
|
|
1974
|
-
async register(properties) {
|
|
1975
|
-
this.wrap(() => {
|
|
1976
|
-
this.props = {
|
|
1977
|
-
...this.props,
|
|
1978
|
-
...properties,
|
|
1979
|
-
};
|
|
1980
|
-
this.setPersistedProperty(PostHogPersistedProperty.Props, this.props);
|
|
1981
|
-
});
|
|
1982
|
-
}
|
|
1983
2179
|
registerForSession(properties) {
|
|
1984
2180
|
this.sessionProps = {
|
|
1985
2181
|
...this.sessionProps,
|
|
@@ -2006,8 +2202,8 @@ class PostHogCore extends PostHogCoreStateless {
|
|
|
2006
2202
|
const userProps = properties?.$set || properties;
|
|
2007
2203
|
const allProperties = this.enrichProperties({
|
|
2008
2204
|
$anon_distinct_id: this.getAnonymousId(),
|
|
2009
|
-
$set
|
|
2010
|
-
$set_once
|
|
2205
|
+
...maybeAdd('$set', userProps),
|
|
2206
|
+
...maybeAdd('$set_once', userPropsOnce),
|
|
2011
2207
|
});
|
|
2012
2208
|
if (distinctId !== previousDistinctId) {
|
|
2013
2209
|
// We keep the AnonymousId to be used by decide calls and identify to link the previousId
|
|
@@ -2155,14 +2351,16 @@ class PostHogCore extends PostHogCoreStateless {
|
|
|
2155
2351
|
}
|
|
2156
2352
|
return this._decideAsync(sendAnonDistinctId);
|
|
2157
2353
|
}
|
|
2158
|
-
cacheSessionReplay(response) {
|
|
2354
|
+
cacheSessionReplay(source, response) {
|
|
2159
2355
|
const sessionReplay = response?.sessionRecording;
|
|
2160
2356
|
if (sessionReplay) {
|
|
2161
2357
|
this.setPersistedProperty(PostHogPersistedProperty.SessionReplay, sessionReplay);
|
|
2162
|
-
this.logMsgIfDebug(() => console.log('PostHog Debug',
|
|
2358
|
+
this.logMsgIfDebug(() => console.log('PostHog Debug', `Session replay config from ${source}: `, JSON.stringify(sessionReplay)));
|
|
2163
2359
|
}
|
|
2164
|
-
else {
|
|
2165
|
-
|
|
2360
|
+
else if (typeof sessionReplay === 'boolean' && sessionReplay === false) {
|
|
2361
|
+
// if session replay is disabled, we don't need to cache it
|
|
2362
|
+
// we need to check for this because the response might be undefined (/flags does not return sessionRecording yet)
|
|
2363
|
+
this.logMsgIfDebug(() => console.info('PostHog Debug', `Session replay config from ${source} disabled.`));
|
|
2166
2364
|
this.setPersistedProperty(PostHogPersistedProperty.SessionReplay, null);
|
|
2167
2365
|
}
|
|
2168
2366
|
}
|
|
@@ -2176,25 +2374,30 @@ class PostHogCore extends PostHogCoreStateless {
|
|
|
2176
2374
|
const remoteConfigWithoutSurveys = { ...response };
|
|
2177
2375
|
delete remoteConfigWithoutSurveys.surveys;
|
|
2178
2376
|
this.logMsgIfDebug(() => console.log('PostHog Debug', 'Fetched remote config: ', JSON.stringify(remoteConfigWithoutSurveys)));
|
|
2179
|
-
|
|
2180
|
-
|
|
2181
|
-
|
|
2182
|
-
|
|
2183
|
-
|
|
2184
|
-
|
|
2185
|
-
|
|
2186
|
-
|
|
2187
|
-
|
|
2188
|
-
|
|
2189
|
-
|
|
2190
|
-
|
|
2377
|
+
if (this.disableSurveys === false) {
|
|
2378
|
+
const surveys = response.surveys;
|
|
2379
|
+
let hasSurveys = true;
|
|
2380
|
+
if (!Array.isArray(surveys)) {
|
|
2381
|
+
// If surveys is not an array, it means there are no surveys (its a boolean instead)
|
|
2382
|
+
this.logMsgIfDebug(() => console.log('PostHog Debug', 'There are no surveys.'));
|
|
2383
|
+
hasSurveys = false;
|
|
2384
|
+
}
|
|
2385
|
+
else {
|
|
2386
|
+
this.logMsgIfDebug(() => console.log('PostHog Debug', 'Surveys fetched from remote config: ', JSON.stringify(surveys)));
|
|
2387
|
+
}
|
|
2388
|
+
if (hasSurveys) {
|
|
2389
|
+
this.setPersistedProperty(PostHogPersistedProperty.Surveys, surveys);
|
|
2390
|
+
}
|
|
2391
|
+
else {
|
|
2392
|
+
this.setPersistedProperty(PostHogPersistedProperty.Surveys, null);
|
|
2393
|
+
}
|
|
2191
2394
|
}
|
|
2192
2395
|
else {
|
|
2193
2396
|
this.setPersistedProperty(PostHogPersistedProperty.Surveys, null);
|
|
2194
2397
|
}
|
|
2195
2398
|
// we cache the surveys in its own storage key
|
|
2196
2399
|
this.setPersistedProperty(PostHogPersistedProperty.RemoteConfig, remoteConfigWithoutSurveys);
|
|
2197
|
-
this.cacheSessionReplay(response);
|
|
2400
|
+
this.cacheSessionReplay('remote config', response);
|
|
2198
2401
|
// we only dont load flags if the remote config has no feature flags
|
|
2199
2402
|
if (response.hasFeatureFlags === false) {
|
|
2200
2403
|
// resetting flags to empty object
|
|
@@ -2251,7 +2454,7 @@ class PostHogCore extends PostHogCoreStateless {
|
|
|
2251
2454
|
this.setKnownFeatureFlagDetails(newFeatureFlagDetails);
|
|
2252
2455
|
// Mark that we hit the /decide endpoint so we can capture this in the $feature_flag_called event
|
|
2253
2456
|
this.setPersistedProperty(PostHogPersistedProperty.DecideEndpointWasHit, true);
|
|
2254
|
-
this.cacheSessionReplay(res);
|
|
2457
|
+
this.cacheSessionReplay('decide/flags', res);
|
|
2255
2458
|
}
|
|
2256
2459
|
return res;
|
|
2257
2460
|
})
|
|
@@ -2337,14 +2540,14 @@ class PostHogCore extends PostHogCoreStateless {
|
|
|
2337
2540
|
this.capture('$feature_flag_called', {
|
|
2338
2541
|
$feature_flag: key,
|
|
2339
2542
|
$feature_flag_response: response,
|
|
2340
|
-
$feature_flag_id
|
|
2341
|
-
$feature_flag_version
|
|
2342
|
-
$feature_flag_reason
|
|
2343
|
-
$feature_flag_bootstrapped_response
|
|
2344
|
-
$feature_flag_bootstrapped_payload
|
|
2543
|
+
...maybeAdd('$feature_flag_id', featureFlag?.metadata?.id),
|
|
2544
|
+
...maybeAdd('$feature_flag_version', featureFlag?.metadata?.version),
|
|
2545
|
+
...maybeAdd('$feature_flag_reason', featureFlag?.reason?.description ?? featureFlag?.reason?.code),
|
|
2546
|
+
...maybeAdd('$feature_flag_bootstrapped_response', bootstrappedResponse),
|
|
2547
|
+
...maybeAdd('$feature_flag_bootstrapped_payload', bootstrappedPayload),
|
|
2345
2548
|
// If we haven't yet received a response from the /decide endpoint, we must have used the bootstrapped value
|
|
2346
2549
|
$used_bootstrap_value: !this.getPersistedProperty(PostHogPersistedProperty.DecideEndpointWasHit),
|
|
2347
|
-
$feature_flag_request_id
|
|
2550
|
+
...maybeAdd('$feature_flag_request_id', details.requestId),
|
|
2348
2551
|
});
|
|
2349
2552
|
}
|
|
2350
2553
|
// If we have flags we either return the value (true or string) or false
|
|
@@ -2418,7 +2621,7 @@ class PostHogCore extends PostHogCoreStateless {
|
|
|
2418
2621
|
.catch((e) => {
|
|
2419
2622
|
cb?.(e, undefined);
|
|
2420
2623
|
if (!cb) {
|
|
2421
|
-
this.logMsgIfDebug(() => console.log('
|
|
2624
|
+
this.logMsgIfDebug(() => console.log('PostHog Debug', 'Error reloading feature flags', e));
|
|
2422
2625
|
}
|
|
2423
2626
|
});
|
|
2424
2627
|
}
|
|
@@ -2499,8 +2702,6 @@ class PostHogCore extends PostHogCoreStateless {
|
|
|
2499
2702
|
}
|
|
2500
2703
|
}
|
|
2501
2704
|
|
|
2502
|
-
var version = "3.5.0";
|
|
2503
|
-
|
|
2504
2705
|
function getContext(window) {
|
|
2505
2706
|
let context = {};
|
|
2506
2707
|
if (window?.navigator) {
|
|
@@ -2804,39 +3005,45 @@ const getStorage = (type, window) => {
|
|
|
2804
3005
|
}
|
|
2805
3006
|
};
|
|
2806
3007
|
|
|
2807
|
-
// import { patch } from 'rrweb/typings/utils'
|
|
2808
|
-
|
|
2809
|
-
|
|
2810
|
-
|
|
2811
|
-
|
|
2812
|
-
|
|
2813
|
-
|
|
2814
|
-
|
|
2815
|
-
|
|
2816
|
-
|
|
2817
|
-
|
|
2818
|
-
|
|
2819
|
-
|
|
2820
|
-
|
|
2821
|
-
|
|
2822
|
-
|
|
2823
|
-
|
|
2824
|
-
|
|
2825
|
-
|
|
2826
|
-
|
|
2827
|
-
|
|
2828
|
-
|
|
2829
|
-
|
|
2830
|
-
|
|
2831
|
-
|
|
2832
|
-
|
|
2833
|
-
|
|
2834
|
-
|
|
2835
|
-
|
|
2836
|
-
|
|
2837
|
-
|
|
2838
|
-
|
|
2839
|
-
|
|
3008
|
+
// import { patch } from 'rrweb/typings/utils'
|
|
3009
|
+
// copied from: https://github.com/PostHog/posthog-js/blob/main/src/extensions/replay/rrweb-plugins/patch.ts
|
|
3010
|
+
// which was copied from https://github.com/rrweb-io/rrweb/blob/8aea5b00a4dfe5a6f59bd2ae72bb624f45e51e81/packages/rrweb/src/utils.ts#L129
|
|
3011
|
+
// which was copied from https://github.com/getsentry/sentry-javascript/blob/b2109071975af8bf0316d3b5b38f519bdaf5dc15/packages/utils/src/object.ts
|
|
3012
|
+
// copied from: https://github.com/PostHog/posthog-js/blob/main/react/src/utils/type-utils.ts#L4
|
|
3013
|
+
const isFunction = function (f) {
|
|
3014
|
+
return typeof f === 'function';
|
|
3015
|
+
};
|
|
3016
|
+
function patch(source, name, replacement) {
|
|
3017
|
+
try {
|
|
3018
|
+
if (!(name in source)) {
|
|
3019
|
+
return () => {
|
|
3020
|
+
//
|
|
3021
|
+
};
|
|
3022
|
+
}
|
|
3023
|
+
const original = source[name];
|
|
3024
|
+
const wrapped = replacement(original);
|
|
3025
|
+
// Make sure it's a function first, as we need to attach an empty prototype for `defineProperties` to work
|
|
3026
|
+
// otherwise it'll throw "TypeError: Object.defineProperties called on non-object"
|
|
3027
|
+
if (isFunction(wrapped)) {
|
|
3028
|
+
wrapped.prototype = wrapped.prototype || {};
|
|
3029
|
+
Object.defineProperties(wrapped, {
|
|
3030
|
+
__posthog_wrapped__: {
|
|
3031
|
+
enumerable: false,
|
|
3032
|
+
value: true
|
|
3033
|
+
}
|
|
3034
|
+
});
|
|
3035
|
+
}
|
|
3036
|
+
source[name] = wrapped;
|
|
3037
|
+
return () => {
|
|
3038
|
+
source[name] = original;
|
|
3039
|
+
};
|
|
3040
|
+
} catch {
|
|
3041
|
+
return () => {
|
|
3042
|
+
//
|
|
3043
|
+
};
|
|
3044
|
+
// This can throw if multiple fill happens on a global object like XMLHttpRequest
|
|
3045
|
+
// Fixes https://github.com/getsentry/sentry-javascript/issues/2043
|
|
3046
|
+
}
|
|
2840
3047
|
}
|
|
2841
3048
|
|
|
2842
3049
|
class PostHog extends PostHogCore {
|
|
@@ -2942,4 +3149,4 @@ class PostHog extends PostHogCore {
|
|
|
2942
3149
|
}
|
|
2943
3150
|
|
|
2944
3151
|
export { PostHog, PostHog as default };
|
|
2945
|
-
//# sourceMappingURL=index.
|
|
3152
|
+
//# sourceMappingURL=index.mjs.map
|