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
|
@@ -2,6 +2,8 @@
|
|
|
2
2
|
|
|
3
3
|
Object.defineProperty(exports, '__esModule', { value: true });
|
|
4
4
|
|
|
5
|
+
var version = "3.6.0";
|
|
6
|
+
|
|
5
7
|
var PostHogPersistedProperty;
|
|
6
8
|
(function (PostHogPersistedProperty) {
|
|
7
9
|
PostHogPersistedProperty["AnonymousId"] = "anonymous_id";
|
|
@@ -17,6 +19,7 @@ var PostHogPersistedProperty;
|
|
|
17
19
|
PostHogPersistedProperty["Queue"] = "queue";
|
|
18
20
|
PostHogPersistedProperty["OptedOut"] = "opted_out";
|
|
19
21
|
PostHogPersistedProperty["SessionId"] = "session_id";
|
|
22
|
+
PostHogPersistedProperty["SessionStartTimestamp"] = "session_start_timestamp";
|
|
20
23
|
PostHogPersistedProperty["SessionLastTimestamp"] = "session_timestamp";
|
|
21
24
|
PostHogPersistedProperty["PersonProperties"] = "person_properties";
|
|
22
25
|
PostHogPersistedProperty["GroupProperties"] = "group_properties";
|
|
@@ -291,6 +294,7 @@ const NEW_FLAGS_EXCLUDED_HASHES = new Set([
|
|
|
291
294
|
'fc80b8e2',
|
|
292
295
|
'75cc0998',
|
|
293
296
|
]);
|
|
297
|
+
const STRING_FORMAT = 'utf8';
|
|
294
298
|
function assert(truthyValue, message) {
|
|
295
299
|
if (!truthyValue || typeof truthyValue !== 'string' || isEmpty(truthyValue)) {
|
|
296
300
|
throw new Error(message);
|
|
@@ -343,12 +347,8 @@ const isError = (x) => {
|
|
|
343
347
|
return x instanceof Error;
|
|
344
348
|
};
|
|
345
349
|
function getFetch() {
|
|
346
|
-
return typeof fetch !== 'undefined' ? fetch : typeof
|
|
350
|
+
return typeof fetch !== 'undefined' ? fetch : typeof globalThis.fetch !== 'undefined' ? globalThis.fetch : undefined;
|
|
347
351
|
}
|
|
348
|
-
// copied from: https://github.com/PostHog/posthog-js/blob/main/react/src/utils/type-utils.ts#L4
|
|
349
|
-
const isFunction = function (f) {
|
|
350
|
-
return typeof f === 'function';
|
|
351
|
-
};
|
|
352
352
|
// FNV-1a hash function
|
|
353
353
|
// https://en.wikipedia.org/wiki/Fowler%E2%80%93Noll%E2%80%93Vo_hash_function
|
|
354
354
|
// I know, I know, I'm rolling my own hash function, but I didn't want to take on
|
|
@@ -372,6 +372,9 @@ function isTokenInRollout(token, percentage = 0, excludedHashes) {
|
|
|
372
372
|
const hashInt = parseInt(tokenHash, 16);
|
|
373
373
|
const hashFloat = hashInt / 0xffffffff;
|
|
374
374
|
return hashFloat < percentage;
|
|
375
|
+
}
|
|
376
|
+
function allSettled(promises) {
|
|
377
|
+
return Promise.all(promises.map((p) => (p ?? Promise.resolve()).then((value) => ({ status: 'fulfilled', value }), (reason) => ({ status: 'rejected', reason }))));
|
|
375
378
|
}
|
|
376
379
|
|
|
377
380
|
// Copyright (c) 2013 Pieroxy <pieroxy@pieroxy.net>
|
|
@@ -1236,11 +1239,21 @@ const uuidv7 = () => uuidv7obj().toString();
|
|
|
1236
1239
|
const uuidv7obj = () => (defaultGenerator || (defaultGenerator = new V7Generator())).generate();
|
|
1237
1240
|
|
|
1238
1241
|
class PostHogFetchHttpError extends Error {
|
|
1239
|
-
constructor(response) {
|
|
1240
|
-
super('HTTP error while fetching PostHog: ' + response.status);
|
|
1242
|
+
constructor(response, reqByteLength) {
|
|
1243
|
+
super('HTTP error while fetching PostHog: status=' + response.status + ', reqByteLength=' + reqByteLength);
|
|
1241
1244
|
this.response = response;
|
|
1245
|
+
this.reqByteLength = reqByteLength;
|
|
1242
1246
|
this.name = 'PostHogFetchHttpError';
|
|
1243
1247
|
}
|
|
1248
|
+
get status() {
|
|
1249
|
+
return this.response.status;
|
|
1250
|
+
}
|
|
1251
|
+
get text() {
|
|
1252
|
+
return this.response.text();
|
|
1253
|
+
}
|
|
1254
|
+
get json() {
|
|
1255
|
+
return this.response.json();
|
|
1256
|
+
}
|
|
1244
1257
|
}
|
|
1245
1258
|
class PostHogFetchNetworkError extends Error {
|
|
1246
1259
|
constructor(error) {
|
|
@@ -1252,9 +1265,27 @@ class PostHogFetchNetworkError extends Error {
|
|
|
1252
1265
|
this.name = 'PostHogFetchNetworkError';
|
|
1253
1266
|
}
|
|
1254
1267
|
}
|
|
1268
|
+
const maybeAdd = (key, value) => value !== undefined ? { [key]: value } : {};
|
|
1269
|
+
async function logFlushError(err) {
|
|
1270
|
+
if (err instanceof PostHogFetchHttpError) {
|
|
1271
|
+
let text = '';
|
|
1272
|
+
try {
|
|
1273
|
+
text = await err.text;
|
|
1274
|
+
}
|
|
1275
|
+
catch { }
|
|
1276
|
+
console.error(`Error while flushing PostHog: message=${err.message}, response body=${text}`, err);
|
|
1277
|
+
}
|
|
1278
|
+
else {
|
|
1279
|
+
console.error('Error while flushing PostHog', err);
|
|
1280
|
+
}
|
|
1281
|
+
return Promise.resolve();
|
|
1282
|
+
}
|
|
1255
1283
|
function isPostHogFetchError(err) {
|
|
1256
1284
|
return typeof err === 'object' && (err instanceof PostHogFetchHttpError || err instanceof PostHogFetchNetworkError);
|
|
1257
1285
|
}
|
|
1286
|
+
function isPostHogFetchContentTooLargeError(err) {
|
|
1287
|
+
return typeof err === 'object' && err instanceof PostHogFetchHttpError && err.status === 413;
|
|
1288
|
+
}
|
|
1258
1289
|
var QuotaLimitedFeature;
|
|
1259
1290
|
(function (QuotaLimitedFeature) {
|
|
1260
1291
|
QuotaLimitedFeature["FeatureFlags"] = "feature_flags";
|
|
@@ -1263,6 +1294,7 @@ var QuotaLimitedFeature;
|
|
|
1263
1294
|
class PostHogCoreStateless {
|
|
1264
1295
|
constructor(apiKey, options) {
|
|
1265
1296
|
this.flushPromise = null;
|
|
1297
|
+
this.shutdownPromise = null;
|
|
1266
1298
|
this.pendingPromises = {};
|
|
1267
1299
|
// internal
|
|
1268
1300
|
this._events = new SimpleEventEmitter();
|
|
@@ -1385,12 +1417,26 @@ class PostHogCoreStateless {
|
|
|
1385
1417
|
this.enqueue('identify', payload, options);
|
|
1386
1418
|
});
|
|
1387
1419
|
}
|
|
1420
|
+
async identifyStatelessImmediate(distinctId, properties, options) {
|
|
1421
|
+
const payload = {
|
|
1422
|
+
...this.buildPayload({
|
|
1423
|
+
distinct_id: distinctId,
|
|
1424
|
+
event: '$identify',
|
|
1425
|
+
properties,
|
|
1426
|
+
}),
|
|
1427
|
+
};
|
|
1428
|
+
await this.sendImmediate('identify', payload, options);
|
|
1429
|
+
}
|
|
1388
1430
|
captureStateless(distinctId, event, properties, options) {
|
|
1389
1431
|
this.wrap(() => {
|
|
1390
1432
|
const payload = this.buildPayload({ distinct_id: distinctId, event, properties });
|
|
1391
1433
|
this.enqueue('capture', payload, options);
|
|
1392
1434
|
});
|
|
1393
1435
|
}
|
|
1436
|
+
async captureStatelessImmediate(distinctId, event, properties, options) {
|
|
1437
|
+
const payload = this.buildPayload({ distinct_id: distinctId, event, properties });
|
|
1438
|
+
await this.sendImmediate('capture', payload, options);
|
|
1439
|
+
}
|
|
1394
1440
|
aliasStateless(alias, distinctId, properties, options) {
|
|
1395
1441
|
this.wrap(() => {
|
|
1396
1442
|
const payload = this.buildPayload({
|
|
@@ -1405,6 +1451,18 @@ class PostHogCoreStateless {
|
|
|
1405
1451
|
this.enqueue('alias', payload, options);
|
|
1406
1452
|
});
|
|
1407
1453
|
}
|
|
1454
|
+
async aliasStatelessImmediate(alias, distinctId, properties, options) {
|
|
1455
|
+
const payload = this.buildPayload({
|
|
1456
|
+
event: '$create_alias',
|
|
1457
|
+
distinct_id: distinctId,
|
|
1458
|
+
properties: {
|
|
1459
|
+
...(properties || {}),
|
|
1460
|
+
distinct_id: distinctId,
|
|
1461
|
+
alias,
|
|
1462
|
+
},
|
|
1463
|
+
});
|
|
1464
|
+
await this.sendImmediate('alias', payload, options);
|
|
1465
|
+
}
|
|
1408
1466
|
/***
|
|
1409
1467
|
*** GROUPS
|
|
1410
1468
|
***/
|
|
@@ -1468,6 +1526,7 @@ class PostHogCoreStateless {
|
|
|
1468
1526
|
...extraPayload,
|
|
1469
1527
|
}),
|
|
1470
1528
|
};
|
|
1529
|
+
this.logMsgIfDebug(() => console.log('PostHog Debug', 'Decide URL', url));
|
|
1471
1530
|
// Don't retry /decide API calls
|
|
1472
1531
|
return this.fetchWithRetry(url, fetchOptions, { retryCount: 0 }, this.featureFlagsRequestTimeoutMs)
|
|
1473
1532
|
.then((response) => response.json())
|
|
@@ -1585,7 +1644,7 @@ class PostHogCoreStateless {
|
|
|
1585
1644
|
async getSurveysStateless() {
|
|
1586
1645
|
await this._initPromise;
|
|
1587
1646
|
if (this.disableSurveys === true) {
|
|
1588
|
-
this.logMsgIfDebug(() => console.log('Loading surveys is disabled.'));
|
|
1647
|
+
this.logMsgIfDebug(() => console.log('PostHog Debug', 'Loading surveys is disabled.'));
|
|
1589
1648
|
return [];
|
|
1590
1649
|
}
|
|
1591
1650
|
const url = `${this.host}/api/surveys/?token=${this.apiKey}`;
|
|
@@ -1615,6 +1674,30 @@ class PostHogCoreStateless {
|
|
|
1615
1674
|
}
|
|
1616
1675
|
return newSurveys ?? [];
|
|
1617
1676
|
}
|
|
1677
|
+
get props() {
|
|
1678
|
+
if (!this._props) {
|
|
1679
|
+
this._props = this.getPersistedProperty(PostHogPersistedProperty.Props);
|
|
1680
|
+
}
|
|
1681
|
+
return this._props || {};
|
|
1682
|
+
}
|
|
1683
|
+
set props(val) {
|
|
1684
|
+
this._props = val;
|
|
1685
|
+
}
|
|
1686
|
+
async register(properties) {
|
|
1687
|
+
this.wrap(() => {
|
|
1688
|
+
this.props = {
|
|
1689
|
+
...this.props,
|
|
1690
|
+
...properties,
|
|
1691
|
+
};
|
|
1692
|
+
this.setPersistedProperty(PostHogPersistedProperty.Props, this.props);
|
|
1693
|
+
});
|
|
1694
|
+
}
|
|
1695
|
+
async unregister(property) {
|
|
1696
|
+
this.wrap(() => {
|
|
1697
|
+
delete this.props[property];
|
|
1698
|
+
this.setPersistedProperty(PostHogPersistedProperty.Props, this.props);
|
|
1699
|
+
});
|
|
1700
|
+
}
|
|
1618
1701
|
/***
|
|
1619
1702
|
*** QUEUEING AND FLUSHING
|
|
1620
1703
|
***/
|
|
@@ -1624,25 +1707,7 @@ class PostHogCoreStateless {
|
|
|
1624
1707
|
this._events.emit(type, `Library is disabled. Not sending event. To re-enable, call posthog.optIn()`);
|
|
1625
1708
|
return;
|
|
1626
1709
|
}
|
|
1627
|
-
const message =
|
|
1628
|
-
..._message,
|
|
1629
|
-
type: type,
|
|
1630
|
-
library: this.getLibraryId(),
|
|
1631
|
-
library_version: this.getLibraryVersion(),
|
|
1632
|
-
timestamp: options?.timestamp ? options?.timestamp : currentISOTime(),
|
|
1633
|
-
uuid: options?.uuid ? options.uuid : uuidv7(),
|
|
1634
|
-
};
|
|
1635
|
-
const addGeoipDisableProperty = options?.disableGeoip ?? this.disableGeoip;
|
|
1636
|
-
if (addGeoipDisableProperty) {
|
|
1637
|
-
if (!message.properties) {
|
|
1638
|
-
message.properties = {};
|
|
1639
|
-
}
|
|
1640
|
-
message['properties']['$geoip_disable'] = true;
|
|
1641
|
-
}
|
|
1642
|
-
if (message.distinctId) {
|
|
1643
|
-
message.distinct_id = message.distinctId;
|
|
1644
|
-
delete message.distinctId;
|
|
1645
|
-
}
|
|
1710
|
+
const message = this.prepareMessage(type, _message, options);
|
|
1646
1711
|
const queue = this.getPersistedProperty(PostHogPersistedProperty.Queue) || [];
|
|
1647
1712
|
if (queue.length >= this.maxQueueSize) {
|
|
1648
1713
|
queue.shift();
|
|
@@ -1660,6 +1725,72 @@ class PostHogCoreStateless {
|
|
|
1660
1725
|
}
|
|
1661
1726
|
});
|
|
1662
1727
|
}
|
|
1728
|
+
async sendImmediate(type, _message, options) {
|
|
1729
|
+
if (this.disabled) {
|
|
1730
|
+
this.logMsgIfDebug(() => console.warn('[PostHog] The client is disabled'));
|
|
1731
|
+
return;
|
|
1732
|
+
}
|
|
1733
|
+
if (!this._isInitialized) {
|
|
1734
|
+
await this._initPromise;
|
|
1735
|
+
}
|
|
1736
|
+
if (this.optedOut) {
|
|
1737
|
+
this._events.emit(type, `Library is disabled. Not sending event. To re-enable, call posthog.optIn()`);
|
|
1738
|
+
return;
|
|
1739
|
+
}
|
|
1740
|
+
const data = {
|
|
1741
|
+
api_key: this.apiKey,
|
|
1742
|
+
batch: [this.prepareMessage(type, _message, options)],
|
|
1743
|
+
sent_at: currentISOTime(),
|
|
1744
|
+
};
|
|
1745
|
+
if (this.historicalMigration) {
|
|
1746
|
+
data.historical_migration = true;
|
|
1747
|
+
}
|
|
1748
|
+
const payload = JSON.stringify(data);
|
|
1749
|
+
const url = this.captureMode === 'form'
|
|
1750
|
+
? `${this.host}/e/?ip=1&_=${currentTimestamp()}&v=${this.getLibraryVersion()}`
|
|
1751
|
+
: `${this.host}/batch/`;
|
|
1752
|
+
const fetchOptions = this.captureMode === 'form'
|
|
1753
|
+
? {
|
|
1754
|
+
method: 'POST',
|
|
1755
|
+
mode: 'no-cors',
|
|
1756
|
+
credentials: 'omit',
|
|
1757
|
+
headers: { ...this.getCustomHeaders(), 'Content-Type': 'application/x-www-form-urlencoded' },
|
|
1758
|
+
body: `data=${encodeURIComponent(LZString.compressToBase64(payload))}&compression=lz64`,
|
|
1759
|
+
}
|
|
1760
|
+
: {
|
|
1761
|
+
method: 'POST',
|
|
1762
|
+
headers: { ...this.getCustomHeaders(), 'Content-Type': 'application/json' },
|
|
1763
|
+
body: payload,
|
|
1764
|
+
};
|
|
1765
|
+
try {
|
|
1766
|
+
await this.fetchWithRetry(url, fetchOptions);
|
|
1767
|
+
}
|
|
1768
|
+
catch (err) {
|
|
1769
|
+
this._events.emit('error', err);
|
|
1770
|
+
}
|
|
1771
|
+
}
|
|
1772
|
+
prepareMessage(type, _message, options) {
|
|
1773
|
+
const message = {
|
|
1774
|
+
..._message,
|
|
1775
|
+
type: type,
|
|
1776
|
+
library: this.getLibraryId(),
|
|
1777
|
+
library_version: this.getLibraryVersion(),
|
|
1778
|
+
timestamp: options?.timestamp ? options?.timestamp : currentISOTime(),
|
|
1779
|
+
uuid: options?.uuid ? options.uuid : uuidv7(),
|
|
1780
|
+
};
|
|
1781
|
+
const addGeoipDisableProperty = options?.disableGeoip ?? this.disableGeoip;
|
|
1782
|
+
if (addGeoipDisableProperty) {
|
|
1783
|
+
if (!message.properties) {
|
|
1784
|
+
message.properties = {};
|
|
1785
|
+
}
|
|
1786
|
+
message['properties']['$geoip_disable'] = true;
|
|
1787
|
+
}
|
|
1788
|
+
if (message.distinctId) {
|
|
1789
|
+
message.distinct_id = message.distinctId;
|
|
1790
|
+
delete message.distinctId;
|
|
1791
|
+
}
|
|
1792
|
+
return message;
|
|
1793
|
+
}
|
|
1663
1794
|
clearFlushTimer() {
|
|
1664
1795
|
if (this._flushTimer) {
|
|
1665
1796
|
clearTimeout(this._flushTimer);
|
|
@@ -1671,16 +1802,49 @@ class PostHogCoreStateless {
|
|
|
1671
1802
|
* Avoids unnecessary promise errors
|
|
1672
1803
|
*/
|
|
1673
1804
|
flushBackground() {
|
|
1674
|
-
void this.flush().catch(() => {
|
|
1805
|
+
void this.flush().catch(async (err) => {
|
|
1806
|
+
await logFlushError(err);
|
|
1807
|
+
});
|
|
1675
1808
|
}
|
|
1809
|
+
/**
|
|
1810
|
+
* Flushes the queue
|
|
1811
|
+
*
|
|
1812
|
+
* This function will return a promise that will resolve when the flush is complete,
|
|
1813
|
+
* or reject if there was an error (for example if the server or network is down).
|
|
1814
|
+
*
|
|
1815
|
+
* If there is already a flush in progress, this function will wait for that flush to complete.
|
|
1816
|
+
*
|
|
1817
|
+
* It's recommended to do error handling in the callback of the promise.
|
|
1818
|
+
*
|
|
1819
|
+
* @example
|
|
1820
|
+
* posthog.flush().then(() => {
|
|
1821
|
+
* console.log('Flush complete')
|
|
1822
|
+
* }).catch((err) => {
|
|
1823
|
+
* console.error('Flush failed', err)
|
|
1824
|
+
* })
|
|
1825
|
+
*
|
|
1826
|
+
*
|
|
1827
|
+
* @throws PostHogFetchHttpError
|
|
1828
|
+
* @throws PostHogFetchNetworkError
|
|
1829
|
+
* @throws Error
|
|
1830
|
+
*/
|
|
1676
1831
|
async flush() {
|
|
1677
|
-
|
|
1678
|
-
|
|
1832
|
+
// Wait for the current flush operation to finish (regardless of success or failure), then try to flush again.
|
|
1833
|
+
// Use allSettled instead of finally to be defensive around flush throwing errors immediately rather than rejecting.
|
|
1834
|
+
// Use a custom allSettled implementation to avoid issues with patching Promise on RN
|
|
1835
|
+
const nextFlushPromise = allSettled([this.flushPromise]).then(() => {
|
|
1836
|
+
return this._flush();
|
|
1837
|
+
});
|
|
1838
|
+
this.flushPromise = nextFlushPromise;
|
|
1839
|
+
void this.addPendingPromise(nextFlushPromise);
|
|
1840
|
+
allSettled([nextFlushPromise]).then(() => {
|
|
1841
|
+
// If there are no others waiting to flush, clear the promise.
|
|
1842
|
+
// We don't strictly need to do this, but it could make debugging easier
|
|
1843
|
+
if (this.flushPromise === nextFlushPromise) {
|
|
1679
1844
|
this.flushPromise = null;
|
|
1680
|
-
}
|
|
1681
|
-
|
|
1682
|
-
|
|
1683
|
-
return this.flushPromise;
|
|
1845
|
+
}
|
|
1846
|
+
});
|
|
1847
|
+
return nextFlushPromise;
|
|
1684
1848
|
}
|
|
1685
1849
|
getCustomHeaders() {
|
|
1686
1850
|
// Don't set the user agent if we're not on a browser. The latest spec allows
|
|
@@ -1697,56 +1861,79 @@ class PostHogCoreStateless {
|
|
|
1697
1861
|
async _flush() {
|
|
1698
1862
|
this.clearFlushTimer();
|
|
1699
1863
|
await this._initPromise;
|
|
1700
|
-
|
|
1864
|
+
let queue = this.getPersistedProperty(PostHogPersistedProperty.Queue) || [];
|
|
1701
1865
|
if (!queue.length) {
|
|
1702
|
-
return
|
|
1703
|
-
}
|
|
1704
|
-
const items = queue.slice(0, this.maxBatchSize);
|
|
1705
|
-
const messages = items.map((item) => item.message);
|
|
1706
|
-
const persistQueueChange = () => {
|
|
1707
|
-
const refreshedQueue = this.getPersistedProperty(PostHogPersistedProperty.Queue) || [];
|
|
1708
|
-
this.setPersistedProperty(PostHogPersistedProperty.Queue, refreshedQueue.slice(items.length));
|
|
1709
|
-
};
|
|
1710
|
-
const data = {
|
|
1711
|
-
api_key: this.apiKey,
|
|
1712
|
-
batch: messages,
|
|
1713
|
-
sent_at: currentISOTime(),
|
|
1714
|
-
};
|
|
1715
|
-
if (this.historicalMigration) {
|
|
1716
|
-
data.historical_migration = true;
|
|
1866
|
+
return;
|
|
1717
1867
|
}
|
|
1718
|
-
const
|
|
1719
|
-
const
|
|
1720
|
-
|
|
1721
|
-
|
|
1722
|
-
|
|
1723
|
-
|
|
1724
|
-
|
|
1725
|
-
|
|
1726
|
-
|
|
1727
|
-
|
|
1728
|
-
|
|
1868
|
+
const sentMessages = [];
|
|
1869
|
+
const originalQueueLength = queue.length;
|
|
1870
|
+
while (queue.length > 0 && sentMessages.length < originalQueueLength) {
|
|
1871
|
+
const batchItems = queue.slice(0, this.maxBatchSize);
|
|
1872
|
+
const batchMessages = batchItems.map((item) => item.message);
|
|
1873
|
+
const persistQueueChange = () => {
|
|
1874
|
+
const refreshedQueue = this.getPersistedProperty(PostHogPersistedProperty.Queue) || [];
|
|
1875
|
+
const newQueue = refreshedQueue.slice(batchItems.length);
|
|
1876
|
+
this.setPersistedProperty(PostHogPersistedProperty.Queue, newQueue);
|
|
1877
|
+
queue = newQueue;
|
|
1878
|
+
};
|
|
1879
|
+
const data = {
|
|
1880
|
+
api_key: this.apiKey,
|
|
1881
|
+
batch: batchMessages,
|
|
1882
|
+
sent_at: currentISOTime(),
|
|
1883
|
+
};
|
|
1884
|
+
if (this.historicalMigration) {
|
|
1885
|
+
data.historical_migration = true;
|
|
1729
1886
|
}
|
|
1730
|
-
|
|
1731
|
-
|
|
1732
|
-
|
|
1733
|
-
|
|
1887
|
+
const payload = JSON.stringify(data);
|
|
1888
|
+
const url = this.captureMode === 'form'
|
|
1889
|
+
? `${this.host}/e/?ip=1&_=${currentTimestamp()}&v=${this.getLibraryVersion()}`
|
|
1890
|
+
: `${this.host}/batch/`;
|
|
1891
|
+
const fetchOptions = this.captureMode === 'form'
|
|
1892
|
+
? {
|
|
1893
|
+
method: 'POST',
|
|
1894
|
+
mode: 'no-cors',
|
|
1895
|
+
credentials: 'omit',
|
|
1896
|
+
headers: { ...this.getCustomHeaders(), 'Content-Type': 'application/x-www-form-urlencoded' },
|
|
1897
|
+
body: `data=${encodeURIComponent(LZString.compressToBase64(payload))}&compression=lz64`,
|
|
1898
|
+
}
|
|
1899
|
+
: {
|
|
1900
|
+
method: 'POST',
|
|
1901
|
+
headers: { ...this.getCustomHeaders(), 'Content-Type': 'application/json' },
|
|
1902
|
+
body: payload,
|
|
1903
|
+
};
|
|
1904
|
+
const retryOptions = {
|
|
1905
|
+
retryCheck: (err) => {
|
|
1906
|
+
// don't automatically retry on 413 errors, we want to reduce the batch size first
|
|
1907
|
+
if (isPostHogFetchContentTooLargeError(err)) {
|
|
1908
|
+
return false;
|
|
1909
|
+
}
|
|
1910
|
+
// otherwise, retry on network errors
|
|
1911
|
+
return isPostHogFetchError(err);
|
|
1912
|
+
},
|
|
1734
1913
|
};
|
|
1735
|
-
|
|
1736
|
-
|
|
1737
|
-
}
|
|
1738
|
-
catch (err) {
|
|
1739
|
-
// depending on the error type, eg a malformed JSON or broken queue, it'll always return an error
|
|
1740
|
-
// 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
|
|
1741
|
-
if (!(err instanceof PostHogFetchNetworkError)) {
|
|
1742
|
-
persistQueueChange();
|
|
1914
|
+
try {
|
|
1915
|
+
await this.fetchWithRetry(url, fetchOptions, retryOptions);
|
|
1743
1916
|
}
|
|
1744
|
-
|
|
1745
|
-
|
|
1917
|
+
catch (err) {
|
|
1918
|
+
if (isPostHogFetchContentTooLargeError(err) && batchMessages.length > 1) {
|
|
1919
|
+
// if we get a 413 error, we want to reduce the batch size and try again
|
|
1920
|
+
this.maxBatchSize = Math.max(1, Math.floor(batchMessages.length / 2));
|
|
1921
|
+
this.logMsgIfDebug(() => console.warn(`Received 413 when sending batch of size ${batchMessages.length}, reducing batch size to ${this.maxBatchSize}`));
|
|
1922
|
+
// do not persist the queue change, we want to retry the same batch
|
|
1923
|
+
continue;
|
|
1924
|
+
}
|
|
1925
|
+
// depending on the error type, eg a malformed JSON or broken queue, it'll always return an error
|
|
1926
|
+
// 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
|
|
1927
|
+
if (!(err instanceof PostHogFetchNetworkError)) {
|
|
1928
|
+
persistQueueChange();
|
|
1929
|
+
}
|
|
1930
|
+
this._events.emit('error', err);
|
|
1931
|
+
throw err;
|
|
1932
|
+
}
|
|
1933
|
+
persistQueueChange();
|
|
1934
|
+
sentMessages.push(...batchMessages);
|
|
1746
1935
|
}
|
|
1747
|
-
|
|
1748
|
-
this._events.emit('flush', messages);
|
|
1749
|
-
return messages;
|
|
1936
|
+
this._events.emit('flush', sentMessages);
|
|
1750
1937
|
}
|
|
1751
1938
|
async fetchWithRetry(url, options, retryOptions, requestTimeout) {
|
|
1752
1939
|
var _a;
|
|
@@ -1755,6 +1942,15 @@ class PostHogCoreStateless {
|
|
|
1755
1942
|
setTimeout(() => ctrl.abort(), ms);
|
|
1756
1943
|
return ctrl.signal;
|
|
1757
1944
|
});
|
|
1945
|
+
const body = options.body ? options.body : '';
|
|
1946
|
+
let reqByteLength = -1;
|
|
1947
|
+
try {
|
|
1948
|
+
reqByteLength = Buffer.byteLength(body, STRING_FORMAT);
|
|
1949
|
+
}
|
|
1950
|
+
catch {
|
|
1951
|
+
const encoded = new TextEncoder().encode(body);
|
|
1952
|
+
reqByteLength = encoded.length;
|
|
1953
|
+
}
|
|
1758
1954
|
return await retriable(async () => {
|
|
1759
1955
|
let res = null;
|
|
1760
1956
|
try {
|
|
@@ -1772,12 +1968,12 @@ class PostHogCoreStateless {
|
|
|
1772
1968
|
// https://developer.mozilla.org/en-US/docs/Web/API/Request/mode#no-cors
|
|
1773
1969
|
const isNoCors = options.mode === 'no-cors';
|
|
1774
1970
|
if (!isNoCors && (res.status < 200 || res.status >= 400)) {
|
|
1775
|
-
throw new PostHogFetchHttpError(res);
|
|
1971
|
+
throw new PostHogFetchHttpError(res, reqByteLength);
|
|
1776
1972
|
}
|
|
1777
1973
|
return res;
|
|
1778
1974
|
}, { ...this._retryOptions, ...retryOptions });
|
|
1779
1975
|
}
|
|
1780
|
-
async
|
|
1976
|
+
async _shutdown(shutdownTimeoutMs = 30000) {
|
|
1781
1977
|
// A little tricky - we want to have a max shutdown time and enforce it, even if that means we have some
|
|
1782
1978
|
// dangling promises. We'll keep track of the timeout and resolve/reject based on that.
|
|
1783
1979
|
await this._initPromise;
|
|
@@ -1804,7 +2000,7 @@ class PostHogCoreStateless {
|
|
|
1804
2000
|
if (!isPostHogFetchError(e)) {
|
|
1805
2001
|
throw e;
|
|
1806
2002
|
}
|
|
1807
|
-
|
|
2003
|
+
await logFlushError(e);
|
|
1808
2004
|
}
|
|
1809
2005
|
};
|
|
1810
2006
|
return Promise.race([
|
|
@@ -1818,6 +2014,22 @@ class PostHogCoreStateless {
|
|
|
1818
2014
|
doShutdown(),
|
|
1819
2015
|
]);
|
|
1820
2016
|
}
|
|
2017
|
+
/**
|
|
2018
|
+
* Call shutdown() once before the node process exits, so ensure that all events have been sent and all promises
|
|
2019
|
+
* have resolved. Do not use this function if you intend to keep using this PostHog instance after calling it.
|
|
2020
|
+
* @param shutdownTimeoutMs
|
|
2021
|
+
*/
|
|
2022
|
+
async shutdown(shutdownTimeoutMs = 30000) {
|
|
2023
|
+
if (this.shutdownPromise) {
|
|
2024
|
+
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'));
|
|
2025
|
+
}
|
|
2026
|
+
else {
|
|
2027
|
+
this.shutdownPromise = this._shutdown(shutdownTimeoutMs).finally(() => {
|
|
2028
|
+
this.shutdownPromise = null;
|
|
2029
|
+
});
|
|
2030
|
+
}
|
|
2031
|
+
return this.shutdownPromise;
|
|
2032
|
+
}
|
|
1821
2033
|
}
|
|
1822
2034
|
class PostHogCore extends PostHogCoreStateless {
|
|
1823
2035
|
constructor(apiKey, options) {
|
|
@@ -1827,6 +2039,7 @@ class PostHogCore extends PostHogCoreStateless {
|
|
|
1827
2039
|
const featureFlagsRequestTimeoutMs = options?.featureFlagsRequestTimeoutMs ?? 10000; // 10 seconds
|
|
1828
2040
|
super(apiKey, { ...options, disableGeoip: disableGeoipOption, featureFlagsRequestTimeoutMs });
|
|
1829
2041
|
this.flagCallReported = {};
|
|
2042
|
+
this._sessionMaxLengthSeconds = 24 * 60 * 60; // 24 hours
|
|
1830
2043
|
this.sessionProps = {};
|
|
1831
2044
|
this.sendFeatureFlagEvent = options?.sendFeatureFlagEvent ?? true;
|
|
1832
2045
|
this._sessionExpirationTimeSeconds = options?.sessionExpirationTimeSeconds ?? 1800; // 30 minutes
|
|
@@ -1870,16 +2083,6 @@ class PostHogCore extends PostHogCoreStateless {
|
|
|
1870
2083
|
}
|
|
1871
2084
|
}
|
|
1872
2085
|
}
|
|
1873
|
-
// NOTE: Props are lazy loaded from localstorage hence the complex getter setter logic
|
|
1874
|
-
get props() {
|
|
1875
|
-
if (!this._props) {
|
|
1876
|
-
this._props = this.getPersistedProperty(PostHogPersistedProperty.Props);
|
|
1877
|
-
}
|
|
1878
|
-
return this._props || {};
|
|
1879
|
-
}
|
|
1880
|
-
set props(val) {
|
|
1881
|
-
this._props = val;
|
|
1882
|
-
}
|
|
1883
2086
|
clearProps() {
|
|
1884
2087
|
this.props = undefined;
|
|
1885
2088
|
this.sessionProps = {};
|
|
@@ -1910,7 +2113,7 @@ class PostHogCore extends PostHogCoreStateless {
|
|
|
1910
2113
|
}
|
|
1911
2114
|
}
|
|
1912
2115
|
return {
|
|
1913
|
-
$active_feature_flags
|
|
2116
|
+
...maybeAdd('$active_feature_flags', featureFlags ? Object.keys(featureFlags) : undefined),
|
|
1914
2117
|
...featureVariantProperties,
|
|
1915
2118
|
...super.getCommonEventProperties(),
|
|
1916
2119
|
};
|
|
@@ -1932,18 +2135,26 @@ class PostHogCore extends PostHogCoreStateless {
|
|
|
1932
2135
|
return '';
|
|
1933
2136
|
}
|
|
1934
2137
|
let sessionId = this.getPersistedProperty(PostHogPersistedProperty.SessionId);
|
|
1935
|
-
const
|
|
1936
|
-
|
|
2138
|
+
const sessionLastTimestamp = this.getPersistedProperty(PostHogPersistedProperty.SessionLastTimestamp) || 0;
|
|
2139
|
+
const sessionStartTimestamp = this.getPersistedProperty(PostHogPersistedProperty.SessionStartTimestamp) || 0;
|
|
2140
|
+
const now = Date.now();
|
|
2141
|
+
const sessionLastDif = now - sessionLastTimestamp;
|
|
2142
|
+
const sessionStartDif = now - sessionStartTimestamp;
|
|
2143
|
+
if (!sessionId ||
|
|
2144
|
+
sessionLastDif > this._sessionExpirationTimeSeconds * 1000 ||
|
|
2145
|
+
sessionStartDif > this._sessionMaxLengthSeconds * 1000) {
|
|
1937
2146
|
sessionId = uuidv7();
|
|
1938
2147
|
this.setPersistedProperty(PostHogPersistedProperty.SessionId, sessionId);
|
|
2148
|
+
this.setPersistedProperty(PostHogPersistedProperty.SessionStartTimestamp, now);
|
|
1939
2149
|
}
|
|
1940
|
-
this.setPersistedProperty(PostHogPersistedProperty.SessionLastTimestamp,
|
|
2150
|
+
this.setPersistedProperty(PostHogPersistedProperty.SessionLastTimestamp, now);
|
|
1941
2151
|
return sessionId;
|
|
1942
2152
|
}
|
|
1943
2153
|
resetSessionId() {
|
|
1944
2154
|
this.wrap(() => {
|
|
1945
2155
|
this.setPersistedProperty(PostHogPersistedProperty.SessionId, null);
|
|
1946
2156
|
this.setPersistedProperty(PostHogPersistedProperty.SessionLastTimestamp, null);
|
|
2157
|
+
this.setPersistedProperty(PostHogPersistedProperty.SessionStartTimestamp, null);
|
|
1947
2158
|
});
|
|
1948
2159
|
}
|
|
1949
2160
|
/**
|
|
@@ -1969,21 +2180,6 @@ class PostHogCore extends PostHogCoreStateless {
|
|
|
1969
2180
|
}
|
|
1970
2181
|
return this.getPersistedProperty(PostHogPersistedProperty.DistinctId) || this.getAnonymousId();
|
|
1971
2182
|
}
|
|
1972
|
-
async unregister(property) {
|
|
1973
|
-
this.wrap(() => {
|
|
1974
|
-
delete this.props[property];
|
|
1975
|
-
this.setPersistedProperty(PostHogPersistedProperty.Props, this.props);
|
|
1976
|
-
});
|
|
1977
|
-
}
|
|
1978
|
-
async register(properties) {
|
|
1979
|
-
this.wrap(() => {
|
|
1980
|
-
this.props = {
|
|
1981
|
-
...this.props,
|
|
1982
|
-
...properties,
|
|
1983
|
-
};
|
|
1984
|
-
this.setPersistedProperty(PostHogPersistedProperty.Props, this.props);
|
|
1985
|
-
});
|
|
1986
|
-
}
|
|
1987
2183
|
registerForSession(properties) {
|
|
1988
2184
|
this.sessionProps = {
|
|
1989
2185
|
...this.sessionProps,
|
|
@@ -2010,8 +2206,8 @@ class PostHogCore extends PostHogCoreStateless {
|
|
|
2010
2206
|
const userProps = properties?.$set || properties;
|
|
2011
2207
|
const allProperties = this.enrichProperties({
|
|
2012
2208
|
$anon_distinct_id: this.getAnonymousId(),
|
|
2013
|
-
$set
|
|
2014
|
-
$set_once
|
|
2209
|
+
...maybeAdd('$set', userProps),
|
|
2210
|
+
...maybeAdd('$set_once', userPropsOnce),
|
|
2015
2211
|
});
|
|
2016
2212
|
if (distinctId !== previousDistinctId) {
|
|
2017
2213
|
// We keep the AnonymousId to be used by decide calls and identify to link the previousId
|
|
@@ -2159,14 +2355,16 @@ class PostHogCore extends PostHogCoreStateless {
|
|
|
2159
2355
|
}
|
|
2160
2356
|
return this._decideAsync(sendAnonDistinctId);
|
|
2161
2357
|
}
|
|
2162
|
-
cacheSessionReplay(response) {
|
|
2358
|
+
cacheSessionReplay(source, response) {
|
|
2163
2359
|
const sessionReplay = response?.sessionRecording;
|
|
2164
2360
|
if (sessionReplay) {
|
|
2165
2361
|
this.setPersistedProperty(PostHogPersistedProperty.SessionReplay, sessionReplay);
|
|
2166
|
-
this.logMsgIfDebug(() => console.log('PostHog Debug',
|
|
2362
|
+
this.logMsgIfDebug(() => console.log('PostHog Debug', `Session replay config from ${source}: `, JSON.stringify(sessionReplay)));
|
|
2167
2363
|
}
|
|
2168
|
-
else {
|
|
2169
|
-
|
|
2364
|
+
else if (typeof sessionReplay === 'boolean' && sessionReplay === false) {
|
|
2365
|
+
// if session replay is disabled, we don't need to cache it
|
|
2366
|
+
// we need to check for this because the response might be undefined (/flags does not return sessionRecording yet)
|
|
2367
|
+
this.logMsgIfDebug(() => console.info('PostHog Debug', `Session replay config from ${source} disabled.`));
|
|
2170
2368
|
this.setPersistedProperty(PostHogPersistedProperty.SessionReplay, null);
|
|
2171
2369
|
}
|
|
2172
2370
|
}
|
|
@@ -2180,25 +2378,30 @@ class PostHogCore extends PostHogCoreStateless {
|
|
|
2180
2378
|
const remoteConfigWithoutSurveys = { ...response };
|
|
2181
2379
|
delete remoteConfigWithoutSurveys.surveys;
|
|
2182
2380
|
this.logMsgIfDebug(() => console.log('PostHog Debug', 'Fetched remote config: ', JSON.stringify(remoteConfigWithoutSurveys)));
|
|
2183
|
-
|
|
2184
|
-
|
|
2185
|
-
|
|
2186
|
-
|
|
2187
|
-
|
|
2188
|
-
|
|
2189
|
-
|
|
2190
|
-
|
|
2191
|
-
|
|
2192
|
-
|
|
2193
|
-
|
|
2194
|
-
|
|
2381
|
+
if (this.disableSurveys === false) {
|
|
2382
|
+
const surveys = response.surveys;
|
|
2383
|
+
let hasSurveys = true;
|
|
2384
|
+
if (!Array.isArray(surveys)) {
|
|
2385
|
+
// If surveys is not an array, it means there are no surveys (its a boolean instead)
|
|
2386
|
+
this.logMsgIfDebug(() => console.log('PostHog Debug', 'There are no surveys.'));
|
|
2387
|
+
hasSurveys = false;
|
|
2388
|
+
}
|
|
2389
|
+
else {
|
|
2390
|
+
this.logMsgIfDebug(() => console.log('PostHog Debug', 'Surveys fetched from remote config: ', JSON.stringify(surveys)));
|
|
2391
|
+
}
|
|
2392
|
+
if (hasSurveys) {
|
|
2393
|
+
this.setPersistedProperty(PostHogPersistedProperty.Surveys, surveys);
|
|
2394
|
+
}
|
|
2395
|
+
else {
|
|
2396
|
+
this.setPersistedProperty(PostHogPersistedProperty.Surveys, null);
|
|
2397
|
+
}
|
|
2195
2398
|
}
|
|
2196
2399
|
else {
|
|
2197
2400
|
this.setPersistedProperty(PostHogPersistedProperty.Surveys, null);
|
|
2198
2401
|
}
|
|
2199
2402
|
// we cache the surveys in its own storage key
|
|
2200
2403
|
this.setPersistedProperty(PostHogPersistedProperty.RemoteConfig, remoteConfigWithoutSurveys);
|
|
2201
|
-
this.cacheSessionReplay(response);
|
|
2404
|
+
this.cacheSessionReplay('remote config', response);
|
|
2202
2405
|
// we only dont load flags if the remote config has no feature flags
|
|
2203
2406
|
if (response.hasFeatureFlags === false) {
|
|
2204
2407
|
// resetting flags to empty object
|
|
@@ -2255,7 +2458,7 @@ class PostHogCore extends PostHogCoreStateless {
|
|
|
2255
2458
|
this.setKnownFeatureFlagDetails(newFeatureFlagDetails);
|
|
2256
2459
|
// Mark that we hit the /decide endpoint so we can capture this in the $feature_flag_called event
|
|
2257
2460
|
this.setPersistedProperty(PostHogPersistedProperty.DecideEndpointWasHit, true);
|
|
2258
|
-
this.cacheSessionReplay(res);
|
|
2461
|
+
this.cacheSessionReplay('decide/flags', res);
|
|
2259
2462
|
}
|
|
2260
2463
|
return res;
|
|
2261
2464
|
})
|
|
@@ -2341,14 +2544,14 @@ class PostHogCore extends PostHogCoreStateless {
|
|
|
2341
2544
|
this.capture('$feature_flag_called', {
|
|
2342
2545
|
$feature_flag: key,
|
|
2343
2546
|
$feature_flag_response: response,
|
|
2344
|
-
$feature_flag_id
|
|
2345
|
-
$feature_flag_version
|
|
2346
|
-
$feature_flag_reason
|
|
2347
|
-
$feature_flag_bootstrapped_response
|
|
2348
|
-
$feature_flag_bootstrapped_payload
|
|
2547
|
+
...maybeAdd('$feature_flag_id', featureFlag?.metadata?.id),
|
|
2548
|
+
...maybeAdd('$feature_flag_version', featureFlag?.metadata?.version),
|
|
2549
|
+
...maybeAdd('$feature_flag_reason', featureFlag?.reason?.description ?? featureFlag?.reason?.code),
|
|
2550
|
+
...maybeAdd('$feature_flag_bootstrapped_response', bootstrappedResponse),
|
|
2551
|
+
...maybeAdd('$feature_flag_bootstrapped_payload', bootstrappedPayload),
|
|
2349
2552
|
// If we haven't yet received a response from the /decide endpoint, we must have used the bootstrapped value
|
|
2350
2553
|
$used_bootstrap_value: !this.getPersistedProperty(PostHogPersistedProperty.DecideEndpointWasHit),
|
|
2351
|
-
$feature_flag_request_id
|
|
2554
|
+
...maybeAdd('$feature_flag_request_id', details.requestId),
|
|
2352
2555
|
});
|
|
2353
2556
|
}
|
|
2354
2557
|
// If we have flags we either return the value (true or string) or false
|
|
@@ -2422,7 +2625,7 @@ class PostHogCore extends PostHogCoreStateless {
|
|
|
2422
2625
|
.catch((e) => {
|
|
2423
2626
|
cb?.(e, undefined);
|
|
2424
2627
|
if (!cb) {
|
|
2425
|
-
this.logMsgIfDebug(() => console.log('
|
|
2628
|
+
this.logMsgIfDebug(() => console.log('PostHog Debug', 'Error reloading feature flags', e));
|
|
2426
2629
|
}
|
|
2427
2630
|
});
|
|
2428
2631
|
}
|
|
@@ -2503,8 +2706,6 @@ class PostHogCore extends PostHogCoreStateless {
|
|
|
2503
2706
|
}
|
|
2504
2707
|
}
|
|
2505
2708
|
|
|
2506
|
-
var version = "3.5.0";
|
|
2507
|
-
|
|
2508
2709
|
function getContext(window) {
|
|
2509
2710
|
let context = {};
|
|
2510
2711
|
if (window?.navigator) {
|
|
@@ -2808,39 +3009,45 @@ const getStorage = (type, window) => {
|
|
|
2808
3009
|
}
|
|
2809
3010
|
};
|
|
2810
3011
|
|
|
2811
|
-
// import { patch } from 'rrweb/typings/utils'
|
|
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
|
-
|
|
2840
|
-
|
|
2841
|
-
|
|
2842
|
-
|
|
2843
|
-
|
|
3012
|
+
// import { patch } from 'rrweb/typings/utils'
|
|
3013
|
+
// copied from: https://github.com/PostHog/posthog-js/blob/main/src/extensions/replay/rrweb-plugins/patch.ts
|
|
3014
|
+
// which was copied from https://github.com/rrweb-io/rrweb/blob/8aea5b00a4dfe5a6f59bd2ae72bb624f45e51e81/packages/rrweb/src/utils.ts#L129
|
|
3015
|
+
// which was copied from https://github.com/getsentry/sentry-javascript/blob/b2109071975af8bf0316d3b5b38f519bdaf5dc15/packages/utils/src/object.ts
|
|
3016
|
+
// copied from: https://github.com/PostHog/posthog-js/blob/main/react/src/utils/type-utils.ts#L4
|
|
3017
|
+
const isFunction = function (f) {
|
|
3018
|
+
return typeof f === 'function';
|
|
3019
|
+
};
|
|
3020
|
+
function patch(source, name, replacement) {
|
|
3021
|
+
try {
|
|
3022
|
+
if (!(name in source)) {
|
|
3023
|
+
return () => {
|
|
3024
|
+
//
|
|
3025
|
+
};
|
|
3026
|
+
}
|
|
3027
|
+
const original = source[name];
|
|
3028
|
+
const wrapped = replacement(original);
|
|
3029
|
+
// Make sure it's a function first, as we need to attach an empty prototype for `defineProperties` to work
|
|
3030
|
+
// otherwise it'll throw "TypeError: Object.defineProperties called on non-object"
|
|
3031
|
+
if (isFunction(wrapped)) {
|
|
3032
|
+
wrapped.prototype = wrapped.prototype || {};
|
|
3033
|
+
Object.defineProperties(wrapped, {
|
|
3034
|
+
__posthog_wrapped__: {
|
|
3035
|
+
enumerable: false,
|
|
3036
|
+
value: true
|
|
3037
|
+
}
|
|
3038
|
+
});
|
|
3039
|
+
}
|
|
3040
|
+
source[name] = wrapped;
|
|
3041
|
+
return () => {
|
|
3042
|
+
source[name] = original;
|
|
3043
|
+
};
|
|
3044
|
+
} catch {
|
|
3045
|
+
return () => {
|
|
3046
|
+
//
|
|
3047
|
+
};
|
|
3048
|
+
// This can throw if multiple fill happens on a global object like XMLHttpRequest
|
|
3049
|
+
// Fixes https://github.com/getsentry/sentry-javascript/issues/2043
|
|
3050
|
+
}
|
|
2844
3051
|
}
|
|
2845
3052
|
|
|
2846
3053
|
class PostHog extends PostHogCore {
|
|
@@ -2947,4 +3154,4 @@ class PostHog extends PostHogCore {
|
|
|
2947
3154
|
|
|
2948
3155
|
exports.PostHog = PostHog;
|
|
2949
3156
|
exports["default"] = PostHog;
|
|
2950
|
-
//# sourceMappingURL=index.cjs.
|
|
3157
|
+
//# sourceMappingURL=index.cjs.map
|