posthog-js-lite 3.5.0 → 3.5.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +6 -0
- package/lib/{index.cjs.js → index.cjs} +297 -140
- package/lib/index.cjs.map +1 -0
- package/lib/index.d.ts +661 -642
- package/lib/{index.esm.js → index.mjs} +297 -140
- 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 +6 -9
- 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.5.1";
|
|
2
|
+
|
|
1
3
|
var PostHogPersistedProperty;
|
|
2
4
|
(function (PostHogPersistedProperty) {
|
|
3
5
|
PostHogPersistedProperty["AnonymousId"] = "anonymous_id";
|
|
@@ -287,6 +289,7 @@ const NEW_FLAGS_EXCLUDED_HASHES = new Set([
|
|
|
287
289
|
'fc80b8e2',
|
|
288
290
|
'75cc0998',
|
|
289
291
|
]);
|
|
292
|
+
const STRING_FORMAT = 'utf8';
|
|
290
293
|
function assert(truthyValue, message) {
|
|
291
294
|
if (!truthyValue || typeof truthyValue !== 'string' || isEmpty(truthyValue)) {
|
|
292
295
|
throw new Error(message);
|
|
@@ -339,12 +342,8 @@ const isError = (x) => {
|
|
|
339
342
|
return x instanceof Error;
|
|
340
343
|
};
|
|
341
344
|
function getFetch() {
|
|
342
|
-
return typeof fetch !== 'undefined' ? fetch : typeof
|
|
345
|
+
return typeof fetch !== 'undefined' ? fetch : typeof globalThis.fetch !== 'undefined' ? globalThis.fetch : undefined;
|
|
343
346
|
}
|
|
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
347
|
// FNV-1a hash function
|
|
349
348
|
// https://en.wikipedia.org/wiki/Fowler%E2%80%93Noll%E2%80%93Vo_hash_function
|
|
350
349
|
// I know, I know, I'm rolling my own hash function, but I didn't want to take on
|
|
@@ -1232,11 +1231,21 @@ const uuidv7 = () => uuidv7obj().toString();
|
|
|
1232
1231
|
const uuidv7obj = () => (defaultGenerator || (defaultGenerator = new V7Generator())).generate();
|
|
1233
1232
|
|
|
1234
1233
|
class PostHogFetchHttpError extends Error {
|
|
1235
|
-
constructor(response) {
|
|
1236
|
-
super('HTTP error while fetching PostHog: ' + response.status);
|
|
1234
|
+
constructor(response, reqByteLength) {
|
|
1235
|
+
super('HTTP error while fetching PostHog: status=' + response.status + ', reqByteLength=' + reqByteLength);
|
|
1237
1236
|
this.response = response;
|
|
1237
|
+
this.reqByteLength = reqByteLength;
|
|
1238
1238
|
this.name = 'PostHogFetchHttpError';
|
|
1239
1239
|
}
|
|
1240
|
+
get status() {
|
|
1241
|
+
return this.response.status;
|
|
1242
|
+
}
|
|
1243
|
+
get text() {
|
|
1244
|
+
return this.response.text();
|
|
1245
|
+
}
|
|
1246
|
+
get json() {
|
|
1247
|
+
return this.response.json();
|
|
1248
|
+
}
|
|
1240
1249
|
}
|
|
1241
1250
|
class PostHogFetchNetworkError extends Error {
|
|
1242
1251
|
constructor(error) {
|
|
@@ -1248,9 +1257,26 @@ class PostHogFetchNetworkError extends Error {
|
|
|
1248
1257
|
this.name = 'PostHogFetchNetworkError';
|
|
1249
1258
|
}
|
|
1250
1259
|
}
|
|
1260
|
+
async function logFlushError(err) {
|
|
1261
|
+
if (err instanceof PostHogFetchHttpError) {
|
|
1262
|
+
let text = '';
|
|
1263
|
+
try {
|
|
1264
|
+
text = await err.text;
|
|
1265
|
+
}
|
|
1266
|
+
catch { }
|
|
1267
|
+
console.error(`Error while flushing PostHog: message=${err.message}, response body=${text}`, err);
|
|
1268
|
+
}
|
|
1269
|
+
else {
|
|
1270
|
+
console.error('Error while flushing PostHog', err);
|
|
1271
|
+
}
|
|
1272
|
+
return Promise.resolve();
|
|
1273
|
+
}
|
|
1251
1274
|
function isPostHogFetchError(err) {
|
|
1252
1275
|
return typeof err === 'object' && (err instanceof PostHogFetchHttpError || err instanceof PostHogFetchNetworkError);
|
|
1253
1276
|
}
|
|
1277
|
+
function isPostHogFetchContentTooLargeError(err) {
|
|
1278
|
+
return typeof err === 'object' && err instanceof PostHogFetchHttpError && err.status === 413;
|
|
1279
|
+
}
|
|
1254
1280
|
var QuotaLimitedFeature;
|
|
1255
1281
|
(function (QuotaLimitedFeature) {
|
|
1256
1282
|
QuotaLimitedFeature["FeatureFlags"] = "feature_flags";
|
|
@@ -1259,6 +1285,7 @@ var QuotaLimitedFeature;
|
|
|
1259
1285
|
class PostHogCoreStateless {
|
|
1260
1286
|
constructor(apiKey, options) {
|
|
1261
1287
|
this.flushPromise = null;
|
|
1288
|
+
this.shutdownPromise = null;
|
|
1262
1289
|
this.pendingPromises = {};
|
|
1263
1290
|
// internal
|
|
1264
1291
|
this._events = new SimpleEventEmitter();
|
|
@@ -1381,12 +1408,26 @@ class PostHogCoreStateless {
|
|
|
1381
1408
|
this.enqueue('identify', payload, options);
|
|
1382
1409
|
});
|
|
1383
1410
|
}
|
|
1411
|
+
async identifyStatelessImmediate(distinctId, properties, options) {
|
|
1412
|
+
const payload = {
|
|
1413
|
+
...this.buildPayload({
|
|
1414
|
+
distinct_id: distinctId,
|
|
1415
|
+
event: '$identify',
|
|
1416
|
+
properties,
|
|
1417
|
+
}),
|
|
1418
|
+
};
|
|
1419
|
+
await this.sendImmediate('identify', payload, options);
|
|
1420
|
+
}
|
|
1384
1421
|
captureStateless(distinctId, event, properties, options) {
|
|
1385
1422
|
this.wrap(() => {
|
|
1386
1423
|
const payload = this.buildPayload({ distinct_id: distinctId, event, properties });
|
|
1387
1424
|
this.enqueue('capture', payload, options);
|
|
1388
1425
|
});
|
|
1389
1426
|
}
|
|
1427
|
+
async captureStatelessImmediate(distinctId, event, properties, options) {
|
|
1428
|
+
const payload = this.buildPayload({ distinct_id: distinctId, event, properties });
|
|
1429
|
+
await this.sendImmediate('capture', payload, options);
|
|
1430
|
+
}
|
|
1390
1431
|
aliasStateless(alias, distinctId, properties, options) {
|
|
1391
1432
|
this.wrap(() => {
|
|
1392
1433
|
const payload = this.buildPayload({
|
|
@@ -1401,6 +1442,18 @@ class PostHogCoreStateless {
|
|
|
1401
1442
|
this.enqueue('alias', payload, options);
|
|
1402
1443
|
});
|
|
1403
1444
|
}
|
|
1445
|
+
async aliasStatelessImmediate(alias, distinctId, properties, options) {
|
|
1446
|
+
const payload = this.buildPayload({
|
|
1447
|
+
event: '$create_alias',
|
|
1448
|
+
distinct_id: distinctId,
|
|
1449
|
+
properties: {
|
|
1450
|
+
...(properties || {}),
|
|
1451
|
+
distinct_id: distinctId,
|
|
1452
|
+
alias,
|
|
1453
|
+
},
|
|
1454
|
+
});
|
|
1455
|
+
await this.sendImmediate('alias', payload, options);
|
|
1456
|
+
}
|
|
1404
1457
|
/***
|
|
1405
1458
|
*** GROUPS
|
|
1406
1459
|
***/
|
|
@@ -1611,6 +1664,30 @@ class PostHogCoreStateless {
|
|
|
1611
1664
|
}
|
|
1612
1665
|
return newSurveys ?? [];
|
|
1613
1666
|
}
|
|
1667
|
+
get props() {
|
|
1668
|
+
if (!this._props) {
|
|
1669
|
+
this._props = this.getPersistedProperty(PostHogPersistedProperty.Props);
|
|
1670
|
+
}
|
|
1671
|
+
return this._props || {};
|
|
1672
|
+
}
|
|
1673
|
+
set props(val) {
|
|
1674
|
+
this._props = val;
|
|
1675
|
+
}
|
|
1676
|
+
async register(properties) {
|
|
1677
|
+
this.wrap(() => {
|
|
1678
|
+
this.props = {
|
|
1679
|
+
...this.props,
|
|
1680
|
+
...properties,
|
|
1681
|
+
};
|
|
1682
|
+
this.setPersistedProperty(PostHogPersistedProperty.Props, this.props);
|
|
1683
|
+
});
|
|
1684
|
+
}
|
|
1685
|
+
async unregister(property) {
|
|
1686
|
+
this.wrap(() => {
|
|
1687
|
+
delete this.props[property];
|
|
1688
|
+
this.setPersistedProperty(PostHogPersistedProperty.Props, this.props);
|
|
1689
|
+
});
|
|
1690
|
+
}
|
|
1614
1691
|
/***
|
|
1615
1692
|
*** QUEUEING AND FLUSHING
|
|
1616
1693
|
***/
|
|
@@ -1620,25 +1697,7 @@ class PostHogCoreStateless {
|
|
|
1620
1697
|
this._events.emit(type, `Library is disabled. Not sending event. To re-enable, call posthog.optIn()`);
|
|
1621
1698
|
return;
|
|
1622
1699
|
}
|
|
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
|
-
}
|
|
1700
|
+
const message = this.prepareMessage(type, _message, options);
|
|
1642
1701
|
const queue = this.getPersistedProperty(PostHogPersistedProperty.Queue) || [];
|
|
1643
1702
|
if (queue.length >= this.maxQueueSize) {
|
|
1644
1703
|
queue.shift();
|
|
@@ -1656,6 +1715,73 @@ class PostHogCoreStateless {
|
|
|
1656
1715
|
}
|
|
1657
1716
|
});
|
|
1658
1717
|
}
|
|
1718
|
+
async sendImmediate(type, _message, options) {
|
|
1719
|
+
if (this.disabled) {
|
|
1720
|
+
this.logMsgIfDebug(() => console.warn('[PostHog] The client is disabled'));
|
|
1721
|
+
return;
|
|
1722
|
+
}
|
|
1723
|
+
if (!this._isInitialized) {
|
|
1724
|
+
await this._initPromise;
|
|
1725
|
+
}
|
|
1726
|
+
if (this.optedOut) {
|
|
1727
|
+
this._events.emit(type, `Library is disabled. Not sending event. To re-enable, call posthog.optIn()`);
|
|
1728
|
+
return;
|
|
1729
|
+
}
|
|
1730
|
+
const data = {
|
|
1731
|
+
api_key: this.apiKey,
|
|
1732
|
+
batch: [this.prepareMessage(type, _message, options)],
|
|
1733
|
+
sent_at: currentISOTime(),
|
|
1734
|
+
};
|
|
1735
|
+
if (this.historicalMigration) {
|
|
1736
|
+
data.historical_migration = true;
|
|
1737
|
+
}
|
|
1738
|
+
const payload = JSON.stringify(data);
|
|
1739
|
+
const url = this.captureMode === 'form'
|
|
1740
|
+
? `${this.host}/e/?ip=1&_=${currentTimestamp()}&v=${this.getLibraryVersion()}`
|
|
1741
|
+
: `${this.host}/batch/`;
|
|
1742
|
+
const fetchOptions = this.captureMode === 'form'
|
|
1743
|
+
? {
|
|
1744
|
+
method: 'POST',
|
|
1745
|
+
mode: 'no-cors',
|
|
1746
|
+
credentials: 'omit',
|
|
1747
|
+
headers: { ...this.getCustomHeaders(), 'Content-Type': 'application/x-www-form-urlencoded' },
|
|
1748
|
+
body: `data=${encodeURIComponent(LZString.compressToBase64(payload))}&compression=lz64`,
|
|
1749
|
+
}
|
|
1750
|
+
: {
|
|
1751
|
+
method: 'POST',
|
|
1752
|
+
headers: { ...this.getCustomHeaders(), 'Content-Type': 'application/json' },
|
|
1753
|
+
body: payload,
|
|
1754
|
+
};
|
|
1755
|
+
try {
|
|
1756
|
+
await this.fetchWithRetry(url, fetchOptions);
|
|
1757
|
+
}
|
|
1758
|
+
catch (err) {
|
|
1759
|
+
this._events.emit('error', err);
|
|
1760
|
+
throw err;
|
|
1761
|
+
}
|
|
1762
|
+
}
|
|
1763
|
+
prepareMessage(type, _message, options) {
|
|
1764
|
+
const message = {
|
|
1765
|
+
..._message,
|
|
1766
|
+
type: type,
|
|
1767
|
+
library: this.getLibraryId(),
|
|
1768
|
+
library_version: this.getLibraryVersion(),
|
|
1769
|
+
timestamp: options?.timestamp ? options?.timestamp : currentISOTime(),
|
|
1770
|
+
uuid: options?.uuid ? options.uuid : uuidv7(),
|
|
1771
|
+
};
|
|
1772
|
+
const addGeoipDisableProperty = options?.disableGeoip ?? this.disableGeoip;
|
|
1773
|
+
if (addGeoipDisableProperty) {
|
|
1774
|
+
if (!message.properties) {
|
|
1775
|
+
message.properties = {};
|
|
1776
|
+
}
|
|
1777
|
+
message['properties']['$geoip_disable'] = true;
|
|
1778
|
+
}
|
|
1779
|
+
if (message.distinctId) {
|
|
1780
|
+
message.distinct_id = message.distinctId;
|
|
1781
|
+
delete message.distinctId;
|
|
1782
|
+
}
|
|
1783
|
+
return message;
|
|
1784
|
+
}
|
|
1659
1785
|
clearFlushTimer() {
|
|
1660
1786
|
if (this._flushTimer) {
|
|
1661
1787
|
clearTimeout(this._flushTimer);
|
|
@@ -1667,16 +1793,26 @@ class PostHogCoreStateless {
|
|
|
1667
1793
|
* Avoids unnecessary promise errors
|
|
1668
1794
|
*/
|
|
1669
1795
|
flushBackground() {
|
|
1670
|
-
void this.flush().catch(() => {
|
|
1796
|
+
void this.flush().catch(async (err) => {
|
|
1797
|
+
await logFlushError(err);
|
|
1798
|
+
});
|
|
1671
1799
|
}
|
|
1672
1800
|
async flush() {
|
|
1673
|
-
|
|
1674
|
-
|
|
1801
|
+
// Wait for the current flush operation to finish (regardless of success or failure), then try to flush again.
|
|
1802
|
+
// Use allSettled instead of finally to be defensive around flush throwing errors immediately rather than rejecting.
|
|
1803
|
+
const nextFlushPromise = Promise.allSettled([this.flushPromise]).then(() => {
|
|
1804
|
+
return this._flush();
|
|
1805
|
+
});
|
|
1806
|
+
this.flushPromise = nextFlushPromise;
|
|
1807
|
+
void this.addPendingPromise(nextFlushPromise);
|
|
1808
|
+
Promise.allSettled([nextFlushPromise]).then(() => {
|
|
1809
|
+
// If there are no others waiting to flush, clear the promise.
|
|
1810
|
+
// We don't strictly need to do this, but it could make debugging easier
|
|
1811
|
+
if (this.flushPromise === nextFlushPromise) {
|
|
1675
1812
|
this.flushPromise = null;
|
|
1676
|
-
}
|
|
1677
|
-
|
|
1678
|
-
|
|
1679
|
-
return this.flushPromise;
|
|
1813
|
+
}
|
|
1814
|
+
});
|
|
1815
|
+
return nextFlushPromise;
|
|
1680
1816
|
}
|
|
1681
1817
|
getCustomHeaders() {
|
|
1682
1818
|
// Don't set the user agent if we're not on a browser. The latest spec allows
|
|
@@ -1693,56 +1829,80 @@ class PostHogCoreStateless {
|
|
|
1693
1829
|
async _flush() {
|
|
1694
1830
|
this.clearFlushTimer();
|
|
1695
1831
|
await this._initPromise;
|
|
1696
|
-
|
|
1832
|
+
let queue = this.getPersistedProperty(PostHogPersistedProperty.Queue) || [];
|
|
1697
1833
|
if (!queue.length) {
|
|
1698
1834
|
return [];
|
|
1699
1835
|
}
|
|
1700
|
-
const
|
|
1701
|
-
const
|
|
1702
|
-
|
|
1703
|
-
const
|
|
1704
|
-
|
|
1705
|
-
|
|
1706
|
-
|
|
1707
|
-
|
|
1708
|
-
|
|
1709
|
-
|
|
1710
|
-
|
|
1711
|
-
|
|
1712
|
-
|
|
1713
|
-
|
|
1714
|
-
|
|
1715
|
-
|
|
1716
|
-
|
|
1717
|
-
|
|
1718
|
-
const fetchOptions = this.captureMode === 'form'
|
|
1719
|
-
? {
|
|
1720
|
-
method: 'POST',
|
|
1721
|
-
mode: 'no-cors',
|
|
1722
|
-
credentials: 'omit',
|
|
1723
|
-
headers: { ...this.getCustomHeaders(), 'Content-Type': 'application/x-www-form-urlencoded' },
|
|
1724
|
-
body: `data=${encodeURIComponent(LZString.compressToBase64(payload))}&compression=lz64`,
|
|
1836
|
+
const sentMessages = [];
|
|
1837
|
+
const originalQueueLength = queue.length;
|
|
1838
|
+
while (queue.length > 0 && sentMessages.length < originalQueueLength) {
|
|
1839
|
+
const batchItems = queue.slice(0, this.maxBatchSize);
|
|
1840
|
+
const batchMessages = batchItems.map((item) => item.message);
|
|
1841
|
+
const persistQueueChange = () => {
|
|
1842
|
+
const refreshedQueue = this.getPersistedProperty(PostHogPersistedProperty.Queue) || [];
|
|
1843
|
+
const newQueue = refreshedQueue.slice(batchItems.length);
|
|
1844
|
+
this.setPersistedProperty(PostHogPersistedProperty.Queue, newQueue);
|
|
1845
|
+
queue = newQueue;
|
|
1846
|
+
};
|
|
1847
|
+
const data = {
|
|
1848
|
+
api_key: this.apiKey,
|
|
1849
|
+
batch: batchMessages,
|
|
1850
|
+
sent_at: currentISOTime(),
|
|
1851
|
+
};
|
|
1852
|
+
if (this.historicalMigration) {
|
|
1853
|
+
data.historical_migration = true;
|
|
1725
1854
|
}
|
|
1726
|
-
|
|
1727
|
-
|
|
1728
|
-
|
|
1729
|
-
|
|
1855
|
+
const payload = JSON.stringify(data);
|
|
1856
|
+
const url = this.captureMode === 'form'
|
|
1857
|
+
? `${this.host}/e/?ip=1&_=${currentTimestamp()}&v=${this.getLibraryVersion()}`
|
|
1858
|
+
: `${this.host}/batch/`;
|
|
1859
|
+
const fetchOptions = this.captureMode === 'form'
|
|
1860
|
+
? {
|
|
1861
|
+
method: 'POST',
|
|
1862
|
+
mode: 'no-cors',
|
|
1863
|
+
credentials: 'omit',
|
|
1864
|
+
headers: { ...this.getCustomHeaders(), 'Content-Type': 'application/x-www-form-urlencoded' },
|
|
1865
|
+
body: `data=${encodeURIComponent(LZString.compressToBase64(payload))}&compression=lz64`,
|
|
1866
|
+
}
|
|
1867
|
+
: {
|
|
1868
|
+
method: 'POST',
|
|
1869
|
+
headers: { ...this.getCustomHeaders(), 'Content-Type': 'application/json' },
|
|
1870
|
+
body: payload,
|
|
1871
|
+
};
|
|
1872
|
+
const retryOptions = {
|
|
1873
|
+
retryCheck: (err) => {
|
|
1874
|
+
// don't automatically retry on 413 errors, we want to reduce the batch size first
|
|
1875
|
+
if (isPostHogFetchContentTooLargeError(err)) {
|
|
1876
|
+
return false;
|
|
1877
|
+
}
|
|
1878
|
+
// otherwise, retry on network errors
|
|
1879
|
+
return isPostHogFetchError(err);
|
|
1880
|
+
},
|
|
1730
1881
|
};
|
|
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();
|
|
1882
|
+
try {
|
|
1883
|
+
await this.fetchWithRetry(url, fetchOptions, retryOptions);
|
|
1739
1884
|
}
|
|
1740
|
-
|
|
1741
|
-
|
|
1885
|
+
catch (err) {
|
|
1886
|
+
if (isPostHogFetchContentTooLargeError(err) && batchMessages.length > 1) {
|
|
1887
|
+
// if we get a 413 error, we want to reduce the batch size and try again
|
|
1888
|
+
this.maxBatchSize = Math.max(1, Math.floor(batchMessages.length / 2));
|
|
1889
|
+
this.logMsgIfDebug(() => console.warn(`Received 413 when sending batch of size ${batchMessages.length}, reducing batch size to ${this.maxBatchSize}`));
|
|
1890
|
+
// do not persist the queue change, we want to retry the same batch
|
|
1891
|
+
continue;
|
|
1892
|
+
}
|
|
1893
|
+
// depending on the error type, eg a malformed JSON or broken queue, it'll always return an error
|
|
1894
|
+
// 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
|
|
1895
|
+
if (!(err instanceof PostHogFetchNetworkError)) {
|
|
1896
|
+
persistQueueChange();
|
|
1897
|
+
}
|
|
1898
|
+
this._events.emit('error', err);
|
|
1899
|
+
throw err;
|
|
1900
|
+
}
|
|
1901
|
+
persistQueueChange();
|
|
1902
|
+
sentMessages.push(...batchMessages);
|
|
1742
1903
|
}
|
|
1743
|
-
|
|
1744
|
-
|
|
1745
|
-
return messages;
|
|
1904
|
+
this._events.emit('flush', sentMessages);
|
|
1905
|
+
return sentMessages;
|
|
1746
1906
|
}
|
|
1747
1907
|
async fetchWithRetry(url, options, retryOptions, requestTimeout) {
|
|
1748
1908
|
var _a;
|
|
@@ -1751,6 +1911,8 @@ class PostHogCoreStateless {
|
|
|
1751
1911
|
setTimeout(() => ctrl.abort(), ms);
|
|
1752
1912
|
return ctrl.signal;
|
|
1753
1913
|
});
|
|
1914
|
+
const body = options.body ? options.body : '';
|
|
1915
|
+
const reqByteLength = Buffer.byteLength(body, STRING_FORMAT);
|
|
1754
1916
|
return await retriable(async () => {
|
|
1755
1917
|
let res = null;
|
|
1756
1918
|
try {
|
|
@@ -1768,12 +1930,12 @@ class PostHogCoreStateless {
|
|
|
1768
1930
|
// https://developer.mozilla.org/en-US/docs/Web/API/Request/mode#no-cors
|
|
1769
1931
|
const isNoCors = options.mode === 'no-cors';
|
|
1770
1932
|
if (!isNoCors && (res.status < 200 || res.status >= 400)) {
|
|
1771
|
-
throw new PostHogFetchHttpError(res);
|
|
1933
|
+
throw new PostHogFetchHttpError(res, reqByteLength);
|
|
1772
1934
|
}
|
|
1773
1935
|
return res;
|
|
1774
1936
|
}, { ...this._retryOptions, ...retryOptions });
|
|
1775
1937
|
}
|
|
1776
|
-
async
|
|
1938
|
+
async _shutdown(shutdownTimeoutMs = 30000) {
|
|
1777
1939
|
// A little tricky - we want to have a max shutdown time and enforce it, even if that means we have some
|
|
1778
1940
|
// dangling promises. We'll keep track of the timeout and resolve/reject based on that.
|
|
1779
1941
|
await this._initPromise;
|
|
@@ -1800,7 +1962,7 @@ class PostHogCoreStateless {
|
|
|
1800
1962
|
if (!isPostHogFetchError(e)) {
|
|
1801
1963
|
throw e;
|
|
1802
1964
|
}
|
|
1803
|
-
|
|
1965
|
+
await logFlushError(e);
|
|
1804
1966
|
}
|
|
1805
1967
|
};
|
|
1806
1968
|
return Promise.race([
|
|
@@ -1814,6 +1976,22 @@ class PostHogCoreStateless {
|
|
|
1814
1976
|
doShutdown(),
|
|
1815
1977
|
]);
|
|
1816
1978
|
}
|
|
1979
|
+
/**
|
|
1980
|
+
* Call shutdown() once before the node process exits, so ensure that all events have been sent and all promises
|
|
1981
|
+
* have resolved. Do not use this function if you intend to keep using this PostHog instance after calling it.
|
|
1982
|
+
* @param shutdownTimeoutMs
|
|
1983
|
+
*/
|
|
1984
|
+
async shutdown(shutdownTimeoutMs = 30000) {
|
|
1985
|
+
if (this.shutdownPromise) {
|
|
1986
|
+
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'));
|
|
1987
|
+
}
|
|
1988
|
+
else {
|
|
1989
|
+
this.shutdownPromise = this._shutdown(shutdownTimeoutMs).finally(() => {
|
|
1990
|
+
this.shutdownPromise = null;
|
|
1991
|
+
});
|
|
1992
|
+
}
|
|
1993
|
+
return this.shutdownPromise;
|
|
1994
|
+
}
|
|
1817
1995
|
}
|
|
1818
1996
|
class PostHogCore extends PostHogCoreStateless {
|
|
1819
1997
|
constructor(apiKey, options) {
|
|
@@ -1866,16 +2044,6 @@ class PostHogCore extends PostHogCoreStateless {
|
|
|
1866
2044
|
}
|
|
1867
2045
|
}
|
|
1868
2046
|
}
|
|
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
2047
|
clearProps() {
|
|
1880
2048
|
this.props = undefined;
|
|
1881
2049
|
this.sessionProps = {};
|
|
@@ -1965,21 +2133,6 @@ class PostHogCore extends PostHogCoreStateless {
|
|
|
1965
2133
|
}
|
|
1966
2134
|
return this.getPersistedProperty(PostHogPersistedProperty.DistinctId) || this.getAnonymousId();
|
|
1967
2135
|
}
|
|
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
2136
|
registerForSession(properties) {
|
|
1984
2137
|
this.sessionProps = {
|
|
1985
2138
|
...this.sessionProps,
|
|
@@ -2499,8 +2652,6 @@ class PostHogCore extends PostHogCoreStateless {
|
|
|
2499
2652
|
}
|
|
2500
2653
|
}
|
|
2501
2654
|
|
|
2502
|
-
var version = "3.5.0";
|
|
2503
|
-
|
|
2504
2655
|
function getContext(window) {
|
|
2505
2656
|
let context = {};
|
|
2506
2657
|
if (window?.navigator) {
|
|
@@ -2804,39 +2955,45 @@ const getStorage = (type, window) => {
|
|
|
2804
2955
|
}
|
|
2805
2956
|
};
|
|
2806
2957
|
|
|
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
|
-
|
|
2958
|
+
// import { patch } from 'rrweb/typings/utils'
|
|
2959
|
+
// copied from: https://github.com/PostHog/posthog-js/blob/main/src/extensions/replay/rrweb-plugins/patch.ts
|
|
2960
|
+
// which was copied from https://github.com/rrweb-io/rrweb/blob/8aea5b00a4dfe5a6f59bd2ae72bb624f45e51e81/packages/rrweb/src/utils.ts#L129
|
|
2961
|
+
// which was copied from https://github.com/getsentry/sentry-javascript/blob/b2109071975af8bf0316d3b5b38f519bdaf5dc15/packages/utils/src/object.ts
|
|
2962
|
+
// copied from: https://github.com/PostHog/posthog-js/blob/main/react/src/utils/type-utils.ts#L4
|
|
2963
|
+
const isFunction = function (f) {
|
|
2964
|
+
return typeof f === 'function';
|
|
2965
|
+
};
|
|
2966
|
+
function patch(source, name, replacement) {
|
|
2967
|
+
try {
|
|
2968
|
+
if (!(name in source)) {
|
|
2969
|
+
return () => {
|
|
2970
|
+
//
|
|
2971
|
+
};
|
|
2972
|
+
}
|
|
2973
|
+
const original = source[name];
|
|
2974
|
+
const wrapped = replacement(original);
|
|
2975
|
+
// Make sure it's a function first, as we need to attach an empty prototype for `defineProperties` to work
|
|
2976
|
+
// otherwise it'll throw "TypeError: Object.defineProperties called on non-object"
|
|
2977
|
+
if (isFunction(wrapped)) {
|
|
2978
|
+
wrapped.prototype = wrapped.prototype || {};
|
|
2979
|
+
Object.defineProperties(wrapped, {
|
|
2980
|
+
__posthog_wrapped__: {
|
|
2981
|
+
enumerable: false,
|
|
2982
|
+
value: true
|
|
2983
|
+
}
|
|
2984
|
+
});
|
|
2985
|
+
}
|
|
2986
|
+
source[name] = wrapped;
|
|
2987
|
+
return () => {
|
|
2988
|
+
source[name] = original;
|
|
2989
|
+
};
|
|
2990
|
+
} catch {
|
|
2991
|
+
return () => {
|
|
2992
|
+
//
|
|
2993
|
+
};
|
|
2994
|
+
// This can throw if multiple fill happens on a global object like XMLHttpRequest
|
|
2995
|
+
// Fixes https://github.com/getsentry/sentry-javascript/issues/2043
|
|
2996
|
+
}
|
|
2840
2997
|
}
|
|
2841
2998
|
|
|
2842
2999
|
class PostHog extends PostHogCore {
|
|
@@ -2942,4 +3099,4 @@ class PostHog extends PostHogCore {
|
|
|
2942
3099
|
}
|
|
2943
3100
|
|
|
2944
3101
|
export { PostHog, PostHog as default };
|
|
2945
|
-
//# sourceMappingURL=index.
|
|
3102
|
+
//# sourceMappingURL=index.mjs.map
|