@rpcbase/server 0.547.0 → 0.548.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/dist/index.js +523 -266
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -6,7 +6,7 @@ import { MongoClient } from "mongodb";
|
|
|
6
6
|
import env from "@rpcbase/env";
|
|
7
7
|
import { initApiClient, STATIC_RPCBASE_RTS_HYDRATION_DATA_KEY, RtsSsrRuntimeProvider, SsrErrorFallback, SSR_ERROR_STATE_GLOBAL_KEY, serializeSsrErrorState } from "@rpcbase/client";
|
|
8
8
|
import { getMongoUrl } from "@rpcbase/db/mongo";
|
|
9
|
-
import { posix, dirname, sep } from "path";
|
|
9
|
+
import { posix, dirname, sep, isAbsolute, relative } from "path";
|
|
10
10
|
import fs, { createReadStream, readFileSync } from "node:fs";
|
|
11
11
|
import { createInterface } from "node:readline";
|
|
12
12
|
import { AsyncLocalStorage } from "node:async_hooks";
|
|
@@ -291,194 +291,23 @@ const parsePayload = (response) => {
|
|
|
291
291
|
return response;
|
|
292
292
|
}
|
|
293
293
|
};
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
constructor(bytes) {
|
|
297
|
-
this.bytes = bytes;
|
|
298
|
-
}
|
|
299
|
-
static ofInner(bytes) {
|
|
300
|
-
if (16 === bytes.length) return new UUID(bytes);
|
|
301
|
-
throw new TypeError("not 128-bit length");
|
|
302
|
-
}
|
|
303
|
-
static fromFieldsV7(unixTsMs, randA, randBHi, randBLo) {
|
|
304
|
-
if (!Number.isInteger(unixTsMs) || !Number.isInteger(randA) || !Number.isInteger(randBHi) || !Number.isInteger(randBLo) || unixTsMs < 0 || randA < 0 || randBHi < 0 || randBLo < 0 || unixTsMs > 281474976710655 || randA > 4095 || randBHi > 1073741823 || randBLo > 4294967295) throw new RangeError("invalid field value");
|
|
305
|
-
const bytes = new Uint8Array(16);
|
|
306
|
-
bytes[0] = unixTsMs / 2 ** 40;
|
|
307
|
-
bytes[1] = unixTsMs / 2 ** 32;
|
|
308
|
-
bytes[2] = unixTsMs / 2 ** 24;
|
|
309
|
-
bytes[3] = unixTsMs / 2 ** 16;
|
|
310
|
-
bytes[4] = unixTsMs / 256;
|
|
311
|
-
bytes[5] = unixTsMs;
|
|
312
|
-
bytes[6] = 112 | randA >>> 8;
|
|
313
|
-
bytes[7] = randA;
|
|
314
|
-
bytes[8] = 128 | randBHi >>> 24;
|
|
315
|
-
bytes[9] = randBHi >>> 16;
|
|
316
|
-
bytes[10] = randBHi >>> 8;
|
|
317
|
-
bytes[11] = randBHi;
|
|
318
|
-
bytes[12] = randBLo >>> 24;
|
|
319
|
-
bytes[13] = randBLo >>> 16;
|
|
320
|
-
bytes[14] = randBLo >>> 8;
|
|
321
|
-
bytes[15] = randBLo;
|
|
322
|
-
return new UUID(bytes);
|
|
323
|
-
}
|
|
324
|
-
static parse(uuid) {
|
|
325
|
-
let hex;
|
|
326
|
-
switch (uuid.length) {
|
|
327
|
-
case 32:
|
|
328
|
-
hex = /^[0-9a-f]{32}$/i.exec(uuid)?.[0];
|
|
329
|
-
break;
|
|
330
|
-
case 36:
|
|
331
|
-
hex = /^([0-9a-f]{8})-([0-9a-f]{4})-([0-9a-f]{4})-([0-9a-f]{4})-([0-9a-f]{12})$/i.exec(uuid)?.slice(1, 6).join("");
|
|
332
|
-
break;
|
|
333
|
-
case 38:
|
|
334
|
-
hex = /^\{([0-9a-f]{8})-([0-9a-f]{4})-([0-9a-f]{4})-([0-9a-f]{4})-([0-9a-f]{12})\}$/i.exec(uuid)?.slice(1, 6).join("");
|
|
335
|
-
break;
|
|
336
|
-
case 45:
|
|
337
|
-
hex = /^urn:uuid:([0-9a-f]{8})-([0-9a-f]{4})-([0-9a-f]{4})-([0-9a-f]{4})-([0-9a-f]{12})$/i.exec(uuid)?.slice(1, 6).join("");
|
|
338
|
-
break;
|
|
339
|
-
}
|
|
340
|
-
if (hex) {
|
|
341
|
-
const inner = new Uint8Array(16);
|
|
342
|
-
for (let i = 0; i < 16; i += 4) {
|
|
343
|
-
const n = parseInt(hex.substring(2 * i, 2 * i + 8), 16);
|
|
344
|
-
inner[i + 0] = n >>> 24;
|
|
345
|
-
inner[i + 1] = n >>> 16;
|
|
346
|
-
inner[i + 2] = n >>> 8;
|
|
347
|
-
inner[i + 3] = n;
|
|
348
|
-
}
|
|
349
|
-
return new UUID(inner);
|
|
350
|
-
}
|
|
351
|
-
throw new SyntaxError("could not parse UUID string");
|
|
352
|
-
}
|
|
353
|
-
toString() {
|
|
354
|
-
let text = "";
|
|
355
|
-
for (let i = 0; i < this.bytes.length; i++) {
|
|
356
|
-
text += DIGITS.charAt(this.bytes[i] >>> 4);
|
|
357
|
-
text += DIGITS.charAt(15 & this.bytes[i]);
|
|
358
|
-
if (3 === i || 5 === i || 7 === i || 9 === i) text += "-";
|
|
359
|
-
}
|
|
360
|
-
return text;
|
|
361
|
-
}
|
|
362
|
-
toHex() {
|
|
363
|
-
let text = "";
|
|
364
|
-
for (let i = 0; i < this.bytes.length; i++) {
|
|
365
|
-
text += DIGITS.charAt(this.bytes[i] >>> 4);
|
|
366
|
-
text += DIGITS.charAt(15 & this.bytes[i]);
|
|
367
|
-
}
|
|
368
|
-
return text;
|
|
369
|
-
}
|
|
370
|
-
toJSON() {
|
|
371
|
-
return this.toString();
|
|
372
|
-
}
|
|
373
|
-
getVariant() {
|
|
374
|
-
const n = this.bytes[8] >>> 4;
|
|
375
|
-
if (n < 0) throw new Error("unreachable");
|
|
376
|
-
if (n <= 7) return this.bytes.every((e) => 0 === e) ? "NIL" : "VAR_0";
|
|
377
|
-
if (n <= 11) return "VAR_10";
|
|
378
|
-
if (n <= 13) return "VAR_110";
|
|
379
|
-
if (n <= 15) return this.bytes.every((e) => 255 === e) ? "MAX" : "VAR_RESERVED";
|
|
380
|
-
else throw new Error("unreachable");
|
|
381
|
-
}
|
|
382
|
-
getVersion() {
|
|
383
|
-
return "VAR_10" === this.getVariant() ? this.bytes[6] >>> 4 : void 0;
|
|
384
|
-
}
|
|
385
|
-
clone() {
|
|
386
|
-
return new UUID(this.bytes.slice(0));
|
|
387
|
-
}
|
|
388
|
-
equals(other) {
|
|
389
|
-
return 0 === this.compareTo(other);
|
|
390
|
-
}
|
|
391
|
-
compareTo(other) {
|
|
392
|
-
for (let i = 0; i < 16; i++) {
|
|
393
|
-
const diff = this.bytes[i] - other.bytes[i];
|
|
394
|
-
if (0 !== diff) return Math.sign(diff);
|
|
395
|
-
}
|
|
396
|
-
return 0;
|
|
397
|
-
}
|
|
294
|
+
function isGzipSupported() {
|
|
295
|
+
return "CompressionStream" in globalThis;
|
|
398
296
|
}
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
generateOrResetCore(unixTsMs, rollbackAllowance) {
|
|
412
|
-
let value = this.generateOrAbortCore(unixTsMs, rollbackAllowance);
|
|
413
|
-
if (void 0 === value) {
|
|
414
|
-
this.timestamp = 0;
|
|
415
|
-
value = this.generateOrAbortCore(unixTsMs, rollbackAllowance);
|
|
416
|
-
}
|
|
417
|
-
return value;
|
|
418
|
-
}
|
|
419
|
-
generateOrAbortCore(unixTsMs, rollbackAllowance) {
|
|
420
|
-
const MAX_COUNTER = 4398046511103;
|
|
421
|
-
if (!Number.isInteger(unixTsMs) || unixTsMs < 1 || unixTsMs > 281474976710655) throw new RangeError("`unixTsMs` must be a 48-bit positive integer");
|
|
422
|
-
if (rollbackAllowance < 0 || rollbackAllowance > 281474976710655) throw new RangeError("`rollbackAllowance` out of reasonable range");
|
|
423
|
-
if (unixTsMs > this.timestamp) {
|
|
424
|
-
this.timestamp = unixTsMs;
|
|
425
|
-
this.resetCounter();
|
|
426
|
-
} else {
|
|
427
|
-
if (!(unixTsMs + rollbackAllowance >= this.timestamp)) return;
|
|
428
|
-
this.counter++;
|
|
429
|
-
if (this.counter > MAX_COUNTER) {
|
|
430
|
-
this.timestamp++;
|
|
431
|
-
this.resetCounter();
|
|
432
|
-
}
|
|
433
|
-
}
|
|
434
|
-
return UUID.fromFieldsV7(this.timestamp, Math.trunc(this.counter / 2 ** 30), this.counter & 2 ** 30 - 1, this.random.nextUint32());
|
|
435
|
-
}
|
|
436
|
-
resetCounter() {
|
|
437
|
-
this.counter = 1024 * this.random.nextUint32() + (1023 & this.random.nextUint32());
|
|
438
|
-
}
|
|
439
|
-
generateV4() {
|
|
440
|
-
const bytes = new Uint8Array(Uint32Array.of(this.random.nextUint32(), this.random.nextUint32(), this.random.nextUint32(), this.random.nextUint32()).buffer);
|
|
441
|
-
bytes[6] = 64 | bytes[6] >>> 4;
|
|
442
|
-
bytes[8] = 128 | bytes[8] >>> 2;
|
|
443
|
-
return UUID.ofInner(bytes);
|
|
297
|
+
async function gzipCompress(input, isDebug = true, options) {
|
|
298
|
+
try {
|
|
299
|
+
const dataStream = new Blob([
|
|
300
|
+
input
|
|
301
|
+
], {
|
|
302
|
+
type: "text/plain"
|
|
303
|
+
}).stream();
|
|
304
|
+
const compressedStream = dataStream.pipeThrough(new CompressionStream("gzip"));
|
|
305
|
+
return await new Response(compressedStream).blob();
|
|
306
|
+
} catch (error) {
|
|
307
|
+
if (isDebug) console.error("Failed to gzip compress data", error);
|
|
308
|
+
return null;
|
|
444
309
|
}
|
|
445
310
|
}
|
|
446
|
-
const getDefaultRandom = () => ({
|
|
447
|
-
nextUint32: () => 65536 * Math.trunc(65536 * Math.random()) + Math.trunc(65536 * Math.random())
|
|
448
|
-
});
|
|
449
|
-
let defaultGenerator;
|
|
450
|
-
const uuidv7 = () => uuidv7obj().toString();
|
|
451
|
-
const uuidv7obj = () => (defaultGenerator || (defaultGenerator = new V7Generator())).generate();
|
|
452
|
-
var types_PostHogPersistedProperty = /* @__PURE__ */ (function(PostHogPersistedProperty) {
|
|
453
|
-
PostHogPersistedProperty["AnonymousId"] = "anonymous_id";
|
|
454
|
-
PostHogPersistedProperty["DistinctId"] = "distinct_id";
|
|
455
|
-
PostHogPersistedProperty["Props"] = "props";
|
|
456
|
-
PostHogPersistedProperty["EnablePersonProcessing"] = "enable_person_processing";
|
|
457
|
-
PostHogPersistedProperty["PersonMode"] = "person_mode";
|
|
458
|
-
PostHogPersistedProperty["FeatureFlagDetails"] = "feature_flag_details";
|
|
459
|
-
PostHogPersistedProperty["FeatureFlags"] = "feature_flags";
|
|
460
|
-
PostHogPersistedProperty["FeatureFlagPayloads"] = "feature_flag_payloads";
|
|
461
|
-
PostHogPersistedProperty["BootstrapFeatureFlagDetails"] = "bootstrap_feature_flag_details";
|
|
462
|
-
PostHogPersistedProperty["BootstrapFeatureFlags"] = "bootstrap_feature_flags";
|
|
463
|
-
PostHogPersistedProperty["BootstrapFeatureFlagPayloads"] = "bootstrap_feature_flag_payloads";
|
|
464
|
-
PostHogPersistedProperty["OverrideFeatureFlags"] = "override_feature_flags";
|
|
465
|
-
PostHogPersistedProperty["Queue"] = "queue";
|
|
466
|
-
PostHogPersistedProperty["OptedOut"] = "opted_out";
|
|
467
|
-
PostHogPersistedProperty["SessionId"] = "session_id";
|
|
468
|
-
PostHogPersistedProperty["SessionStartTimestamp"] = "session_start_timestamp";
|
|
469
|
-
PostHogPersistedProperty["SessionLastTimestamp"] = "session_timestamp";
|
|
470
|
-
PostHogPersistedProperty["PersonProperties"] = "person_properties";
|
|
471
|
-
PostHogPersistedProperty["GroupProperties"] = "group_properties";
|
|
472
|
-
PostHogPersistedProperty["InstalledAppBuild"] = "installed_app_build";
|
|
473
|
-
PostHogPersistedProperty["InstalledAppVersion"] = "installed_app_version";
|
|
474
|
-
PostHogPersistedProperty["SessionReplay"] = "session_replay";
|
|
475
|
-
PostHogPersistedProperty["SurveyLastSeenDate"] = "survey_last_seen_date";
|
|
476
|
-
PostHogPersistedProperty["SurveysSeen"] = "surveys_seen";
|
|
477
|
-
PostHogPersistedProperty["Surveys"] = "surveys";
|
|
478
|
-
PostHogPersistedProperty["RemoteConfig"] = "remote_config";
|
|
479
|
-
PostHogPersistedProperty["FlagsEndpointWasHit"] = "flags_endpoint_was_hit";
|
|
480
|
-
return PostHogPersistedProperty;
|
|
481
|
-
})({});
|
|
482
311
|
const DEFAULT_BLOCKED_UA_STRS = [
|
|
483
312
|
"amazonbot",
|
|
484
313
|
"amazonproductbot",
|
|
@@ -566,6 +395,37 @@ const isBlockedUA = function(ua, customBlockedUserAgents = []) {
|
|
|
566
395
|
return -1 !== uaLower.indexOf(blockedUaLower);
|
|
567
396
|
});
|
|
568
397
|
};
|
|
398
|
+
var types_PostHogPersistedProperty = /* @__PURE__ */ (function(PostHogPersistedProperty) {
|
|
399
|
+
PostHogPersistedProperty["AnonymousId"] = "anonymous_id";
|
|
400
|
+
PostHogPersistedProperty["DistinctId"] = "distinct_id";
|
|
401
|
+
PostHogPersistedProperty["Props"] = "props";
|
|
402
|
+
PostHogPersistedProperty["EnablePersonProcessing"] = "enable_person_processing";
|
|
403
|
+
PostHogPersistedProperty["PersonMode"] = "person_mode";
|
|
404
|
+
PostHogPersistedProperty["FeatureFlagDetails"] = "feature_flag_details";
|
|
405
|
+
PostHogPersistedProperty["FeatureFlags"] = "feature_flags";
|
|
406
|
+
PostHogPersistedProperty["FeatureFlagPayloads"] = "feature_flag_payloads";
|
|
407
|
+
PostHogPersistedProperty["BootstrapFeatureFlagDetails"] = "bootstrap_feature_flag_details";
|
|
408
|
+
PostHogPersistedProperty["BootstrapFeatureFlags"] = "bootstrap_feature_flags";
|
|
409
|
+
PostHogPersistedProperty["BootstrapFeatureFlagPayloads"] = "bootstrap_feature_flag_payloads";
|
|
410
|
+
PostHogPersistedProperty["OverrideFeatureFlags"] = "override_feature_flags";
|
|
411
|
+
PostHogPersistedProperty["Queue"] = "queue";
|
|
412
|
+
PostHogPersistedProperty["OptedOut"] = "opted_out";
|
|
413
|
+
PostHogPersistedProperty["SessionId"] = "session_id";
|
|
414
|
+
PostHogPersistedProperty["SessionStartTimestamp"] = "session_start_timestamp";
|
|
415
|
+
PostHogPersistedProperty["SessionLastTimestamp"] = "session_timestamp";
|
|
416
|
+
PostHogPersistedProperty["PersonProperties"] = "person_properties";
|
|
417
|
+
PostHogPersistedProperty["GroupProperties"] = "group_properties";
|
|
418
|
+
PostHogPersistedProperty["InstalledAppBuild"] = "installed_app_build";
|
|
419
|
+
PostHogPersistedProperty["InstalledAppVersion"] = "installed_app_version";
|
|
420
|
+
PostHogPersistedProperty["SessionReplay"] = "session_replay";
|
|
421
|
+
PostHogPersistedProperty["SurveyLastSeenDate"] = "survey_last_seen_date";
|
|
422
|
+
PostHogPersistedProperty["SurveysSeen"] = "surveys_seen";
|
|
423
|
+
PostHogPersistedProperty["Surveys"] = "surveys";
|
|
424
|
+
PostHogPersistedProperty["RemoteConfig"] = "remote_config";
|
|
425
|
+
PostHogPersistedProperty["FlagsEndpointWasHit"] = "flags_endpoint_was_hit";
|
|
426
|
+
PostHogPersistedProperty["DeviceId"] = "device_id";
|
|
427
|
+
return PostHogPersistedProperty;
|
|
428
|
+
})({});
|
|
569
429
|
const nativeIsArray = Array.isArray;
|
|
570
430
|
const ObjProto = Object.prototype;
|
|
571
431
|
const type_utils_toString = ObjProto.toString;
|
|
@@ -573,7 +433,6 @@ const isArray = nativeIsArray || function(obj) {
|
|
|
573
433
|
return "[object Array]" === type_utils_toString.call(obj);
|
|
574
434
|
};
|
|
575
435
|
const isObject = (x) => x === Object(x) && !isArray(x);
|
|
576
|
-
const isUndefined = (x) => void 0 === x;
|
|
577
436
|
const isString = (x) => "[object String]" == type_utils_toString.call(x);
|
|
578
437
|
const isEmptyString = (x) => isString(x) && 0 === x.trim().length;
|
|
579
438
|
const isNumber = (x) => "[object Number]" == type_utils_toString.call(x) && x === x;
|
|
@@ -585,7 +444,7 @@ function isBuiltin(candidate, className) {
|
|
|
585
444
|
return Object.prototype.toString.call(candidate) === `[object ${className}]`;
|
|
586
445
|
}
|
|
587
446
|
function isEvent(candidate) {
|
|
588
|
-
return
|
|
447
|
+
return "undefined" != typeof Event && isInstanceOf(candidate, Event);
|
|
589
448
|
}
|
|
590
449
|
function isPlainObject(candidate) {
|
|
591
450
|
return isBuiltin(candidate, "Object");
|
|
@@ -652,6 +511,164 @@ class BucketedRateLimiter {
|
|
|
652
511
|
this._buckets = {};
|
|
653
512
|
}
|
|
654
513
|
}
|
|
514
|
+
const DIGITS = "0123456789abcdef";
|
|
515
|
+
class UUID {
|
|
516
|
+
constructor(bytes) {
|
|
517
|
+
this.bytes = bytes;
|
|
518
|
+
}
|
|
519
|
+
static ofInner(bytes) {
|
|
520
|
+
if (16 === bytes.length) return new UUID(bytes);
|
|
521
|
+
throw new TypeError("not 128-bit length");
|
|
522
|
+
}
|
|
523
|
+
static fromFieldsV7(unixTsMs, randA, randBHi, randBLo) {
|
|
524
|
+
if (!Number.isInteger(unixTsMs) || !Number.isInteger(randA) || !Number.isInteger(randBHi) || !Number.isInteger(randBLo) || unixTsMs < 0 || randA < 0 || randBHi < 0 || randBLo < 0 || unixTsMs > 281474976710655 || randA > 4095 || randBHi > 1073741823 || randBLo > 4294967295) throw new RangeError("invalid field value");
|
|
525
|
+
const bytes = new Uint8Array(16);
|
|
526
|
+
bytes[0] = unixTsMs / 2 ** 40;
|
|
527
|
+
bytes[1] = unixTsMs / 2 ** 32;
|
|
528
|
+
bytes[2] = unixTsMs / 2 ** 24;
|
|
529
|
+
bytes[3] = unixTsMs / 2 ** 16;
|
|
530
|
+
bytes[4] = unixTsMs / 256;
|
|
531
|
+
bytes[5] = unixTsMs;
|
|
532
|
+
bytes[6] = 112 | randA >>> 8;
|
|
533
|
+
bytes[7] = randA;
|
|
534
|
+
bytes[8] = 128 | randBHi >>> 24;
|
|
535
|
+
bytes[9] = randBHi >>> 16;
|
|
536
|
+
bytes[10] = randBHi >>> 8;
|
|
537
|
+
bytes[11] = randBHi;
|
|
538
|
+
bytes[12] = randBLo >>> 24;
|
|
539
|
+
bytes[13] = randBLo >>> 16;
|
|
540
|
+
bytes[14] = randBLo >>> 8;
|
|
541
|
+
bytes[15] = randBLo;
|
|
542
|
+
return new UUID(bytes);
|
|
543
|
+
}
|
|
544
|
+
static parse(uuid) {
|
|
545
|
+
let hex;
|
|
546
|
+
switch (uuid.length) {
|
|
547
|
+
case 32:
|
|
548
|
+
hex = /^[0-9a-f]{32}$/i.exec(uuid)?.[0];
|
|
549
|
+
break;
|
|
550
|
+
case 36:
|
|
551
|
+
hex = /^([0-9a-f]{8})-([0-9a-f]{4})-([0-9a-f]{4})-([0-9a-f]{4})-([0-9a-f]{12})$/i.exec(uuid)?.slice(1, 6).join("");
|
|
552
|
+
break;
|
|
553
|
+
case 38:
|
|
554
|
+
hex = /^\{([0-9a-f]{8})-([0-9a-f]{4})-([0-9a-f]{4})-([0-9a-f]{4})-([0-9a-f]{12})\}$/i.exec(uuid)?.slice(1, 6).join("");
|
|
555
|
+
break;
|
|
556
|
+
case 45:
|
|
557
|
+
hex = /^urn:uuid:([0-9a-f]{8})-([0-9a-f]{4})-([0-9a-f]{4})-([0-9a-f]{4})-([0-9a-f]{12})$/i.exec(uuid)?.slice(1, 6).join("");
|
|
558
|
+
break;
|
|
559
|
+
}
|
|
560
|
+
if (hex) {
|
|
561
|
+
const inner = new Uint8Array(16);
|
|
562
|
+
for (let i = 0; i < 16; i += 4) {
|
|
563
|
+
const n = parseInt(hex.substring(2 * i, 2 * i + 8), 16);
|
|
564
|
+
inner[i + 0] = n >>> 24;
|
|
565
|
+
inner[i + 1] = n >>> 16;
|
|
566
|
+
inner[i + 2] = n >>> 8;
|
|
567
|
+
inner[i + 3] = n;
|
|
568
|
+
}
|
|
569
|
+
return new UUID(inner);
|
|
570
|
+
}
|
|
571
|
+
throw new SyntaxError("could not parse UUID string");
|
|
572
|
+
}
|
|
573
|
+
toString() {
|
|
574
|
+
let text = "";
|
|
575
|
+
for (let i = 0; i < this.bytes.length; i++) {
|
|
576
|
+
text += DIGITS.charAt(this.bytes[i] >>> 4);
|
|
577
|
+
text += DIGITS.charAt(15 & this.bytes[i]);
|
|
578
|
+
if (3 === i || 5 === i || 7 === i || 9 === i) text += "-";
|
|
579
|
+
}
|
|
580
|
+
return text;
|
|
581
|
+
}
|
|
582
|
+
toHex() {
|
|
583
|
+
let text = "";
|
|
584
|
+
for (let i = 0; i < this.bytes.length; i++) {
|
|
585
|
+
text += DIGITS.charAt(this.bytes[i] >>> 4);
|
|
586
|
+
text += DIGITS.charAt(15 & this.bytes[i]);
|
|
587
|
+
}
|
|
588
|
+
return text;
|
|
589
|
+
}
|
|
590
|
+
toJSON() {
|
|
591
|
+
return this.toString();
|
|
592
|
+
}
|
|
593
|
+
getVariant() {
|
|
594
|
+
const n = this.bytes[8] >>> 4;
|
|
595
|
+
if (n < 0) throw new Error("unreachable");
|
|
596
|
+
if (n <= 7) return this.bytes.every((e) => 0 === e) ? "NIL" : "VAR_0";
|
|
597
|
+
if (n <= 11) return "VAR_10";
|
|
598
|
+
if (n <= 13) return "VAR_110";
|
|
599
|
+
if (n <= 15) return this.bytes.every((e) => 255 === e) ? "MAX" : "VAR_RESERVED";
|
|
600
|
+
else throw new Error("unreachable");
|
|
601
|
+
}
|
|
602
|
+
getVersion() {
|
|
603
|
+
return "VAR_10" === this.getVariant() ? this.bytes[6] >>> 4 : void 0;
|
|
604
|
+
}
|
|
605
|
+
clone() {
|
|
606
|
+
return new UUID(this.bytes.slice(0));
|
|
607
|
+
}
|
|
608
|
+
equals(other) {
|
|
609
|
+
return 0 === this.compareTo(other);
|
|
610
|
+
}
|
|
611
|
+
compareTo(other) {
|
|
612
|
+
for (let i = 0; i < 16; i++) {
|
|
613
|
+
const diff = this.bytes[i] - other.bytes[i];
|
|
614
|
+
if (0 !== diff) return Math.sign(diff);
|
|
615
|
+
}
|
|
616
|
+
return 0;
|
|
617
|
+
}
|
|
618
|
+
}
|
|
619
|
+
class V7Generator {
|
|
620
|
+
constructor(randomNumberGenerator) {
|
|
621
|
+
this.timestamp = 0;
|
|
622
|
+
this.counter = 0;
|
|
623
|
+
this.random = randomNumberGenerator ?? getDefaultRandom();
|
|
624
|
+
}
|
|
625
|
+
generate() {
|
|
626
|
+
return this.generateOrResetCore(Date.now(), 1e4);
|
|
627
|
+
}
|
|
628
|
+
generateOrAbort() {
|
|
629
|
+
return this.generateOrAbortCore(Date.now(), 1e4);
|
|
630
|
+
}
|
|
631
|
+
generateOrResetCore(unixTsMs, rollbackAllowance) {
|
|
632
|
+
let value = this.generateOrAbortCore(unixTsMs, rollbackAllowance);
|
|
633
|
+
if (void 0 === value) {
|
|
634
|
+
this.timestamp = 0;
|
|
635
|
+
value = this.generateOrAbortCore(unixTsMs, rollbackAllowance);
|
|
636
|
+
}
|
|
637
|
+
return value;
|
|
638
|
+
}
|
|
639
|
+
generateOrAbortCore(unixTsMs, rollbackAllowance) {
|
|
640
|
+
const MAX_COUNTER = 4398046511103;
|
|
641
|
+
if (!Number.isInteger(unixTsMs) || unixTsMs < 1 || unixTsMs > 281474976710655) throw new RangeError("`unixTsMs` must be a 48-bit positive integer");
|
|
642
|
+
if (rollbackAllowance < 0 || rollbackAllowance > 281474976710655) throw new RangeError("`rollbackAllowance` out of reasonable range");
|
|
643
|
+
if (unixTsMs > this.timestamp) {
|
|
644
|
+
this.timestamp = unixTsMs;
|
|
645
|
+
this.resetCounter();
|
|
646
|
+
} else {
|
|
647
|
+
if (!(unixTsMs + rollbackAllowance >= this.timestamp)) return;
|
|
648
|
+
this.counter++;
|
|
649
|
+
if (this.counter > MAX_COUNTER) {
|
|
650
|
+
this.timestamp++;
|
|
651
|
+
this.resetCounter();
|
|
652
|
+
}
|
|
653
|
+
}
|
|
654
|
+
return UUID.fromFieldsV7(this.timestamp, Math.trunc(this.counter / 2 ** 30), this.counter & 2 ** 30 - 1, this.random.nextUint32());
|
|
655
|
+
}
|
|
656
|
+
resetCounter() {
|
|
657
|
+
this.counter = 1024 * this.random.nextUint32() + (1023 & this.random.nextUint32());
|
|
658
|
+
}
|
|
659
|
+
generateV4() {
|
|
660
|
+
const bytes = new Uint8Array(Uint32Array.of(this.random.nextUint32(), this.random.nextUint32(), this.random.nextUint32(), this.random.nextUint32()).buffer);
|
|
661
|
+
bytes[6] = 64 | bytes[6] >>> 4;
|
|
662
|
+
bytes[8] = 128 | bytes[8] >>> 2;
|
|
663
|
+
return UUID.ofInner(bytes);
|
|
664
|
+
}
|
|
665
|
+
}
|
|
666
|
+
const getDefaultRandom = () => ({
|
|
667
|
+
nextUint32: () => 65536 * Math.trunc(65536 * Math.random()) + Math.trunc(65536 * Math.random())
|
|
668
|
+
});
|
|
669
|
+
let defaultGenerator;
|
|
670
|
+
const uuidv7 = () => uuidv7obj().toString();
|
|
671
|
+
const uuidv7obj = () => (defaultGenerator || (defaultGenerator = new V7Generator())).generate();
|
|
655
672
|
class PromiseQueue {
|
|
656
673
|
add(promise) {
|
|
657
674
|
const promiseUUID = uuidv7();
|
|
@@ -716,13 +733,6 @@ function createLogger(prefix, maybeCall = passThrough) {
|
|
|
716
733
|
return _createLogger(prefix, maybeCall, createConsole());
|
|
717
734
|
}
|
|
718
735
|
const STRING_FORMAT = "utf8";
|
|
719
|
-
function assert(truthyValue, message) {
|
|
720
|
-
if (!truthyValue || "string" != typeof truthyValue || isEmpty(truthyValue)) throw new Error(message);
|
|
721
|
-
}
|
|
722
|
-
function isEmpty(truthyValue) {
|
|
723
|
-
if (0 === truthyValue.trim().length) return true;
|
|
724
|
-
return false;
|
|
725
|
-
}
|
|
726
736
|
function removeTrailingSlash(url) {
|
|
727
737
|
return url?.replace(/\/+$/, "");
|
|
728
738
|
}
|
|
@@ -775,23 +785,6 @@ class SimpleEventEmitter {
|
|
|
775
785
|
for (const listener of this.events["*"] || []) listener(event, payload);
|
|
776
786
|
}
|
|
777
787
|
}
|
|
778
|
-
function isGzipSupported() {
|
|
779
|
-
return "CompressionStream" in globalThis;
|
|
780
|
-
}
|
|
781
|
-
async function gzipCompress(input, isDebug = true) {
|
|
782
|
-
try {
|
|
783
|
-
const dataStream = new Blob([
|
|
784
|
-
input
|
|
785
|
-
], {
|
|
786
|
-
type: "text/plain"
|
|
787
|
-
}).stream();
|
|
788
|
-
const compressedStream = dataStream.pipeThrough(new CompressionStream("gzip"));
|
|
789
|
-
return await new Response(compressedStream).blob();
|
|
790
|
-
} catch (error) {
|
|
791
|
-
if (isDebug) console.error("Failed to gzip compress data", error);
|
|
792
|
-
return null;
|
|
793
|
-
}
|
|
794
|
-
}
|
|
795
788
|
class PostHogFetchHttpError extends Error {
|
|
796
789
|
constructor(response, reqByteLength) {
|
|
797
790
|
super("HTTP error while fetching PostHog: status=" + response.status + ", reqByteLength=" + reqByteLength), this.response = response, this.reqByteLength = reqByteLength, this.name = "PostHogFetchHttpError";
|
|
@@ -837,9 +830,13 @@ class PostHogCoreStateless {
|
|
|
837
830
|
this.promiseQueue = new PromiseQueue();
|
|
838
831
|
this._events = new SimpleEventEmitter();
|
|
839
832
|
this._isInitialized = false;
|
|
840
|
-
|
|
841
|
-
|
|
842
|
-
|
|
833
|
+
const normalizedApiKey = "string" == typeof apiKey ? apiKey.trim() : "";
|
|
834
|
+
const normalizedHost = "string" == typeof options.host ? options.host.trim() : "";
|
|
835
|
+
const missingApiKey = !normalizedApiKey;
|
|
836
|
+
this._logger = createLogger("[PostHog]", this.logMsgIfDebug.bind(this));
|
|
837
|
+
if (missingApiKey) this._logger.error("You must pass your PostHog project's api key. The client will be disabled.");
|
|
838
|
+
this.apiKey = normalizedApiKey;
|
|
839
|
+
this.host = removeTrailingSlash(normalizedHost || "https://us.i.posthog.com");
|
|
843
840
|
this.flushAt = options.flushAt ? Math.max(options.flushAt, 1) : 20;
|
|
844
841
|
this.maxBatchSize = Math.max(this.flushAt, options.maxBatchSize ?? 100);
|
|
845
842
|
this.maxQueueSize = Math.max(this.flushAt, options.maxQueueSize ?? 1e3);
|
|
@@ -856,11 +853,10 @@ class PostHogCoreStateless {
|
|
|
856
853
|
this.featureFlagsRequestTimeoutMs = options.featureFlagsRequestTimeoutMs ?? 3e3;
|
|
857
854
|
this.remoteConfigRequestTimeoutMs = options.remoteConfigRequestTimeoutMs ?? 3e3;
|
|
858
855
|
this.disableGeoip = options.disableGeoip ?? true;
|
|
859
|
-
this.disabled = options.disabled ?? false;
|
|
856
|
+
this.disabled = (options.disabled ?? false) || missingApiKey;
|
|
860
857
|
this.historicalMigration = options?.historicalMigration ?? false;
|
|
861
858
|
this._initPromise = Promise.resolve();
|
|
862
859
|
this._isInitialized = true;
|
|
863
|
-
this._logger = createLogger("[PostHog]", this.logMsgIfDebug.bind(this));
|
|
864
860
|
this.evaluationContexts = options?.evaluationContexts ?? options?.evaluationEnvironments;
|
|
865
861
|
if (options?.evaluationEnvironments && !options?.evaluationContexts) this._logger.warn("evaluationEnvironments is deprecated. Use evaluationContexts instead. This property will be removed in a future version.");
|
|
866
862
|
this.disableCompression = !isGzipSupported() || (options?.disableCompression ?? false);
|
|
@@ -1025,7 +1021,7 @@ class PostHogCoreStateless {
|
|
|
1025
1021
|
this._events.emit("error", error);
|
|
1026
1022
|
});
|
|
1027
1023
|
}
|
|
1028
|
-
async getFlags(distinctId, groups = {}, personProperties = {}, groupProperties = {}, extraPayload = {}, fetchConfig =
|
|
1024
|
+
async getFlags(distinctId, groups = {}, personProperties = {}, groupProperties = {}, extraPayload = {}, fetchConfig = false) {
|
|
1029
1025
|
await this._initPromise;
|
|
1030
1026
|
const configParam = fetchConfig ? "&config=true" : "";
|
|
1031
1027
|
const url = `${this.host}/flags/?v=2${configParam}`;
|
|
@@ -1037,6 +1033,7 @@ class PostHogCoreStateless {
|
|
|
1037
1033
|
group_properties: groupProperties,
|
|
1038
1034
|
...extraPayload
|
|
1039
1035
|
};
|
|
1036
|
+
if (personProperties.$device_id) requestData.$device_id = personProperties.$device_id;
|
|
1040
1037
|
if (this.evaluationContexts && this.evaluationContexts.length > 0) requestData.evaluation_contexts = this.evaluationContexts;
|
|
1041
1038
|
const fetchOptions = {
|
|
1042
1039
|
method: "POST",
|
|
@@ -1384,11 +1381,6 @@ class PostHogCoreStateless {
|
|
|
1384
1381
|
this._events.emit("flush", sentMessages);
|
|
1385
1382
|
}
|
|
1386
1383
|
async fetchWithRetry(url, options, retryOptions, requestTimeout) {
|
|
1387
|
-
AbortSignal.timeout ??= function(ms) {
|
|
1388
|
-
const ctrl = new AbortController();
|
|
1389
|
-
setTimeout(() => ctrl.abort(), ms);
|
|
1390
|
-
return ctrl.signal;
|
|
1391
|
-
};
|
|
1392
1384
|
const body = options.body ? options.body : "";
|
|
1393
1385
|
let reqByteLength = -1;
|
|
1394
1386
|
try {
|
|
@@ -1401,14 +1393,19 @@ class PostHogCoreStateless {
|
|
|
1401
1393
|
}
|
|
1402
1394
|
}
|
|
1403
1395
|
return await retriable(async () => {
|
|
1396
|
+
const ctrl = new AbortController();
|
|
1397
|
+
const timeoutMs = requestTimeout ?? this.requestTimeout;
|
|
1398
|
+
const timer = safeSetTimeout(() => ctrl.abort(), timeoutMs);
|
|
1404
1399
|
let res = null;
|
|
1405
1400
|
try {
|
|
1406
1401
|
res = await this.fetch(url, {
|
|
1407
|
-
signal:
|
|
1402
|
+
signal: ctrl.signal,
|
|
1408
1403
|
...options
|
|
1409
1404
|
});
|
|
1410
1405
|
} catch (e) {
|
|
1411
1406
|
throw new PostHogFetchNetworkError(e);
|
|
1407
|
+
} finally {
|
|
1408
|
+
clearTimeout(timer);
|
|
1412
1409
|
}
|
|
1413
1410
|
const isNoCors = "no-cors" === options.mode;
|
|
1414
1411
|
if (!isNoCors && (res.status < 200 || res.status >= 400)) throw new PostHogFetchHttpError(res, reqByteLength);
|
|
@@ -1436,16 +1433,21 @@ class PostHogCoreStateless {
|
|
|
1436
1433
|
await logFlushError(e);
|
|
1437
1434
|
}
|
|
1438
1435
|
};
|
|
1439
|
-
|
|
1440
|
-
|
|
1441
|
-
|
|
1442
|
-
|
|
1443
|
-
|
|
1444
|
-
|
|
1445
|
-
|
|
1446
|
-
|
|
1447
|
-
|
|
1448
|
-
|
|
1436
|
+
let timeoutHandle;
|
|
1437
|
+
try {
|
|
1438
|
+
return await Promise.race([
|
|
1439
|
+
new Promise((_, reject) => {
|
|
1440
|
+
timeoutHandle = safeSetTimeout(() => {
|
|
1441
|
+
this._logger.error("Timed out while shutting down PostHog");
|
|
1442
|
+
hasTimedOut = true;
|
|
1443
|
+
reject("Timeout while shutting down PostHog. Some events may not have been sent.");
|
|
1444
|
+
}, shutdownTimeoutMs);
|
|
1445
|
+
}),
|
|
1446
|
+
doShutdown()
|
|
1447
|
+
]);
|
|
1448
|
+
} finally {
|
|
1449
|
+
clearTimeout(timeoutHandle);
|
|
1450
|
+
}
|
|
1449
1451
|
}
|
|
1450
1452
|
async shutdown(shutdownTimeoutMs = 3e4) {
|
|
1451
1453
|
if (this.shutdownPromise) this._logger.warn("shutdown() called while already shutting down. shutdown() is meant to be called once before process exit - use flush() for per-request cleanup");
|
|
@@ -2052,6 +2054,17 @@ function snipLine(line, colno) {
|
|
|
2052
2054
|
if (end < lineLength) newLine += "...";
|
|
2053
2055
|
return newLine;
|
|
2054
2056
|
}
|
|
2057
|
+
function createRelativePathModifier(basePath = process.cwd()) {
|
|
2058
|
+
const isWindows = "\\" === sep;
|
|
2059
|
+
const toUnix = (p) => isWindows ? p.replace(/\\/g, "/") : p;
|
|
2060
|
+
const normalizedBase = toUnix(basePath);
|
|
2061
|
+
return async (frames) => {
|
|
2062
|
+
for (const frame of frames) if (!(!frame.filename || frame.filename.startsWith("node:") || frame.filename.startsWith("data:"))) {
|
|
2063
|
+
if (isAbsolute(frame.filename)) frame.filename = toUnix(relative(normalizedBase, toUnix(frame.filename)));
|
|
2064
|
+
}
|
|
2065
|
+
return frames;
|
|
2066
|
+
};
|
|
2067
|
+
}
|
|
2055
2068
|
function makeUncaughtExceptionHandler(captureFn, onFatalFn) {
|
|
2056
2069
|
let calledFatalError = false;
|
|
2057
2070
|
return Object.assign((error) => {
|
|
@@ -2103,12 +2116,11 @@ class ErrorTracking {
|
|
|
2103
2116
|
const properties = {
|
|
2104
2117
|
...additionalProperties
|
|
2105
2118
|
};
|
|
2106
|
-
if (!distinctId) properties.$process_person_profile = false;
|
|
2107
2119
|
const exceptionProperties = this.errorPropertiesBuilder.buildFromUnknown(error, hint);
|
|
2108
2120
|
exceptionProperties.$exception_list = await this.errorPropertiesBuilder.modifyFrames(exceptionProperties.$exception_list);
|
|
2109
2121
|
return {
|
|
2110
2122
|
event: "$exception",
|
|
2111
|
-
distinctId
|
|
2123
|
+
distinctId,
|
|
2112
2124
|
properties: {
|
|
2113
2125
|
...exceptionProperties,
|
|
2114
2126
|
...properties
|
|
@@ -2148,7 +2160,7 @@ class ErrorTracking {
|
|
|
2148
2160
|
this._rateLimiter.stop();
|
|
2149
2161
|
}
|
|
2150
2162
|
}
|
|
2151
|
-
const version = "5.
|
|
2163
|
+
const version = "5.30.1";
|
|
2152
2164
|
const FeatureFlagError = {
|
|
2153
2165
|
ERRORS_WHILE_COMPUTING: "errors_while_computing_flags",
|
|
2154
2166
|
FLAG_MISSING: "flag_missing",
|
|
@@ -2477,6 +2489,9 @@ class FeatureFlagsPoller {
|
|
|
2477
2489
|
isLocalEvaluationReady() {
|
|
2478
2490
|
return (this.loadedSuccessfullyOnce ?? false) && (this.featureFlags?.length ?? 0) > 0;
|
|
2479
2491
|
}
|
|
2492
|
+
getFlagDefinitionsLoadedAt() {
|
|
2493
|
+
return this.flagDefinitionsLoadedAt;
|
|
2494
|
+
}
|
|
2480
2495
|
getPollingInterval() {
|
|
2481
2496
|
if (!this.shouldBeginExponentialBackoff) return this.pollingInterval;
|
|
2482
2497
|
return Math.min(SIXTY_SECONDS, this.pollingInterval * 2 ** this.backOffCount);
|
|
@@ -2544,6 +2559,7 @@ class FeatureFlagsPoller {
|
|
|
2544
2559
|
cohorts: responseJson.cohorts || {}
|
|
2545
2560
|
};
|
|
2546
2561
|
this.updateFlagState(flagData);
|
|
2562
|
+
this.flagDefinitionsLoadedAt = Date.now();
|
|
2547
2563
|
this.clearBackoff();
|
|
2548
2564
|
if (this.cacheProvider && shouldFetch) try {
|
|
2549
2565
|
await this.cacheProvider.onFlagDefinitionsReceived(flagData);
|
|
@@ -2574,7 +2590,7 @@ class FeatureFlagsPoller {
|
|
|
2574
2590
|
};
|
|
2575
2591
|
}
|
|
2576
2592
|
_requestFeatureFlagDefinitions() {
|
|
2577
|
-
const url = `${this.host}/
|
|
2593
|
+
const url = `${this.host}/flags/definitions?token=${this.projectApiKey}&send_cohorts`;
|
|
2578
2594
|
const options = this.getPersonalApiKeyRequestOptions("GET", this.flagsEtag);
|
|
2579
2595
|
let abortTimeout = null;
|
|
2580
2596
|
if (this.timeout && "number" == typeof this.timeout) {
|
|
@@ -2671,6 +2687,45 @@ function matchProperty(property, propertyValues, warnFunction) {
|
|
|
2671
2687
|
].includes(operator)) return overrideDate < parsedDate;
|
|
2672
2688
|
return overrideDate > parsedDate;
|
|
2673
2689
|
}
|
|
2690
|
+
case "semver_eq": {
|
|
2691
|
+
const cmp = compareSemverTuples(parseSemver(String(overrideValue)), parseSemver(String(value)));
|
|
2692
|
+
return 0 === cmp;
|
|
2693
|
+
}
|
|
2694
|
+
case "semver_neq": {
|
|
2695
|
+
const cmp = compareSemverTuples(parseSemver(String(overrideValue)), parseSemver(String(value)));
|
|
2696
|
+
return 0 !== cmp;
|
|
2697
|
+
}
|
|
2698
|
+
case "semver_gt": {
|
|
2699
|
+
const cmp = compareSemverTuples(parseSemver(String(overrideValue)), parseSemver(String(value)));
|
|
2700
|
+
return cmp > 0;
|
|
2701
|
+
}
|
|
2702
|
+
case "semver_gte": {
|
|
2703
|
+
const cmp = compareSemverTuples(parseSemver(String(overrideValue)), parseSemver(String(value)));
|
|
2704
|
+
return cmp >= 0;
|
|
2705
|
+
}
|
|
2706
|
+
case "semver_lt": {
|
|
2707
|
+
const cmp = compareSemverTuples(parseSemver(String(overrideValue)), parseSemver(String(value)));
|
|
2708
|
+
return cmp < 0;
|
|
2709
|
+
}
|
|
2710
|
+
case "semver_lte": {
|
|
2711
|
+
const cmp = compareSemverTuples(parseSemver(String(overrideValue)), parseSemver(String(value)));
|
|
2712
|
+
return cmp <= 0;
|
|
2713
|
+
}
|
|
2714
|
+
case "semver_tilde": {
|
|
2715
|
+
const overrideParsed = parseSemver(String(overrideValue));
|
|
2716
|
+
const { lower, upper } = computeTildeBounds(String(value));
|
|
2717
|
+
return compareSemverTuples(overrideParsed, lower) >= 0 && compareSemverTuples(overrideParsed, upper) < 0;
|
|
2718
|
+
}
|
|
2719
|
+
case "semver_caret": {
|
|
2720
|
+
const overrideParsed = parseSemver(String(overrideValue));
|
|
2721
|
+
const { lower, upper } = computeCaretBounds(String(value));
|
|
2722
|
+
return compareSemverTuples(overrideParsed, lower) >= 0 && compareSemverTuples(overrideParsed, upper) < 0;
|
|
2723
|
+
}
|
|
2724
|
+
case "semver_wildcard": {
|
|
2725
|
+
const overrideParsed = parseSemver(String(overrideValue));
|
|
2726
|
+
const { lower, upper } = computeWildcardBounds(String(value));
|
|
2727
|
+
return compareSemverTuples(overrideParsed, lower) >= 0 && compareSemverTuples(overrideParsed, upper) < 0;
|
|
2728
|
+
}
|
|
2674
2729
|
default:
|
|
2675
2730
|
throw new InconclusiveMatchError(`Unknown operator: ${operator}`);
|
|
2676
2731
|
}
|
|
@@ -2739,6 +2794,115 @@ function isValidRegex(regex) {
|
|
|
2739
2794
|
return false;
|
|
2740
2795
|
}
|
|
2741
2796
|
}
|
|
2797
|
+
function parseSemver(value) {
|
|
2798
|
+
const text = String(value).trim().replace(/^[vV]/, "");
|
|
2799
|
+
const baseVersion = text.split("-")[0].split("+")[0];
|
|
2800
|
+
if (!baseVersion || baseVersion.startsWith(".")) throw new InconclusiveMatchError(`Invalid semver: ${value}`);
|
|
2801
|
+
const parts = baseVersion.split(".");
|
|
2802
|
+
const parsePart = (part) => {
|
|
2803
|
+
if (void 0 === part || "" === part) return 0;
|
|
2804
|
+
if (!/^\d+$/.test(part)) throw new InconclusiveMatchError(`Invalid semver: ${value}`);
|
|
2805
|
+
return parseInt(part, 10);
|
|
2806
|
+
};
|
|
2807
|
+
const major = parsePart(parts[0]);
|
|
2808
|
+
const minor = parsePart(parts[1]);
|
|
2809
|
+
const patch = parsePart(parts[2]);
|
|
2810
|
+
return [
|
|
2811
|
+
major,
|
|
2812
|
+
minor,
|
|
2813
|
+
patch
|
|
2814
|
+
];
|
|
2815
|
+
}
|
|
2816
|
+
function compareSemverTuples(a, b) {
|
|
2817
|
+
for (let i = 0; i < 3; i++) {
|
|
2818
|
+
if (a[i] < b[i]) return -1;
|
|
2819
|
+
if (a[i] > b[i]) return 1;
|
|
2820
|
+
}
|
|
2821
|
+
return 0;
|
|
2822
|
+
}
|
|
2823
|
+
function computeTildeBounds(value) {
|
|
2824
|
+
const parsed = parseSemver(value);
|
|
2825
|
+
const lower = [
|
|
2826
|
+
parsed[0],
|
|
2827
|
+
parsed[1],
|
|
2828
|
+
parsed[2]
|
|
2829
|
+
];
|
|
2830
|
+
const upper = [
|
|
2831
|
+
parsed[0],
|
|
2832
|
+
parsed[1] + 1,
|
|
2833
|
+
0
|
|
2834
|
+
];
|
|
2835
|
+
return {
|
|
2836
|
+
lower,
|
|
2837
|
+
upper
|
|
2838
|
+
};
|
|
2839
|
+
}
|
|
2840
|
+
function computeCaretBounds(value) {
|
|
2841
|
+
const parsed = parseSemver(value);
|
|
2842
|
+
const [major, minor, patch] = parsed;
|
|
2843
|
+
const lower = [
|
|
2844
|
+
major,
|
|
2845
|
+
minor,
|
|
2846
|
+
patch
|
|
2847
|
+
];
|
|
2848
|
+
let upper;
|
|
2849
|
+
upper = major > 0 ? [
|
|
2850
|
+
major + 1,
|
|
2851
|
+
0,
|
|
2852
|
+
0
|
|
2853
|
+
] : minor > 0 ? [
|
|
2854
|
+
0,
|
|
2855
|
+
minor + 1,
|
|
2856
|
+
0
|
|
2857
|
+
] : [
|
|
2858
|
+
0,
|
|
2859
|
+
0,
|
|
2860
|
+
patch + 1
|
|
2861
|
+
];
|
|
2862
|
+
return {
|
|
2863
|
+
lower,
|
|
2864
|
+
upper
|
|
2865
|
+
};
|
|
2866
|
+
}
|
|
2867
|
+
function computeWildcardBounds(value) {
|
|
2868
|
+
const text = String(value).trim().replace(/^[vV]/, "");
|
|
2869
|
+
const cleanedText = text.replace(/\.\*$/, "").replace(/\*$/, "");
|
|
2870
|
+
if (!cleanedText) throw new InconclusiveMatchError(`Invalid wildcard semver: ${value}`);
|
|
2871
|
+
const parts = cleanedText.split(".");
|
|
2872
|
+
const major = parseInt(parts[0], 10);
|
|
2873
|
+
if (isNaN(major)) throw new InconclusiveMatchError(`Invalid wildcard semver: ${value}`);
|
|
2874
|
+
let lower;
|
|
2875
|
+
let upper;
|
|
2876
|
+
if (1 === parts.length) {
|
|
2877
|
+
lower = [
|
|
2878
|
+
major,
|
|
2879
|
+
0,
|
|
2880
|
+
0
|
|
2881
|
+
];
|
|
2882
|
+
upper = [
|
|
2883
|
+
major + 1,
|
|
2884
|
+
0,
|
|
2885
|
+
0
|
|
2886
|
+
];
|
|
2887
|
+
} else {
|
|
2888
|
+
const minor = parseInt(parts[1], 10);
|
|
2889
|
+
if (isNaN(minor)) throw new InconclusiveMatchError(`Invalid wildcard semver: ${value}`);
|
|
2890
|
+
lower = [
|
|
2891
|
+
major,
|
|
2892
|
+
minor,
|
|
2893
|
+
0
|
|
2894
|
+
];
|
|
2895
|
+
upper = [
|
|
2896
|
+
major,
|
|
2897
|
+
minor + 1,
|
|
2898
|
+
0
|
|
2899
|
+
];
|
|
2900
|
+
}
|
|
2901
|
+
return {
|
|
2902
|
+
lower,
|
|
2903
|
+
upper
|
|
2904
|
+
};
|
|
2905
|
+
}
|
|
2742
2906
|
function convertToDateTime(value) {
|
|
2743
2907
|
if (value instanceof Date) return value;
|
|
2744
2908
|
if ("string" == typeof value || "number" == typeof value) {
|
|
@@ -2783,22 +2947,44 @@ class PostHogMemoryStorage {
|
|
|
2783
2947
|
const MINIMUM_POLLING_INTERVAL = 100;
|
|
2784
2948
|
const THIRTY_SECONDS = 3e4;
|
|
2785
2949
|
const MAX_CACHE_SIZE = 5e4;
|
|
2950
|
+
const WAITUNTIL_DEBOUNCE_MS = 50;
|
|
2951
|
+
const WAITUNTIL_MAX_WAIT_MS = 500;
|
|
2952
|
+
const DEFAULT_NODE_HOST = "https://us.i.posthog.com";
|
|
2953
|
+
function normalizeApiKey(value) {
|
|
2954
|
+
return "string" == typeof value ? value.trim() : "";
|
|
2955
|
+
}
|
|
2956
|
+
function normalizePersonalApiKey(value) {
|
|
2957
|
+
const normalizedValue = "string" == typeof value ? value.trim() : "";
|
|
2958
|
+
return normalizedValue || void 0;
|
|
2959
|
+
}
|
|
2960
|
+
function normalizeHost(value) {
|
|
2961
|
+
const normalizedValue = "string" == typeof value ? value.trim() : "";
|
|
2962
|
+
return normalizedValue || DEFAULT_NODE_HOST;
|
|
2963
|
+
}
|
|
2786
2964
|
class PostHogBackendClient extends PostHogCoreStateless {
|
|
2787
2965
|
constructor(apiKey, options = {}) {
|
|
2788
|
-
|
|
2789
|
-
|
|
2966
|
+
const normalizedApiKey = normalizeApiKey(apiKey);
|
|
2967
|
+
const normalizedOptions = {
|
|
2968
|
+
...options,
|
|
2969
|
+
host: normalizeHost(options.host),
|
|
2970
|
+
personalApiKey: normalizePersonalApiKey(options.personalApiKey)
|
|
2971
|
+
};
|
|
2972
|
+
super(normalizedApiKey, normalizedOptions), this._memoryStorage = new PostHogMemoryStorage();
|
|
2973
|
+
this.options = normalizedOptions;
|
|
2790
2974
|
this.context = this.initializeContext();
|
|
2791
|
-
this.options.featureFlagsPollingInterval = "number" == typeof
|
|
2792
|
-
if (options.
|
|
2793
|
-
|
|
2794
|
-
|
|
2975
|
+
this.options.featureFlagsPollingInterval = "number" == typeof normalizedOptions.featureFlagsPollingInterval ? Math.max(normalizedOptions.featureFlagsPollingInterval, MINIMUM_POLLING_INTERVAL) : THIRTY_SECONDS;
|
|
2976
|
+
if ("number" == typeof normalizedOptions.waitUntilDebounceMs) this.options.waitUntilDebounceMs = Math.max(normalizedOptions.waitUntilDebounceMs, 0);
|
|
2977
|
+
if ("number" == typeof normalizedOptions.waitUntilMaxWaitMs) this.options.waitUntilMaxWaitMs = Math.max(normalizedOptions.waitUntilMaxWaitMs, 0);
|
|
2978
|
+
if (normalizedOptions.personalApiKey) {
|
|
2979
|
+
if (normalizedOptions.personalApiKey.includes("phc_")) throw new Error('Your Personal API key is invalid. These keys are prefixed with "phx_" and can be created in PostHog project settings.');
|
|
2980
|
+
const shouldEnableLocalEvaluation = false !== normalizedOptions.enableLocalEvaluation;
|
|
2795
2981
|
if (shouldEnableLocalEvaluation) this.featureFlagsPoller = new FeatureFlagsPoller({
|
|
2796
2982
|
pollingInterval: this.options.featureFlagsPollingInterval,
|
|
2797
|
-
personalApiKey:
|
|
2798
|
-
projectApiKey:
|
|
2799
|
-
timeout:
|
|
2983
|
+
personalApiKey: normalizedOptions.personalApiKey,
|
|
2984
|
+
projectApiKey: normalizedApiKey,
|
|
2985
|
+
timeout: normalizedOptions.requestTimeout ?? 1e4,
|
|
2800
2986
|
host: this.host,
|
|
2801
|
-
fetch:
|
|
2987
|
+
fetch: normalizedOptions.fetch,
|
|
2802
2988
|
onError: (err) => {
|
|
2803
2989
|
this._events.emit("error", err);
|
|
2804
2990
|
},
|
|
@@ -2806,13 +2992,74 @@ class PostHogBackendClient extends PostHogCoreStateless {
|
|
|
2806
2992
|
this._events.emit("localEvaluationFlagsLoaded", count);
|
|
2807
2993
|
},
|
|
2808
2994
|
customHeaders: this.getCustomHeaders(),
|
|
2809
|
-
cacheProvider:
|
|
2810
|
-
strictLocalEvaluation:
|
|
2995
|
+
cacheProvider: normalizedOptions.flagDefinitionCacheProvider,
|
|
2996
|
+
strictLocalEvaluation: normalizedOptions.strictLocalEvaluation
|
|
2811
2997
|
});
|
|
2812
2998
|
}
|
|
2813
|
-
this.errorTracking = new ErrorTracking(this,
|
|
2999
|
+
this.errorTracking = new ErrorTracking(this, normalizedOptions, this._logger);
|
|
2814
3000
|
this.distinctIdHasSentFlagCalls = {};
|
|
2815
|
-
this.maxCacheSize =
|
|
3001
|
+
this.maxCacheSize = normalizedOptions.maxCacheSize || MAX_CACHE_SIZE;
|
|
3002
|
+
}
|
|
3003
|
+
enqueue(type, message, options) {
|
|
3004
|
+
super.enqueue(type, message, options);
|
|
3005
|
+
this.scheduleDebouncedFlush();
|
|
3006
|
+
}
|
|
3007
|
+
async flush() {
|
|
3008
|
+
const flushPromise = super.flush();
|
|
3009
|
+
const waitUntil = this.options.waitUntil;
|
|
3010
|
+
if (waitUntil && !this._waitUntilCycle) try {
|
|
3011
|
+
waitUntil(flushPromise.catch(() => {
|
|
3012
|
+
}));
|
|
3013
|
+
} catch {
|
|
3014
|
+
}
|
|
3015
|
+
return flushPromise;
|
|
3016
|
+
}
|
|
3017
|
+
scheduleDebouncedFlush() {
|
|
3018
|
+
const waitUntil = this.options.waitUntil;
|
|
3019
|
+
if (!waitUntil) return;
|
|
3020
|
+
if (this.disabled || this.optedOut) return;
|
|
3021
|
+
if (!this._waitUntilCycle) {
|
|
3022
|
+
let resolve;
|
|
3023
|
+
const promise = new Promise((r) => {
|
|
3024
|
+
resolve = r;
|
|
3025
|
+
});
|
|
3026
|
+
try {
|
|
3027
|
+
waitUntil(promise);
|
|
3028
|
+
} catch {
|
|
3029
|
+
return;
|
|
3030
|
+
}
|
|
3031
|
+
this._waitUntilCycle = {
|
|
3032
|
+
resolve,
|
|
3033
|
+
startedAt: Date.now(),
|
|
3034
|
+
timer: void 0
|
|
3035
|
+
};
|
|
3036
|
+
}
|
|
3037
|
+
const elapsed = Date.now() - this._waitUntilCycle.startedAt;
|
|
3038
|
+
const maxWaitMs = this.options.waitUntilMaxWaitMs ?? WAITUNTIL_MAX_WAIT_MS;
|
|
3039
|
+
const flushNow = elapsed >= maxWaitMs;
|
|
3040
|
+
if (void 0 !== this._waitUntilCycle.timer) clearTimeout(this._waitUntilCycle.timer);
|
|
3041
|
+
if (flushNow) return void this.resolveWaitUntilFlush();
|
|
3042
|
+
const debounceMs = this.options.waitUntilDebounceMs ?? WAITUNTIL_DEBOUNCE_MS;
|
|
3043
|
+
this._waitUntilCycle.timer = safeSetTimeout(() => {
|
|
3044
|
+
this.resolveWaitUntilFlush();
|
|
3045
|
+
}, debounceMs);
|
|
3046
|
+
}
|
|
3047
|
+
_consumeWaitUntilCycle() {
|
|
3048
|
+
const cycle = this._waitUntilCycle;
|
|
3049
|
+
if (cycle) {
|
|
3050
|
+
clearTimeout(cycle.timer);
|
|
3051
|
+
this._waitUntilCycle = void 0;
|
|
3052
|
+
}
|
|
3053
|
+
return cycle?.resolve;
|
|
3054
|
+
}
|
|
3055
|
+
async resolveWaitUntilFlush() {
|
|
3056
|
+
const resolve = this._consumeWaitUntilCycle();
|
|
3057
|
+
try {
|
|
3058
|
+
await super.flush();
|
|
3059
|
+
} catch {
|
|
3060
|
+
} finally {
|
|
3061
|
+
resolve?.();
|
|
3062
|
+
}
|
|
2816
3063
|
}
|
|
2817
3064
|
getPersistedProperty(key) {
|
|
2818
3065
|
return this._memoryStorage.getProperty(key);
|
|
@@ -3029,8 +3276,12 @@ class PostHogBackendClient extends PostHogCoreStateless {
|
|
|
3029
3276
|
locally_evaluated: flagWasLocallyEvaluated,
|
|
3030
3277
|
[`$feature/${key}`]: response,
|
|
3031
3278
|
$feature_flag_request_id: requestId,
|
|
3032
|
-
$feature_flag_evaluated_at: evaluatedAt
|
|
3279
|
+
$feature_flag_evaluated_at: flagWasLocallyEvaluated ? Date.now() : evaluatedAt
|
|
3033
3280
|
};
|
|
3281
|
+
if (flagWasLocallyEvaluated && this.featureFlagsPoller) {
|
|
3282
|
+
const flagDefinitionsLoadedAt = this.featureFlagsPoller.getFlagDefinitionsLoadedAt();
|
|
3283
|
+
if (void 0 !== flagDefinitionsLoadedAt) properties.$feature_flag_definitions_loaded_at = flagDefinitionsLoadedAt;
|
|
3284
|
+
}
|
|
3034
3285
|
if (featureFlagError) properties.$feature_flag_error = featureFlagError;
|
|
3035
3286
|
this.capture({
|
|
3036
3287
|
distinctId,
|
|
@@ -3213,9 +3464,14 @@ class PostHogBackendClient extends PostHogCoreStateless {
|
|
|
3213
3464
|
this.context?.enter(data, options);
|
|
3214
3465
|
}
|
|
3215
3466
|
async _shutdown(shutdownTimeoutMs) {
|
|
3216
|
-
this.
|
|
3467
|
+
const resolve = this._consumeWaitUntilCycle();
|
|
3468
|
+
await this.featureFlagsPoller?.stopPoller(shutdownTimeoutMs);
|
|
3217
3469
|
this.errorTracking.shutdown();
|
|
3218
|
-
|
|
3470
|
+
try {
|
|
3471
|
+
return await super._shutdown(shutdownTimeoutMs);
|
|
3472
|
+
} finally {
|
|
3473
|
+
resolve?.();
|
|
3474
|
+
}
|
|
3219
3475
|
}
|
|
3220
3476
|
async _requestRemoteConfigPayload(flagKey) {
|
|
3221
3477
|
if (!this.options.personalApiKey) return;
|
|
@@ -3332,7 +3588,7 @@ class PostHogBackendClient extends PostHogCoreStateless {
|
|
|
3332
3588
|
async captureExceptionImmediate(error, distinctId, additionalProperties) {
|
|
3333
3589
|
if (!ErrorTracking.isPreviouslyCapturedError(error)) {
|
|
3334
3590
|
const syntheticException = new Error("PostHog syntheticException");
|
|
3335
|
-
this.addPendingPromise(ErrorTracking.buildEventMessage(error, {
|
|
3591
|
+
return this.addPendingPromise(ErrorTracking.buildEventMessage(error, {
|
|
3336
3592
|
syntheticException
|
|
3337
3593
|
}, distinctId, additionalProperties).then((msg) => this.captureImmediate(msg)));
|
|
3338
3594
|
}
|
|
@@ -3485,7 +3741,8 @@ ErrorTracking.errorPropertiesBuilder = new ErrorPropertiesBuilder([
|
|
|
3485
3741
|
new PrimitiveCoercer()
|
|
3486
3742
|
], createStackParser("node:javascript", nodeStackLineParser), [
|
|
3487
3743
|
createModulerModifier(),
|
|
3488
|
-
addSourceContext
|
|
3744
|
+
addSourceContext,
|
|
3745
|
+
createRelativePathModifier()
|
|
3489
3746
|
]);
|
|
3490
3747
|
class PostHog extends PostHogBackendClient {
|
|
3491
3748
|
getLibraryId() {
|
|
@@ -3816,30 +4073,30 @@ const shutdownSession = async (session2) => {
|
|
|
3816
4073
|
};
|
|
3817
4074
|
const toPosixPath = (input) => input.split(path.sep).join("/");
|
|
3818
4075
|
const isSubpath = (candidate, root) => {
|
|
3819
|
-
const
|
|
3820
|
-
return
|
|
4076
|
+
const relative2 = path.relative(root, candidate);
|
|
4077
|
+
return relative2 === "" || !relative2.startsWith("..") && !path.isAbsolute(relative2);
|
|
3821
4078
|
};
|
|
3822
4079
|
const classifyServerTarget = (absolutePath, projectRoot) => {
|
|
3823
4080
|
if (!isSubpath(absolutePath, projectRoot)) {
|
|
3824
4081
|
return "ssr";
|
|
3825
4082
|
}
|
|
3826
|
-
const
|
|
3827
|
-
if (
|
|
4083
|
+
const relative2 = toPosixPath(path.relative(projectRoot, absolutePath));
|
|
4084
|
+
if (relative2.startsWith("src/api/") || relative2.includes("/src/api/")) {
|
|
3828
4085
|
return "api";
|
|
3829
4086
|
}
|
|
3830
|
-
if (
|
|
4087
|
+
if (relative2.startsWith("src/worker/") || relative2.includes("/src/worker/")) {
|
|
3831
4088
|
return "worker";
|
|
3832
4089
|
}
|
|
3833
|
-
if (
|
|
4090
|
+
if (relative2.startsWith("src/server/") || relative2.includes("/src/server/")) {
|
|
3834
4091
|
return "ssr";
|
|
3835
4092
|
}
|
|
3836
|
-
if (
|
|
4093
|
+
if (relative2.startsWith("build/dist/api/") || relative2.includes("/build/dist/api/")) {
|
|
3837
4094
|
return "api";
|
|
3838
4095
|
}
|
|
3839
|
-
if (
|
|
4096
|
+
if (relative2.startsWith("build/dist/worker/") || relative2.includes("/build/dist/worker/")) {
|
|
3840
4097
|
return "worker";
|
|
3841
4098
|
}
|
|
3842
|
-
if (
|
|
4099
|
+
if (relative2.startsWith("build/dist/ssr/") || relative2.includes("/build/dist/ssr/")) {
|
|
3843
4100
|
return "ssr";
|
|
3844
4101
|
}
|
|
3845
4102
|
return "ssr";
|