posthog-js-lite 3.0.0-beta.1 → 3.0.0-beta.2
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 +87 -73
- package/lib/index.cjs.js.map +1 -1
- package/lib/index.d.ts +14 -5
- package/lib/index.esm.js +87 -73
- package/lib/index.esm.js.map +1 -1
- package/lib/posthog-core/src/index.d.ts +12 -5
- package/lib/posthog-core/src/types.d.ts +2 -0
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,3 +1,9 @@
|
|
|
1
|
+
# 3.0.0-beta.2 - 2024-03-12
|
|
2
|
+
|
|
3
|
+
- `flushAsync` and `shutdownAsync` are removed with `flush` and `shutdown` now being the async methods.
|
|
4
|
+
- Fixed an issue where `shutdownAsync` would potentially exit early if a flush was already in progress
|
|
5
|
+
- Flushes will now try to flush up to `maxBatchSize` (default 100) in one go
|
|
6
|
+
|
|
1
7
|
# 3.0.0-beta.1 - 2024-03-04
|
|
2
8
|
|
|
3
9
|
- Removes the `enable` option. You can now specify `defaultOptIn: false` to start the SDK opted out of tracking
|
package/lib/index.cjs.js
CHANGED
|
@@ -946,6 +946,7 @@ function isPostHogFetchError(err) {
|
|
|
946
946
|
}
|
|
947
947
|
class PostHogCoreStateless {
|
|
948
948
|
constructor(apiKey, options) {
|
|
949
|
+
this.flushPromise = null;
|
|
949
950
|
this.disableGeoip = true;
|
|
950
951
|
this.disabled = false;
|
|
951
952
|
this.defaultOptIn = true;
|
|
@@ -957,6 +958,7 @@ class PostHogCoreStateless {
|
|
|
957
958
|
this.apiKey = apiKey;
|
|
958
959
|
this.host = removeTrailingSlash(options?.host || 'https://app.posthog.com');
|
|
959
960
|
this.flushAt = options?.flushAt ? Math.max(options?.flushAt, 1) : 20;
|
|
961
|
+
this.maxBatchSize = Math.max(this.flushAt, options?.maxBatchSize ?? 100);
|
|
960
962
|
this.flushInterval = options?.flushInterval ?? 10000;
|
|
961
963
|
this.captureMode = options?.captureMode || 'form';
|
|
962
964
|
// If enable is explicitly set to false we override the optout
|
|
@@ -1035,9 +1037,12 @@ class PostHogCoreStateless {
|
|
|
1035
1037
|
addPendingPromise(promise) {
|
|
1036
1038
|
const promiseUUID = uuidv7();
|
|
1037
1039
|
this.pendingPromises[promiseUUID] = promise;
|
|
1038
|
-
promise
|
|
1040
|
+
promise
|
|
1041
|
+
.catch(() => { })
|
|
1042
|
+
.finally(() => {
|
|
1039
1043
|
delete this.pendingPromises[promiseUUID];
|
|
1040
1044
|
});
|
|
1045
|
+
return promise;
|
|
1041
1046
|
}
|
|
1042
1047
|
/***
|
|
1043
1048
|
*** TRACKING
|
|
@@ -1217,75 +1222,90 @@ class PostHogCoreStateless {
|
|
|
1217
1222
|
this._events.emit(type, message);
|
|
1218
1223
|
// Flush queued events if we meet the flushAt length
|
|
1219
1224
|
if (queue.length >= this.flushAt) {
|
|
1220
|
-
this.
|
|
1225
|
+
this.flushBackground();
|
|
1221
1226
|
}
|
|
1222
1227
|
if (this.flushInterval && !this._flushTimer) {
|
|
1223
|
-
this._flushTimer = safeSetTimeout(() => this.
|
|
1228
|
+
this._flushTimer = safeSetTimeout(() => this.flushBackground(), this.flushInterval);
|
|
1224
1229
|
}
|
|
1225
1230
|
});
|
|
1226
1231
|
}
|
|
1227
|
-
|
|
1228
|
-
|
|
1229
|
-
|
|
1230
|
-
this.
|
|
1231
|
-
|
|
1232
|
+
clearFlushTimer() {
|
|
1233
|
+
if (this._flushTimer) {
|
|
1234
|
+
clearTimeout(this._flushTimer);
|
|
1235
|
+
this._flushTimer = undefined;
|
|
1236
|
+
}
|
|
1237
|
+
}
|
|
1238
|
+
/**
|
|
1239
|
+
* Helper for flushing the queue in the background
|
|
1240
|
+
* Avoids unnecessary promise errors
|
|
1241
|
+
*/
|
|
1242
|
+
flushBackground() {
|
|
1243
|
+
void this.flush().catch(() => { });
|
|
1244
|
+
}
|
|
1245
|
+
async flush() {
|
|
1246
|
+
if (!this.flushPromise) {
|
|
1247
|
+
this.flushPromise = this._flush().finally(() => {
|
|
1248
|
+
this.flushPromise = null;
|
|
1232
1249
|
});
|
|
1233
|
-
|
|
1250
|
+
this.addPendingPromise(this.flushPromise);
|
|
1251
|
+
}
|
|
1252
|
+
return this.flushPromise;
|
|
1234
1253
|
}
|
|
1235
|
-
|
|
1236
|
-
this.
|
|
1237
|
-
|
|
1238
|
-
|
|
1239
|
-
|
|
1240
|
-
|
|
1241
|
-
|
|
1242
|
-
|
|
1243
|
-
|
|
1254
|
+
async _flush() {
|
|
1255
|
+
this.clearFlushTimer();
|
|
1256
|
+
await this._initPromise;
|
|
1257
|
+
const queue = this.getPersistedProperty(PostHogPersistedProperty.Queue) || [];
|
|
1258
|
+
if (!queue.length) {
|
|
1259
|
+
return [];
|
|
1260
|
+
}
|
|
1261
|
+
const items = queue.slice(0, this.maxBatchSize);
|
|
1262
|
+
const messages = items.map((item) => item.message);
|
|
1263
|
+
const persistQueueChange = () => {
|
|
1264
|
+
const refreshedQueue = this.getPersistedProperty(PostHogPersistedProperty.Queue) || [];
|
|
1265
|
+
this.setPersistedProperty(PostHogPersistedProperty.Queue, refreshedQueue.slice(items.length));
|
|
1266
|
+
};
|
|
1267
|
+
const data = {
|
|
1268
|
+
api_key: this.apiKey,
|
|
1269
|
+
batch: messages,
|
|
1270
|
+
sent_at: currentISOTime(),
|
|
1271
|
+
};
|
|
1272
|
+
// Don't set the user agent if we're not on a browser. The latest spec allows
|
|
1273
|
+
// the User-Agent header (see https://fetch.spec.whatwg.org/#terminology-headers
|
|
1274
|
+
// and https://developer.mozilla.org/en-US/docs/Web/API/XMLHttpRequest/setRequestHeader),
|
|
1275
|
+
// but browsers such as Chrome and Safari have not caught up.
|
|
1276
|
+
this.getCustomUserAgent();
|
|
1277
|
+
const payload = JSON.stringify(data);
|
|
1278
|
+
const url = this.captureMode === 'form'
|
|
1279
|
+
? `${this.host}/e/?ip=1&_=${currentTimestamp()}&v=${this.getLibraryVersion()}`
|
|
1280
|
+
: `${this.host}/batch/`;
|
|
1281
|
+
const fetchOptions = this.captureMode === 'form'
|
|
1282
|
+
? {
|
|
1283
|
+
method: 'POST',
|
|
1284
|
+
mode: 'no-cors',
|
|
1285
|
+
credentials: 'omit',
|
|
1286
|
+
headers: { 'Content-Type': 'application/x-www-form-urlencoded' },
|
|
1287
|
+
body: `data=${encodeURIComponent(LZString.compressToBase64(payload))}&compression=lz64`,
|
|
1244
1288
|
}
|
|
1245
|
-
|
|
1246
|
-
|
|
1247
|
-
|
|
1248
|
-
|
|
1249
|
-
api_key: this.apiKey,
|
|
1250
|
-
batch: messages,
|
|
1251
|
-
sent_at: currentISOTime(),
|
|
1289
|
+
: {
|
|
1290
|
+
method: 'POST',
|
|
1291
|
+
headers: { 'Content-Type': 'application/json' },
|
|
1292
|
+
body: payload,
|
|
1252
1293
|
};
|
|
1253
|
-
|
|
1254
|
-
|
|
1255
|
-
|
|
1256
|
-
|
|
1257
|
-
|
|
1258
|
-
|
|
1259
|
-
|
|
1260
|
-
|
|
1261
|
-
|
|
1262
|
-
|
|
1263
|
-
|
|
1264
|
-
|
|
1265
|
-
|
|
1266
|
-
|
|
1267
|
-
|
|
1268
|
-
: `${this.host}/batch/`;
|
|
1269
|
-
const fetchOptions = this.captureMode === 'form'
|
|
1270
|
-
? {
|
|
1271
|
-
method: 'POST',
|
|
1272
|
-
mode: 'no-cors',
|
|
1273
|
-
credentials: 'omit',
|
|
1274
|
-
headers: { 'Content-Type': 'application/x-www-form-urlencoded' },
|
|
1275
|
-
body: `data=${encodeURIComponent(LZString.compressToBase64(payload))}&compression=lz64`,
|
|
1276
|
-
}
|
|
1277
|
-
: {
|
|
1278
|
-
method: 'POST',
|
|
1279
|
-
headers: { 'Content-Type': 'application/json' },
|
|
1280
|
-
body: payload,
|
|
1281
|
-
};
|
|
1282
|
-
const requestPromise = this.fetchWithRetry(url, fetchOptions);
|
|
1283
|
-
this.addPendingPromise(requestPromise
|
|
1284
|
-
.then(() => done())
|
|
1285
|
-
.catch((err) => {
|
|
1286
|
-
done(err);
|
|
1287
|
-
}));
|
|
1288
|
-
});
|
|
1294
|
+
try {
|
|
1295
|
+
await this.fetchWithRetry(url, fetchOptions);
|
|
1296
|
+
}
|
|
1297
|
+
catch (err) {
|
|
1298
|
+
// depending on the error type, eg a malformed JSON or broken queue, it'll always return an error
|
|
1299
|
+
// 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
|
|
1300
|
+
if (!(err instanceof PostHogFetchNetworkError)) {
|
|
1301
|
+
persistQueueChange();
|
|
1302
|
+
}
|
|
1303
|
+
this._events.emit('error', err);
|
|
1304
|
+
throw err;
|
|
1305
|
+
}
|
|
1306
|
+
persistQueueChange();
|
|
1307
|
+
this._events.emit('flush', messages);
|
|
1308
|
+
return messages;
|
|
1289
1309
|
}
|
|
1290
1310
|
async fetchWithRetry(url, options, retryOptions, requestTimeout) {
|
|
1291
1311
|
var _a;
|
|
@@ -1316,15 +1336,12 @@ class PostHogCoreStateless {
|
|
|
1316
1336
|
return res;
|
|
1317
1337
|
}, { ...this._retryOptions, ...retryOptions });
|
|
1318
1338
|
}
|
|
1319
|
-
async
|
|
1339
|
+
async shutdown(shutdownTimeoutMs = 30000) {
|
|
1320
1340
|
await this._initPromise;
|
|
1321
|
-
|
|
1341
|
+
this.clearFlushTimer();
|
|
1322
1342
|
try {
|
|
1323
|
-
await Promise.all(Object.values(this.pendingPromises)
|
|
1324
|
-
|
|
1325
|
-
})));
|
|
1326
|
-
const timeout = shutdownTimeoutMs ?? 30000;
|
|
1327
|
-
const startTimeWithDelay = Date.now() + timeout;
|
|
1343
|
+
await Promise.all(Object.values(this.pendingPromises));
|
|
1344
|
+
const startTimeWithDelay = Date.now() + shutdownTimeoutMs;
|
|
1328
1345
|
while (true) {
|
|
1329
1346
|
const queue = this.getPersistedProperty(PostHogPersistedProperty.Queue) || [];
|
|
1330
1347
|
if (queue.length === 0) {
|
|
@@ -1333,7 +1350,7 @@ class PostHogCoreStateless {
|
|
|
1333
1350
|
// flush again to make sure we send all events, some of which might've been added
|
|
1334
1351
|
// while we were waiting for the pending promises to resolve
|
|
1335
1352
|
// For example, see sendFeatureFlags in posthog-node/src/posthog-node.ts::capture
|
|
1336
|
-
await this.
|
|
1353
|
+
await this.flush();
|
|
1337
1354
|
// If we've been waiting for more than the shutdownTimeoutMs, stop it
|
|
1338
1355
|
const now = Date.now();
|
|
1339
1356
|
if (startTimeWithDelay < now) {
|
|
@@ -1348,9 +1365,6 @@ class PostHogCoreStateless {
|
|
|
1348
1365
|
console.error('Error while shutting down PostHog', e);
|
|
1349
1366
|
}
|
|
1350
1367
|
}
|
|
1351
|
-
shutdown(shutdownTimeoutMs) {
|
|
1352
|
-
void this.shutdownAsync(shutdownTimeoutMs);
|
|
1353
|
-
}
|
|
1354
1368
|
}
|
|
1355
1369
|
class PostHogCore extends PostHogCoreStateless {
|
|
1356
1370
|
constructor(apiKey, options) {
|
|
@@ -1816,7 +1830,7 @@ class PostHogCore extends PostHogCoreStateless {
|
|
|
1816
1830
|
}
|
|
1817
1831
|
}
|
|
1818
1832
|
|
|
1819
|
-
var version = "3.0.0-beta.
|
|
1833
|
+
var version = "3.0.0-beta.2";
|
|
1820
1834
|
|
|
1821
1835
|
function getContext(window) {
|
|
1822
1836
|
let context = {};
|