oh-my-opencode 5.0.0-beta.12 → 5.0.0-beta.13

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.
Files changed (98) hide show
  1. package/.agents/skills/senpi-qa/SKILL.md +80 -0
  2. package/.agents/skills/senpi-qa/scripts/resolve-evidence-dir.mjs +65 -0
  3. package/.agents/skills/senpi-qa/scripts/resolve-evidence-dir.test.mjs +171 -0
  4. package/dist/cli/index.js +6774 -4320
  5. package/dist/cli-node/index.js +6774 -4320
  6. package/dist/create-hooks.d.ts +1 -0
  7. package/dist/features/btw-side/btw-command-draft.d.ts +7 -0
  8. package/dist/features/btw-side/context-injector.d.ts +15 -0
  9. package/dist/features/btw-side/index.d.ts +8 -0
  10. package/dist/features/btw-side/metadata.d.ts +15 -0
  11. package/dist/features/btw-side/parent-context-budget.d.ts +9 -0
  12. package/dist/features/btw-side/server-session-registry.d.ts +8 -0
  13. package/dist/features/btw-side/tui-adoption-cache.d.ts +13 -0
  14. package/dist/features/btw-side/tui-adoption-guard.d.ts +5 -0
  15. package/dist/features/btw-side/tui-controller-types.d.ts +63 -0
  16. package/dist/features/btw-side/tui-controller.d.ts +14 -0
  17. package/dist/features/btw-side/tui-keymap.d.ts +10 -0
  18. package/dist/features/btw-side/tui-parent-validator.d.ts +6 -0
  19. package/dist/features/btw-side/tui-prompt-queue.d.ts +8 -0
  20. package/dist/features/btw-side/tui-session-bridge.d.ts +11 -0
  21. package/dist/features/btw-side/tui-side-removal.d.ts +11 -0
  22. package/dist/features/btw-side/tui-side-start.d.ts +9 -0
  23. package/dist/features/btw-side/tui-wiring.d.ts +8 -0
  24. package/dist/hooks/runtime-fallback/chat-message-handler.d.ts +2 -0
  25. package/dist/hooks/runtime-fallback/retry-model-payload.d.ts +1 -0
  26. package/dist/hooks/runtime-fallback/runtime-model-settings.d.ts +6 -0
  27. package/dist/hooks/runtime-fallback/session-status-handler.d.ts +1 -1
  28. package/dist/hooks/runtime-fallback/types.d.ts +3 -1
  29. package/dist/index.js +6502 -3850
  30. package/dist/plugin/event-session-lifecycle.d.ts +1 -0
  31. package/dist/plugin/hooks/create-core-hooks.d.ts +1 -0
  32. package/dist/plugin/hooks/create-transform-hooks.d.ts +2 -0
  33. package/dist/plugin/messages-transform.d.ts +1 -0
  34. package/dist/shared/index.d.ts +1 -0
  35. package/dist/shared/runtime-fallback-retry-marker.d.ts +16 -0
  36. package/dist/tui.js +8092 -6792
  37. package/package.json +24 -23
  38. package/packages/git-bash-mcp/dist/cli.js +5 -1
  39. package/packages/lsp-daemon/dist/cli.js +5 -1
  40. package/packages/lsp-daemon/dist/client.js +5 -1
  41. package/packages/lsp-daemon/dist/index.js +5 -1
  42. package/packages/lsp-tools-mcp/dist/cli.js +5 -1
  43. package/packages/lsp-tools-mcp/dist/mcp.js +5 -1
  44. package/packages/omo-codex/plugin/.codex-plugin/plugin.json +1 -1
  45. package/packages/omo-codex/plugin/components/bootstrap/hooks/hooks.json +1 -1
  46. package/packages/omo-codex/plugin/components/bootstrap/package.json +1 -1
  47. package/packages/omo-codex/plugin/components/codegraph/dist/cli.js +5 -1
  48. package/packages/omo-codex/plugin/components/codegraph/dist/serve.js +5 -1
  49. package/packages/omo-codex/plugin/components/codegraph/package.json +1 -1
  50. package/packages/omo-codex/plugin/components/comment-checker/hooks/hooks.json +1 -1
  51. package/packages/omo-codex/plugin/components/comment-checker/package.json +1 -1
  52. package/packages/omo-codex/plugin/components/git-bash/hooks/hooks.json +2 -2
  53. package/packages/omo-codex/plugin/components/git-bash/package.json +1 -1
  54. package/packages/omo-codex/plugin/components/lazycodex-executor-verify/hooks/hooks.json +1 -1
  55. package/packages/omo-codex/plugin/components/lazycodex-executor-verify/package.json +1 -1
  56. package/packages/omo-codex/plugin/components/lsp/dist/.omo-runtime-manifest.json +2 -2
  57. package/packages/omo-codex/plugin/components/lsp/hooks/hooks.json +2 -2
  58. package/packages/omo-codex/plugin/components/lsp/package.json +1 -1
  59. package/packages/omo-codex/plugin/components/rules/hooks/hooks.json +4 -4
  60. package/packages/omo-codex/plugin/components/rules/package.json +1 -1
  61. package/packages/omo-codex/plugin/components/start-work-continuation/hooks/hooks.json +2 -2
  62. package/packages/omo-codex/plugin/components/start-work-continuation/package.json +1 -1
  63. package/packages/omo-codex/plugin/components/teammode/hooks/hooks.json +1 -1
  64. package/packages/omo-codex/plugin/components/teammode/package.json +1 -1
  65. package/packages/omo-codex/plugin/components/telemetry/dist/cli.js +2242 -381
  66. package/packages/omo-codex/plugin/components/telemetry/dist/posthog.js +2247 -386
  67. package/packages/omo-codex/plugin/components/telemetry/hooks/hooks.json +1 -1
  68. package/packages/omo-codex/plugin/components/telemetry/package.json +1 -1
  69. package/packages/omo-codex/plugin/components/ultrawork/hooks/hooks.json +1 -1
  70. package/packages/omo-codex/plugin/components/ultrawork/package.json +1 -1
  71. package/packages/omo-codex/plugin/components/ulw-loop/hooks/hooks.json +4 -4
  72. package/packages/omo-codex/plugin/components/ulw-loop/package.json +1 -1
  73. package/packages/omo-codex/plugin/hooks/post-compact-resetting-git-bash-mcp-reminder.json +1 -1
  74. package/packages/omo-codex/plugin/hooks/post-compact-resetting-lsp-diagnostics-cache.json +1 -1
  75. package/packages/omo-codex/plugin/hooks/post-compact-resetting-project-rule-cache.json +1 -1
  76. package/packages/omo-codex/plugin/hooks/post-tool-use-checking-codegraph-init-guidance.json +1 -1
  77. package/packages/omo-codex/plugin/hooks/post-tool-use-checking-comments.json +1 -1
  78. package/packages/omo-codex/plugin/hooks/post-tool-use-checking-lsp-diagnostics.json +1 -1
  79. package/packages/omo-codex/plugin/hooks/post-tool-use-checking-thread-title-hygiene.json +1 -1
  80. package/packages/omo-codex/plugin/hooks/post-tool-use-matching-project-rules.json +1 -1
  81. package/packages/omo-codex/plugin/hooks/pre-tool-use-enforcing-unlimited-goal-budget.json +1 -1
  82. package/packages/omo-codex/plugin/hooks/pre-tool-use-guarding-ulw-loop-spawns.json +1 -1
  83. package/packages/omo-codex/plugin/hooks/pre-tool-use-recommending-git-bash-mcp.json +1 -1
  84. package/packages/omo-codex/plugin/hooks/session-start-checking-auto-update.json +1 -1
  85. package/packages/omo-codex/plugin/hooks/session-start-checking-bootstrap-provisioning.json +1 -1
  86. package/packages/omo-codex/plugin/hooks/session-start-checking-codegraph-bootstrap.json +1 -1
  87. package/packages/omo-codex/plugin/hooks/session-start-loading-project-rules.json +1 -1
  88. package/packages/omo-codex/plugin/hooks/session-start-recording-session-telemetry.json +1 -1
  89. package/packages/omo-codex/plugin/hooks/stop-checking-start-work-continuation.json +1 -1
  90. package/packages/omo-codex/plugin/hooks/stop-checking-ulw-loop-resume.json +1 -1
  91. package/packages/omo-codex/plugin/hooks/subagent-stop-checking-start-work-continuation.json +1 -1
  92. package/packages/omo-codex/plugin/hooks/subagent-stop-verifying-lazycodex-executor-evidence.json +1 -1
  93. package/packages/omo-codex/plugin/hooks/user-prompt-submit-checking-ultrawork-trigger.json +1 -1
  94. package/packages/omo-codex/plugin/hooks/user-prompt-submit-checking-ulw-loop-steering.json +1 -1
  95. package/packages/omo-codex/plugin/hooks/user-prompt-submit-loading-project-rules.json +1 -1
  96. package/packages/omo-codex/plugin/package-lock.json +13 -13
  97. package/packages/omo-codex/plugin/package.json +1 -1
  98. package/packages/omo-codex/scripts/install-dist/install-local.mjs +2307 -401
@@ -334,7 +334,7 @@ function getTelemetryHost(env = process.env, defaultHost = DEFAULT_POSTHOG_HOST)
334
334
  return env["POSTHOG_HOST"]?.trim() || defaultHost;
335
335
  }
336
336
 
337
- // ../../../../../node_modules/.bun/posthog-node@5.35.12/node_modules/posthog-node/dist/extensions/error-tracking/modifiers/module.node.mjs
337
+ // ../../../../../node_modules/.bun/posthog-node@5.49.2/node_modules/posthog-node/dist/extensions/error-tracking/modifiers/module.node.mjs
338
338
  import { dirname, posix, sep } from "path";
339
339
  function createModulerModifier() {
340
340
  const getModuleFromFileName = createGetModuleFromFilename();
@@ -370,7 +370,7 @@ function normalizeWindowsPath(path2) {
370
370
  return path2.replace(/^[A-Z]:/, "").replace(/\\/g, "/");
371
371
  }
372
372
 
373
- // ../../../../../node_modules/.bun/@posthog+core@1.30.3/node_modules/@posthog/core/dist/featureFlagUtils.mjs
373
+ // ../../../../../node_modules/.bun/@posthog+core@1.48.6/node_modules/@posthog/core/dist/featureFlagUtils.mjs
374
374
  var normalizeFlagsResponse = (flagsResponse) => {
375
375
  if ("flags" in flagsResponse) {
376
376
  const featureFlags = getFlagValuesFromFlags(flagsResponse.flags);
@@ -440,8 +440,69 @@ var parsePayload = (response) => {
440
440
  return response;
441
441
  }
442
442
  };
443
+ var MINIMAL_FLAG_CALLED_EVENT_CAMPAIGN_PROPERTIES = [
444
+ "utm_source",
445
+ "utm_medium",
446
+ "utm_campaign",
447
+ "utm_content",
448
+ "utm_term",
449
+ "gad_source",
450
+ "mc_cid",
451
+ "gclid",
452
+ "gclsrc",
453
+ "dclid",
454
+ "gbraid",
455
+ "wbraid",
456
+ "fbclid",
457
+ "msclkid",
458
+ "twclid",
459
+ "li_fat_id",
460
+ "igshid",
461
+ "ttclid",
462
+ "rdt_cid",
463
+ "epik",
464
+ "qclid",
465
+ "sccid",
466
+ "irclid",
467
+ "_kx"
468
+ ];
469
+ var MINIMAL_FLAG_CALLED_EVENT_PROPERTIES = [
470
+ "$feature_flag",
471
+ "$feature_flag_response",
472
+ "$feature_flag_has_experiment",
473
+ "$feature_flag_id",
474
+ "$feature_flag_version",
475
+ "$feature_flag_reason",
476
+ "$feature_flag_request_id",
477
+ "$feature_flag_evaluated_at",
478
+ "$feature_flag_error",
479
+ "locally_evaluated",
480
+ "$groups",
481
+ "$process_person_profile",
482
+ "$geoip_disable",
483
+ "$current_url",
484
+ "$pathname",
485
+ "$referring_domain",
486
+ ...MINIMAL_FLAG_CALLED_EVENT_CAMPAIGN_PROPERTIES,
487
+ "$session_id",
488
+ "$window_id",
489
+ "$lib",
490
+ "$lib_version",
491
+ "$device_id",
492
+ "$is_server"
493
+ ];
494
+ var minimizeFlagCalledEventProperties = (properties, transportKeys = []) => {
495
+ const minimal = {};
496
+ const copyKey = (key) => {
497
+ if (properties[key] !== undefined)
498
+ minimal[key] = properties[key];
499
+ };
500
+ MINIMAL_FLAG_CALLED_EVENT_PROPERTIES.forEach(copyKey);
501
+ transportKeys.forEach(copyKey);
502
+ return minimal;
503
+ };
443
504
 
444
- // ../../../../../node_modules/.bun/@posthog+core@1.30.3/node_modules/@posthog/core/dist/types.mjs
505
+ // ../../../../../node_modules/.bun/@posthog+core@1.48.6/node_modules/@posthog/core/dist/types.mjs
445
506
  var types_PostHogPersistedProperty = /* @__PURE__ */ function(PostHogPersistedProperty) {
446
507
  PostHogPersistedProperty["AnonymousId"] = "anonymous_id";
447
508
  PostHogPersistedProperty["DistinctId"] = "distinct_id";
@@ -456,6 +517,8 @@ var types_PostHogPersistedProperty = /* @__PURE__ */ function(PostHogPersistedPr
456
517
  PostHogPersistedProperty["BootstrapFeatureFlagPayloads"] = "bootstrap_feature_flag_payloads";
457
518
  PostHogPersistedProperty["OverrideFeatureFlags"] = "override_feature_flags";
458
519
  PostHogPersistedProperty["Queue"] = "queue";
520
+ PostHogPersistedProperty["AiQueue"] = "ai_queue";
521
+ PostHogPersistedProperty["AiCaptureQueue"] = "ai_capture_queue";
459
522
  PostHogPersistedProperty["LogsQueue"] = "logs_queue";
460
523
  PostHogPersistedProperty["OptedOut"] = "opted_out";
461
524
  PostHogPersistedProperty["SessionId"] = "session_id";
@@ -466,6 +529,8 @@ var types_PostHogPersistedProperty = /* @__PURE__ */ function(PostHogPersistedPr
466
529
  PostHogPersistedProperty["InstalledAppBuild"] = "installed_app_build";
467
530
  PostHogPersistedProperty["InstalledAppVersion"] = "installed_app_version";
468
531
  PostHogPersistedProperty["SessionReplay"] = "session_replay";
532
+ PostHogPersistedProperty["PushRegistered"] = "push_registered";
533
+ PostHogPersistedProperty["SessionReplayEventTriggerActivatedSession"] = "session_replay_event_trigger_activated_session";
469
534
  PostHogPersistedProperty["SurveyLastSeenDate"] = "survey_last_seen_date";
470
535
  PostHogPersistedProperty["SurveysSeen"] = "surveys_seen";
471
536
  PostHogPersistedProperty["Surveys"] = "surveys";
@@ -475,7 +540,7 @@ var types_PostHogPersistedProperty = /* @__PURE__ */ function(PostHogPersistedPr
475
540
  return PostHogPersistedProperty;
476
541
  }({});
477
542
 
478
- // ../../../../../node_modules/.bun/@posthog+core@1.30.3/node_modules/@posthog/core/dist/gzip.mjs
543
+ // ../../../../../node_modules/.bun/@posthog+core@1.48.6/node_modules/@posthog/core/dist/gzip.mjs
479
544
  function isGzipSupported() {
480
545
  return "CompressionStream" in globalThis && "TextEncoder" in globalThis && "Response" in globalThis && typeof Response.prototype.blob == "function";
481
546
  }
@@ -525,7 +590,7 @@ var validateNativeGzip = async (compressed, inputBytes) => {
525
590
  async function gzipCompress(input, isDebug = true, options) {
526
591
  try {
527
592
  const inputBytes = new TextEncoder().encode(input);
528
- const compressedStream = new CompressionStream("gzip");
593
+ const compressedStream = new globalThis.CompressionStream("gzip");
529
594
  const writer = compressedStream.writable.getWriter();
530
595
  const writePromise = writer.write(inputBytes).then(() => writer.close()).catch(async (err) => {
531
596
  try {
@@ -549,7 +614,7 @@ async function gzipCompress(input, isDebug = true, options) {
549
614
  }
550
615
  }
551
616
 
552
- // ../../../../../node_modules/.bun/@posthog+core@1.30.3/node_modules/@posthog/core/dist/utils/bot-detection.mjs
617
+ // ../../../../../node_modules/.bun/@posthog+core@1.48.6/node_modules/@posthog/core/dist/utils/bot-detection.mjs
553
618
  var DEFAULT_BLOCKED_UA_STRS = [
554
619
  "amazonbot",
555
620
  "amazonproductbot",
@@ -638,7 +703,31 @@ var isBlockedUA = function(ua, customBlockedUserAgents = []) {
638
703
  return uaLower.indexOf(blockedUaLower) !== -1;
639
704
  });
640
705
  };
641
- // ../../../../../node_modules/.bun/@posthog+core@1.30.3/node_modules/@posthog/core/dist/utils/type-utils.mjs
706
+ // ../../../../../node_modules/.bun/@posthog+core@1.48.6/node_modules/@posthog/core/dist/utils/string-utils.mjs
707
+ function safeJsonStringify(value) {
708
+ const ancestors = [];
709
+ return JSON.stringify(value, function(_key, replacementValue) {
710
+ if (typeof replacementValue == "bigint")
711
+ return replacementValue.toString();
712
+ if (typeof replacementValue == "function" || typeof replacementValue == "symbol")
713
+ return;
714
+ if (replacementValue instanceof Error)
715
+ return {
716
+ name: replacementValue.name,
717
+ message: replacementValue.message,
718
+ stack: replacementValue.stack
719
+ };
720
+ if (replacementValue && typeof replacementValue == "object") {
721
+ while (ancestors.length > 0 && ancestors[ancestors.length - 1] !== this)
722
+ ancestors.pop();
723
+ if (ancestors.includes(replacementValue))
724
+ return "[Circular]";
725
+ ancestors.push(replacementValue);
726
+ }
727
+ return replacementValue;
728
+ }) ?? "null";
729
+ }
730
+ // ../../../../../node_modules/.bun/@posthog+core@1.48.6/node_modules/@posthog/core/dist/utils/type-utils.mjs
642
731
  var nativeIsArray = Array.isArray;
643
732
  var ObjProto = Object.prototype;
644
733
  var type_utils_hasOwnProperty = ObjProto.hasOwnProperty;
@@ -650,14 +739,27 @@ var isObject = (x) => x === Object(x) && !isArray(x);
650
739
  var isUndefined = (x) => x === undefined;
651
740
  var isString = (x) => type_utils_toString.call(x) == "[object String]";
652
741
  var isEmptyString = (x) => isString(x) && x.trim().length === 0;
742
+ var isNull = (x) => x === null;
653
743
  var isNumber = (x) => type_utils_toString.call(x) == "[object Number]" && x === x;
654
- var isPlainError = (x) => x instanceof Error;
744
+ var isBoolean = (x) => type_utils_toString.call(x) === "[object Boolean]";
655
745
  function isPrimitive(value) {
656
746
  return value === null || typeof value != "object";
657
747
  }
658
748
  function isBuiltin(candidate, className) {
659
749
  return Object.prototype.toString.call(candidate) === `[object ${className}]`;
660
750
  }
751
+ function isError(candidate) {
752
+ switch (Object.prototype.toString.call(candidate)) {
753
+ case "[object Error]":
754
+ case "[object Exception]":
755
+ case "[object DOMException]":
756
+ case "[object DOMError]":
757
+ case "[object WebAssembly.Exception]":
758
+ return true;
759
+ default:
760
+ return isInstanceOf(candidate, Error);
761
+ }
762
+ }
661
763
  function isErrorEvent(event) {
662
764
  return isBuiltin(event, "ErrorEvent");
663
765
  }
@@ -675,7 +777,7 @@ function isInstanceOf(candidate, base) {
675
777
  }
676
778
  }
677
779
 
678
- // ../../../../../node_modules/.bun/@posthog+core@1.30.3/node_modules/@posthog/core/dist/utils/number-utils.mjs
780
+ // ../../../../../node_modules/.bun/@posthog+core@1.48.6/node_modules/@posthog/core/dist/utils/number-utils.mjs
679
781
  function clampToRange(value, min, max, logger, fallbackValue) {
680
782
  if (min > max) {
681
783
  logger.warn("min cannot be greater than max.");
@@ -695,8 +797,16 @@ function clampToRange(value, min, max, logger, fallbackValue) {
695
797
  return clampToRange(fallbackValue || max, min, max, logger);
696
798
  }
697
799
 
698
- // ../../../../../node_modules/.bun/@posthog+core@1.30.3/node_modules/@posthog/core/dist/utils/bucketed-rate-limiter.mjs
800
+ // ../../../../../node_modules/.bun/@posthog+core@1.48.6/node_modules/@posthog/core/dist/utils/bucketed-rate-limiter.mjs
699
801
  var ONE_DAY_IN_MS = 86400000;
802
+ var DEFAULT_EXCEPTION_RATE_LIMITER_REFILL_RATE = 1;
803
+ var DEFAULT_EXCEPTION_RATE_LIMITER_BUCKET_SIZE = 10;
804
+ function resolveExceptionRateLimiterConfig(config = {}) {
805
+ return {
806
+ refillRate: config.exceptionRateLimiterRefillRate ?? config.__exceptionRateLimiterRefillRate ?? DEFAULT_EXCEPTION_RATE_LIMITER_REFILL_RATE,
807
+ bucketSize: config.exceptionRateLimiterBucketSize ?? config.__exceptionRateLimiterBucketSize ?? DEFAULT_EXCEPTION_RATE_LIMITER_BUCKET_SIZE
808
+ };
809
+ }
700
810
 
701
811
  class BucketedRateLimiter {
702
812
  constructor(options) {
@@ -739,7 +849,10 @@ class BucketedRateLimiter {
739
849
  this._buckets = {};
740
850
  }
741
851
  }
742
- // ../../../../../node_modules/.bun/@posthog+core@1.30.3/node_modules/@posthog/core/dist/vendor/uuidv7.mjs
852
+ // ../../../../../node_modules/.bun/@posthog+core@1.48.6/node_modules/@posthog/core/dist/utils/json-utils.mjs
853
+ var dateGetTime = Date.prototype.getTime;
854
+ var dateToISOString = Date.prototype.toISOString;
855
+ // ../../../../../node_modules/.bun/@posthog+core@1.48.6/node_modules/@posthog/core/dist/vendor/uuidv7.mjs
743
856
  /*! For license information please see uuidv7.mjs.LICENSE.txt */
744
857
  var DIGITS = "0123456789abcdef";
745
858
 
@@ -917,33 +1030,45 @@ var defaultGenerator;
917
1030
  var uuidv7 = () => uuidv7obj().toString();
918
1031
  var uuidv7obj = () => (defaultGenerator || (defaultGenerator = new V7Generator)).generate();
919
1032
 
920
- // ../../../../../node_modules/.bun/@posthog+core@1.30.3/node_modules/@posthog/core/dist/utils/promise-queue.mjs
1033
+ // ../../../../../node_modules/.bun/@posthog+core@1.48.6/node_modules/@posthog/core/dist/utils/promise-queue.mjs
921
1034
  class PromiseQueue {
922
1035
  add(promise) {
923
1036
  const promiseUUID = uuidv7();
924
- this.promiseByIds[promiseUUID] = promise;
1037
+ const id = ++this.nextId;
1038
+ this.promiseByIds[promiseUUID] = {
1039
+ id,
1040
+ promise
1041
+ };
925
1042
  promise.catch(() => {}).finally(() => {
926
1043
  delete this.promiseByIds[promiseUUID];
927
1044
  });
928
1045
  return promise;
929
1046
  }
930
1047
  async join() {
931
- let promises = Object.values(this.promiseByIds);
1048
+ let promises = Object.values(this.promiseByIds).map((item) => item.promise);
932
1049
  let length = promises.length;
933
1050
  while (length > 0) {
934
1051
  await Promise.all(promises);
935
- promises = Object.values(this.promiseByIds);
1052
+ promises = Object.values(this.promiseByIds).map((item) => item.promise);
936
1053
  length = promises.length;
937
1054
  }
938
1055
  }
1056
+ getPromises(ignoredPromises = [], maxId = this.nextId) {
1057
+ const ignoredPromiseSet = new Set(ignoredPromises);
1058
+ return Object.values(this.promiseByIds).filter((item) => item.id <= maxId && !ignoredPromiseSet.has(item.promise)).map((item) => item.promise);
1059
+ }
1060
+ get maxId() {
1061
+ return this.nextId;
1062
+ }
939
1063
  get length() {
940
1064
  return Object.keys(this.promiseByIds).length;
941
1065
  }
942
1066
  constructor() {
943
1067
  this.promiseByIds = {};
1068
+ this.nextId = 0;
944
1069
  }
945
1070
  }
946
- // ../../../../../node_modules/.bun/@posthog+core@1.30.3/node_modules/@posthog/core/dist/utils/logger.mjs
1071
+ // ../../../../../node_modules/.bun/@posthog+core@1.48.6/node_modules/@posthog/core/dist/utils/logger.mjs
947
1072
  function createConsole(consoleLike = console) {
948
1073
  const lockedMethods = {
949
1074
  log: consoleLike.log.bind(consoleLike),
@@ -984,7 +1109,7 @@ var passThrough = (fn) => fn();
984
1109
  function createLogger(prefix, maybeCall = passThrough) {
985
1110
  return _createLogger(prefix, maybeCall, createConsole());
986
1111
  }
987
- // ../../../../../node_modules/.bun/@posthog+core@1.30.3/node_modules/@posthog/core/dist/utils/user-agent-utils.mjs
1112
+ // ../../../../../node_modules/.bun/@posthog+core@1.48.6/node_modules/@posthog/core/dist/utils/user-agent-utils.mjs
988
1113
  var MOBILE = "Mobile";
989
1114
  var IOS = "iOS";
990
1115
  var ANDROID = "Android";
@@ -1027,6 +1152,7 @@ var DUCKDUCKGO = "DuckDuckGo";
1027
1152
  var PALE_MOON = "Pale Moon";
1028
1153
  var WATERFOX = "Waterfox";
1029
1154
  var BRAVE = "Brave";
1155
+ var GOOGLE_SEARCH_APP = "Google Search App";
1030
1156
  var BROWSER_VERSION_REGEX_SUFFIX = "(\\d+(\\.\\d+)?)";
1031
1157
  var DEFAULT_BROWSER_VERSION_REGEX = new RegExp("Version/" + BROWSER_VERSION_REGEX_SUFFIX);
1032
1158
  var XBOX_REGEX = new RegExp(XBOX, "i");
@@ -1114,6 +1240,9 @@ var versionRegexes = {
1114
1240
  [WATERFOX]: [
1115
1241
  new RegExp(WATERFOX + "\\/" + BROWSER_VERSION_REGEX_SUFFIX)
1116
1242
  ],
1243
+ [GOOGLE_SEARCH_APP]: [
1244
+ new RegExp("GSA\\/" + BROWSER_VERSION_REGEX_SUFFIX)
1245
+ ],
1117
1246
  [INTERNET_EXPLORER]: [
1118
1247
  new RegExp("(rv:|MSIE )" + BROWSER_VERSION_REGEX_SUFFIX)
1119
1248
  ],
@@ -1273,8 +1402,15 @@ var osMatchers = [
1273
1402
  ]
1274
1403
  ];
1275
1404
 
1276
- // ../../../../../node_modules/.bun/@posthog+core@1.30.3/node_modules/@posthog/core/dist/utils/index.mjs
1405
+ // ../../../../../node_modules/.bun/@posthog+core@1.48.6/node_modules/@posthog/core/dist/utils/index.mjs
1277
1406
  var STRING_FORMAT = "utf8";
1407
+ var UUID_REGEX = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;
1408
+ function isValidUUID(value) {
1409
+ return typeof value == "string" && UUID_REGEX.test(value);
1410
+ }
1411
+ function getEventUuid(uuid, generateUuid) {
1412
+ return isValidUUID(uuid) ? uuid : generateUuid();
1413
+ }
1278
1414
  function removeTrailingSlash(url) {
1279
1415
  return url?.replace(/\/+$/, "");
1280
1416
  }
@@ -1302,7 +1438,26 @@ function safeSetTimeout(fn, timeout) {
1302
1438
  t?.unref && t?.unref();
1303
1439
  return t;
1304
1440
  }
1305
- var isError = (x) => x instanceof Error;
1441
+ async function raceWithTimeout(promise, timeoutMs, onTimeout) {
1442
+ let timeoutHandle;
1443
+ try {
1444
+ return await Promise.race([
1445
+ promise,
1446
+ new Promise((resolve, reject) => {
1447
+ timeoutHandle = safeSetTimeout(() => {
1448
+ try {
1449
+ onTimeout?.();
1450
+ resolve();
1451
+ } catch (error) {
1452
+ reject(error);
1453
+ }
1454
+ }, timeoutMs);
1455
+ })
1456
+ ]);
1457
+ } finally {
1458
+ clearTimeout(timeoutHandle);
1459
+ }
1460
+ }
1306
1461
  function allSettled(promises) {
1307
1462
  return Promise.all(promises.map((p) => (p ?? Promise.resolve()).then((value) => ({
1308
1463
  status: "fulfilled",
@@ -1313,7 +1468,7 @@ function allSettled(promises) {
1313
1468
  }))));
1314
1469
  }
1315
1470
 
1316
- // ../../../../../node_modules/.bun/@posthog+core@1.30.3/node_modules/@posthog/core/dist/logs/logs-utils.mjs
1471
+ // ../../../../../node_modules/.bun/@posthog+core@1.48.6/node_modules/@posthog/core/dist/logs/logs-utils.mjs
1317
1472
  var OTLP_SEVERITY_MAP = {
1318
1473
  trace: {
1319
1474
  text: "TRACE",
@@ -1341,7 +1496,464 @@ var OTLP_SEVERITY_MAP = {
1341
1496
  }
1342
1497
  };
1343
1498
  var DEFAULT_OTLP_SEVERITY = OTLP_SEVERITY_MAP.info;
1344
- // ../../../../../node_modules/.bun/@posthog+core@1.30.3/node_modules/@posthog/core/dist/eventemitter.mjs
1499
+ function toOtlpAnyValue(value) {
1500
+ if (isBoolean(value))
1501
+ return {
1502
+ boolValue: value
1503
+ };
1504
+ if (typeof value == "number") {
1505
+ if (!Number.isFinite(value))
1506
+ return {
1507
+ stringValue: String(value)
1508
+ };
1509
+ if (Number.isInteger(value))
1510
+ return {
1511
+ intValue: value
1512
+ };
1513
+ return {
1514
+ doubleValue: value
1515
+ };
1516
+ }
1517
+ if (typeof value == "string")
1518
+ return {
1519
+ stringValue: value
1520
+ };
1521
+ if (isArray(value))
1522
+ return {
1523
+ arrayValue: {
1524
+ values: value.map((v) => toOtlpAnyValue(v))
1525
+ }
1526
+ };
1527
+ try {
1528
+ return {
1529
+ stringValue: JSON.stringify(value)
1530
+ };
1531
+ } catch {
1532
+ return {
1533
+ stringValue: String(value)
1534
+ };
1535
+ }
1536
+ }
1537
+ function toOtlpKeyValueList(attrs) {
1538
+ const result = [];
1539
+ for (const key in attrs) {
1540
+ const value = attrs[key];
1541
+ if (!(isNull(value) || isUndefined(value)))
1542
+ result.push({
1543
+ key,
1544
+ value: toOtlpAnyValue(value)
1545
+ });
1546
+ }
1547
+ return result;
1548
+ }
1549
+
1550
+ // ../../../../../node_modules/.bun/@posthog+core@1.48.6/node_modules/@posthog/core/dist/metrics/metrics-utils.mjs
1551
+ var DEFAULT_HISTOGRAM_BOUNDS = [
1552
+ 0,
1553
+ 5,
1554
+ 10,
1555
+ 25,
1556
+ 50,
1557
+ 75,
1558
+ 100,
1559
+ 250,
1560
+ 500,
1561
+ 750,
1562
+ 1000,
1563
+ 2500,
1564
+ 5000,
1565
+ 7500,
1566
+ 1e4
1567
+ ];
1568
+ function msToUnixNano(ms) {
1569
+ return String(ms) + "000000";
1570
+ }
1571
+ function seriesKey(type, name, unit, attributes) {
1572
+ let attrsKey = "";
1573
+ if (attributes) {
1574
+ const keys = Object.keys(attributes).sort();
1575
+ attrsKey = keys.map((k) => `${JSON.stringify(k)}:${JSON.stringify(attributes[k])}`).join(",");
1576
+ }
1577
+ return `${type}\x00${name}\x00${unit ?? ""}\x00${attrsKey}`;
1578
+ }
1579
+ function bucketIndexFor(value, bounds) {
1580
+ for (let i = 0;i < bounds.length; i++)
1581
+ if (value <= bounds[i])
1582
+ return i;
1583
+ return bounds.length;
1584
+ }
1585
+ function buildMetricsResourceAttributes(config, scopeName, scopeVersion) {
1586
+ return {
1587
+ ...config.resourceAttributes,
1588
+ "service.name": config.serviceName || "unknown_service",
1589
+ ...config.environment && {
1590
+ "deployment.environment": config.environment
1591
+ },
1592
+ ...config.serviceVersion && {
1593
+ "service.version": config.serviceVersion
1594
+ },
1595
+ "telemetry.sdk.name": scopeName,
1596
+ "telemetry.sdk.version": scopeVersion
1597
+ };
1598
+ }
1599
+ function buildOtlpMetricsPayload(metrics, resourceAttributes, scopeName, scopeVersion) {
1600
+ return {
1601
+ resourceMetrics: [
1602
+ {
1603
+ resource: {
1604
+ attributes: toOtlpKeyValueList(resourceAttributes)
1605
+ },
1606
+ scopeMetrics: [
1607
+ {
1608
+ scope: {
1609
+ name: scopeName,
1610
+ version: scopeVersion
1611
+ },
1612
+ metrics
1613
+ }
1614
+ ]
1615
+ }
1616
+ ]
1617
+ };
1618
+ }
1619
+
1620
+ // ../../../../../node_modules/.bun/@posthog+core@1.48.6/node_modules/@posthog/core/dist/metrics/config.mjs
1621
+ var DEFAULT_FLUSH_INTERVAL_MS = 1e4;
1622
+ var DEFAULT_MAX_SERIES_PER_FLUSH = 1000;
1623
+ function resolveMetricsConfig(config) {
1624
+ const resourceAttributes = config?.resourceAttributes;
1625
+ return {
1626
+ serviceName: resourceAttributes?.["service.name"] ?? config?.serviceName,
1627
+ serviceVersion: resourceAttributes?.["service.version"] ?? config?.serviceVersion,
1628
+ environment: resourceAttributes?.["deployment.environment"] ?? config?.environment,
1629
+ resourceAttributes,
1630
+ beforeSend: config?.beforeSend,
1631
+ flushIntervalMs: config?.flushIntervalMs ?? DEFAULT_FLUSH_INTERVAL_MS,
1632
+ maxSeriesPerFlush: config?.maxSeriesPerFlush ?? DEFAULT_MAX_SERIES_PER_FLUSH
1633
+ };
1634
+ }
1635
+
1636
+ // ../../../../../node_modules/.bun/@posthog+core@1.48.6/node_modules/@posthog/core/dist/metrics/index.mjs
1637
+ var OTLP_TEMPORALITY_DELTA = 1;
1638
+
1639
+ class PostHogMetrics {
1640
+ constructor(_instance, _config, _logger) {
1641
+ this._instance = _instance;
1642
+ this._config = _config;
1643
+ this._logger = _logger;
1644
+ this._series = new Map;
1645
+ this._flushPromise = null;
1646
+ this._seriesCapWarned = false;
1647
+ this._typeByName = new Map;
1648
+ this._typeCollisionWarned = new Set;
1649
+ this._generation = 0;
1650
+ }
1651
+ count(name, value = 1, options) {
1652
+ this._capture({
1653
+ name,
1654
+ type: "count",
1655
+ value,
1656
+ unit: options?.unit,
1657
+ attributes: options?.attributes
1658
+ });
1659
+ }
1660
+ gauge(name, value, options) {
1661
+ this._capture({
1662
+ name,
1663
+ type: "gauge",
1664
+ value,
1665
+ unit: options?.unit,
1666
+ attributes: options?.attributes
1667
+ });
1668
+ }
1669
+ histogram(name, value, options) {
1670
+ this._capture({
1671
+ name,
1672
+ type: "histogram",
1673
+ value,
1674
+ unit: options?.unit,
1675
+ attributes: options?.attributes
1676
+ });
1677
+ }
1678
+ flush() {
1679
+ const prev = this._flushPromise;
1680
+ const run = async () => {
1681
+ if (prev)
1682
+ await prev.catch(() => {});
1683
+ await this._doFlush();
1684
+ };
1685
+ const p = run().finally(() => {
1686
+ if (this._flushPromise === p)
1687
+ this._flushPromise = null;
1688
+ });
1689
+ this._flushPromise = p;
1690
+ return p;
1691
+ }
1692
+ drainWindow() {
1693
+ if (this._series.size === 0)
1694
+ return null;
1695
+ const window = this._series;
1696
+ this._series = new Map;
1697
+ this._seriesCapWarned = false;
1698
+ this._typeByName = new Map;
1699
+ this._typeCollisionWarned = new Set;
1700
+ return this._buildPayload(window);
1701
+ }
1702
+ reset() {
1703
+ this._generation++;
1704
+ this._clearFlushTimer();
1705
+ this._series = new Map;
1706
+ this._flushPromise = null;
1707
+ this._seriesCapWarned = false;
1708
+ this._typeByName = new Map;
1709
+ this._typeCollisionWarned = new Set;
1710
+ }
1711
+ _capture(sample) {
1712
+ if (this._instance.isDisabled || this._instance.optedOut)
1713
+ return;
1714
+ const filtered = this._runBeforeSend(sample);
1715
+ if (filtered === null)
1716
+ return;
1717
+ if (!filtered.name || typeof filtered.name != "string")
1718
+ return void this._logger.warn("Dropping metric with empty name");
1719
+ if (typeof filtered.value != "number" || !Number.isFinite(filtered.value))
1720
+ return void this._logger.warn(`Dropping metric '${filtered.name}': value must be a finite number`);
1721
+ if (filtered.type === "count" && filtered.value < 0)
1722
+ return void this._logger.warn(`Dropping count '${filtered.name}': counters are monotonic, value must be >= 0`);
1723
+ let attributes;
1724
+ let key;
1725
+ try {
1726
+ attributes = filtered.attributes ? {
1727
+ ...filtered.attributes
1728
+ } : undefined;
1729
+ key = seriesKey(filtered.type, filtered.name, filtered.unit, attributes);
1730
+ } catch (e) {
1731
+ this._logger.warn(`Dropping metric '${filtered.name}': attributes could not be serialized`, e);
1732
+ return;
1733
+ }
1734
+ let state = this._series.get(key);
1735
+ if (!state) {
1736
+ if (!this._admitNewSeries())
1737
+ return;
1738
+ state = {
1739
+ name: filtered.name,
1740
+ type: filtered.type,
1741
+ unit: filtered.unit,
1742
+ attributes,
1743
+ windowStartMs: Date.now()
1744
+ };
1745
+ this._series.set(key, state);
1746
+ }
1747
+ const seenType = this._typeByName.get(filtered.name);
1748
+ if (seenType === undefined)
1749
+ this._typeByName.set(filtered.name, filtered.type);
1750
+ else if (seenType !== filtered.type && !this._typeCollisionWarned.has(filtered.name)) {
1751
+ this._typeCollisionWarned.add(filtered.name);
1752
+ this._logger.warn(`Metric name '${filtered.name}' is already used as a ${seenType}; recording it as a ${filtered.type} too will blend both series in charts. Use a distinct name.`);
1753
+ }
1754
+ this._fold(state, filtered.value);
1755
+ this._armFlushTimer();
1756
+ }
1757
+ _admitNewSeries() {
1758
+ if (this._series.size < this._config.maxSeriesPerFlush)
1759
+ return true;
1760
+ if (!this._seriesCapWarned) {
1761
+ this._seriesCapWarned = true;
1762
+ this._logger.warn(`Metric series cap reached (${this._config.maxSeriesPerFlush} per flush window); dropping new series until the next flush. Reduce attribute cardinality.`);
1763
+ }
1764
+ return false;
1765
+ }
1766
+ _fold(state, value) {
1767
+ switch (state.type) {
1768
+ case "count":
1769
+ state.total = (state.total ?? 0) + value;
1770
+ break;
1771
+ case "gauge":
1772
+ state.last = value;
1773
+ break;
1774
+ case "histogram": {
1775
+ if (!state.hist)
1776
+ state.hist = {
1777
+ count: 0,
1778
+ sum: 0,
1779
+ min: value,
1780
+ max: value,
1781
+ bucketCounts: new Array(DEFAULT_HISTOGRAM_BOUNDS.length + 1).fill(0)
1782
+ };
1783
+ const hist = state.hist;
1784
+ hist.count += 1;
1785
+ hist.sum += value;
1786
+ hist.min = Math.min(hist.min, value);
1787
+ hist.max = Math.max(hist.max, value);
1788
+ hist.bucketCounts[bucketIndexFor(value, DEFAULT_HISTOGRAM_BOUNDS)] += 1;
1789
+ break;
1790
+ }
1791
+ }
1792
+ }
1793
+ _runBeforeSend(sample) {
1794
+ const beforeSend = this._config.beforeSend;
1795
+ if (!beforeSend)
1796
+ return sample;
1797
+ const fns = isArray(beforeSend) ? beforeSend : [
1798
+ beforeSend
1799
+ ];
1800
+ let result = sample;
1801
+ for (const fn of fns)
1802
+ try {
1803
+ const next = fn(result);
1804
+ if (!next) {
1805
+ this._logger.info("Metric was rejected in beforeSend function");
1806
+ return null;
1807
+ }
1808
+ result = next;
1809
+ } catch (e) {
1810
+ this._logger.error("Error in beforeSend function for metric:", e);
1811
+ return null;
1812
+ }
1813
+ return result;
1814
+ }
1815
+ _armFlushTimer() {
1816
+ if (this._flushTimer)
1817
+ return;
1818
+ this._flushTimer = safeSetTimeout(() => {
1819
+ this._flushTimer = undefined;
1820
+ this.flush().catch((e) => {
1821
+ this._logger.error("Metrics flush failed:", e);
1822
+ });
1823
+ }, this._config.flushIntervalMs);
1824
+ }
1825
+ _clearFlushTimer() {
1826
+ if (this._flushTimer) {
1827
+ clearTimeout(this._flushTimer);
1828
+ this._flushTimer = undefined;
1829
+ }
1830
+ }
1831
+ async _doFlush() {
1832
+ if (this._series.size === 0)
1833
+ return;
1834
+ const window = this._series;
1835
+ this._series = new Map;
1836
+ this._seriesCapWarned = false;
1837
+ this._typeByName = new Map;
1838
+ this._typeCollisionWarned = new Set;
1839
+ const generation = this._generation;
1840
+ const outcome = await this._instance._sendMetricsBatch(this._buildPayload(window));
1841
+ if (generation !== this._generation)
1842
+ return;
1843
+ switch (outcome.kind) {
1844
+ case "ok":
1845
+ return;
1846
+ case "retry-later":
1847
+ this._mergeWindowBack(window);
1848
+ this._armFlushTimer();
1849
+ return;
1850
+ case "too-large":
1851
+ this._logger.warn("Metrics batch exceeded the server size limit and was dropped");
1852
+ return;
1853
+ case "fatal":
1854
+ this._logger.error("Failed to send metrics batch:", outcome.error);
1855
+ return;
1856
+ }
1857
+ }
1858
+ _buildPayload(window) {
1859
+ return buildOtlpMetricsPayload(this._buildMetrics(window), buildMetricsResourceAttributes(this._config, this._instance.getLibraryId(), this._instance.getLibraryVersion()), this._instance.getLibraryId(), this._instance.getLibraryVersion());
1860
+ }
1861
+ _buildMetrics(window) {
1862
+ const nowNano = msToUnixNano(Date.now());
1863
+ const byMetric = new Map;
1864
+ for (const state of window.values()) {
1865
+ const metricKey = seriesKey(state.type, state.name, state.unit, undefined);
1866
+ let metric = byMetric.get(metricKey);
1867
+ if (!metric) {
1868
+ metric = {
1869
+ name: state.name,
1870
+ ...state.unit && {
1871
+ unit: state.unit
1872
+ }
1873
+ };
1874
+ if (state.type === "count")
1875
+ metric.sum = {
1876
+ aggregationTemporality: OTLP_TEMPORALITY_DELTA,
1877
+ isMonotonic: true,
1878
+ dataPoints: []
1879
+ };
1880
+ else if (state.type === "gauge")
1881
+ metric.gauge = {
1882
+ dataPoints: []
1883
+ };
1884
+ else
1885
+ metric.histogram = {
1886
+ aggregationTemporality: OTLP_TEMPORALITY_DELTA,
1887
+ dataPoints: []
1888
+ };
1889
+ byMetric.set(metricKey, metric);
1890
+ }
1891
+ const attributes = toOtlpKeyValueList(state.attributes ?? {});
1892
+ const startNano = msToUnixNano(state.windowStartMs);
1893
+ if (state.type === "count") {
1894
+ const dp = {
1895
+ attributes,
1896
+ startTimeUnixNano: startNano,
1897
+ timeUnixNano: nowNano,
1898
+ asDouble: state.total ?? 0
1899
+ };
1900
+ metric.sum.dataPoints.push(dp);
1901
+ } else if (state.type === "gauge") {
1902
+ const dp = {
1903
+ attributes,
1904
+ timeUnixNano: nowNano,
1905
+ asDouble: state.last ?? 0
1906
+ };
1907
+ metric.gauge.dataPoints.push(dp);
1908
+ } else if (state.hist) {
1909
+ const dp = {
1910
+ attributes,
1911
+ startTimeUnixNano: startNano,
1912
+ timeUnixNano: nowNano,
1913
+ count: state.hist.count,
1914
+ sum: state.hist.sum,
1915
+ min: state.hist.min,
1916
+ max: state.hist.max,
1917
+ bucketCounts: state.hist.bucketCounts,
1918
+ explicitBounds: DEFAULT_HISTOGRAM_BOUNDS
1919
+ };
1920
+ metric.histogram.dataPoints.push(dp);
1921
+ }
1922
+ }
1923
+ return Array.from(byMetric.values());
1924
+ }
1925
+ _mergeWindowBack(window) {
1926
+ for (const [key, old] of window) {
1927
+ const current = this._series.get(key);
1928
+ if (!current) {
1929
+ if (this._admitNewSeries())
1930
+ this._series.set(key, old);
1931
+ continue;
1932
+ }
1933
+ current.windowStartMs = Math.min(current.windowStartMs, old.windowStartMs);
1934
+ switch (current.type) {
1935
+ case "count":
1936
+ current.total = (current.total ?? 0) + (old.total ?? 0);
1937
+ break;
1938
+ case "gauge":
1939
+ break;
1940
+ case "histogram":
1941
+ if (old.hist)
1942
+ if (current.hist) {
1943
+ current.hist.count += old.hist.count;
1944
+ current.hist.sum += old.hist.sum;
1945
+ current.hist.min = Math.min(current.hist.min, old.hist.min);
1946
+ current.hist.max = Math.max(current.hist.max, old.hist.max);
1947
+ for (let i = 0;i < current.hist.bucketCounts.length; i++)
1948
+ current.hist.bucketCounts[i] += old.hist.bucketCounts[i];
1949
+ } else
1950
+ current.hist = old.hist;
1951
+ break;
1952
+ }
1953
+ }
1954
+ }
1955
+ }
1956
+ // ../../../../../node_modules/.bun/@posthog+core@1.48.6/node_modules/@posthog/core/dist/eventemitter.mjs
1345
1957
  class SimpleEventEmitter {
1346
1958
  constructor() {
1347
1959
  this.events = {};
@@ -1363,7 +1975,7 @@ class SimpleEventEmitter {
1363
1975
  }
1364
1976
  }
1365
1977
 
1366
- // ../../../../../node_modules/.bun/@posthog+core@1.30.3/node_modules/@posthog/core/dist/error-tracking/index.mjs
1978
+ // ../../../../../node_modules/.bun/@posthog+core@1.48.6/node_modules/@posthog/core/dist/error-tracking/index.mjs
1367
1979
  var exports_error_tracking = {};
1368
1980
  __export(exports_error_tracking, {
1369
1981
  winjsStackLineParser: () => winjsStackLineParser,
@@ -1374,6 +1986,7 @@ __export(exports_error_tracking, {
1374
1986
  opera10StackLineParser: () => opera10StackLineParser,
1375
1987
  nodeStackLineParser: () => nodeStackLineParser,
1376
1988
  getUtf8ByteLength: () => getUtf8ByteLength,
1989
+ getInjectedReleaseId: () => getInjectedReleaseId,
1377
1990
  geckoStackLineParser: () => geckoStackLineParser,
1378
1991
  createStackParser: () => createStackParser,
1379
1992
  createDefaultStackParser: () => createDefaultStackParser,
@@ -1393,7 +2006,7 @@ __export(exports_error_tracking, {
1393
2006
  DEFAULT_EXCEPTION_STEPS_CONFIG: () => DEFAULT_EXCEPTION_STEPS_CONFIG
1394
2007
  });
1395
2008
 
1396
- // ../../../../../node_modules/.bun/@posthog+core@1.30.3/node_modules/@posthog/core/dist/error-tracking/chunk-ids.mjs
2009
+ // ../../../../../node_modules/.bun/@posthog+core@1.48.6/node_modules/@posthog/core/dist/error-tracking/chunk-ids.mjs
1397
2010
  var parsedStackResults;
1398
2011
  var lastKeysCount;
1399
2012
  var cachedFilenameChunkIds;
@@ -1432,7 +2045,7 @@ function getFilenameToChunkIdMap(stackParser) {
1432
2045
  return cachedFilenameChunkIds;
1433
2046
  }
1434
2047
 
1435
- // ../../../../../node_modules/.bun/@posthog+core@1.30.3/node_modules/@posthog/core/dist/error-tracking/error-properties-builder.mjs
2048
+ // ../../../../../node_modules/.bun/@posthog+core@1.48.6/node_modules/@posthog/core/dist/error-tracking/error-properties-builder.mjs
1436
2049
  var MAX_CAUSE_RECURSION = 4;
1437
2050
 
1438
2051
  class ErrorPropertiesBuilder {
@@ -1554,14 +2167,16 @@ class ErrorPropertiesBuilder {
1554
2167
  return context;
1555
2168
  }
1556
2169
  }
1557
- // ../../../../../node_modules/.bun/@posthog+core@1.30.3/node_modules/@posthog/core/dist/error-tracking/parsers/base.mjs
2170
+ // ../../../../../node_modules/.bun/@posthog+core@1.48.6/node_modules/@posthog/core/dist/error-tracking/parsers/base.mjs
1558
2171
  var UNKNOWN_FUNCTION = "?";
2172
+ var MASKED_URL_PREFIX = "webkit-masked-url://";
2173
+ var ANONYMOUS_FILENAME = "<anonymous>";
1559
2174
  function createFrame(platform, filename, func, lineno, colno) {
1560
2175
  const frame = {
1561
2176
  platform,
1562
2177
  filename,
1563
2178
  function: func === "<anonymous>" ? UNKNOWN_FUNCTION : func,
1564
- in_app: true
2179
+ in_app: !filename?.startsWith(MASKED_URL_PREFIX) && filename !== ANONYMOUS_FILENAME
1565
2180
  };
1566
2181
  if (!isUndefined(lineno))
1567
2182
  frame.lineno = lineno;
@@ -1570,7 +2185,7 @@ function createFrame(platform, filename, func, lineno, colno) {
1570
2185
  return frame;
1571
2186
  }
1572
2187
 
1573
- // ../../../../../node_modules/.bun/@posthog+core@1.30.3/node_modules/@posthog/core/dist/error-tracking/parsers/safari.mjs
2188
+ // ../../../../../node_modules/.bun/@posthog+core@1.48.6/node_modules/@posthog/core/dist/error-tracking/parsers/safari.mjs
1574
2189
  var extractSafariExtensionDetails = (func, filename) => {
1575
2190
  const isSafariExtension = func.indexOf("safari-extension") !== -1;
1576
2191
  const isSafariWebExtension = func.indexOf("safari-web-extension") !== -1;
@@ -1583,7 +2198,7 @@ var extractSafariExtensionDetails = (func, filename) => {
1583
2198
  ];
1584
2199
  };
1585
2200
 
1586
- // ../../../../../node_modules/.bun/@posthog+core@1.30.3/node_modules/@posthog/core/dist/error-tracking/parsers/chrome.mjs
2201
+ // ../../../../../node_modules/.bun/@posthog+core@1.48.6/node_modules/@posthog/core/dist/error-tracking/parsers/chrome.mjs
1587
2202
  var chromeRegexNoFnName = /^\s*at (\S+?)(?::(\d+))(?::(\d+))\s*$/i;
1588
2203
  var chromeRegex = /^\s*at (?:(.+?\)(?: \[.+\])?|.*?) ?\((?:address at )?)?(?:async )?((?:<anonymous>|[-a-z]+:|.*bundle|\/)?.*?)(?::(\d+))?(?::(\d+))?\)?\s*$/i;
1589
2204
  var chromeEvalRegex = /\((\S*)(?::(\d+))(?::(\d+))\)/;
@@ -1609,7 +2224,7 @@ var chromeStackLineParser = (line, platform) => {
1609
2224
  }
1610
2225
  };
1611
2226
 
1612
- // ../../../../../node_modules/.bun/@posthog+core@1.30.3/node_modules/@posthog/core/dist/error-tracking/parsers/gecko.mjs
2227
+ // ../../../../../node_modules/.bun/@posthog+core@1.48.6/node_modules/@posthog/core/dist/error-tracking/parsers/gecko.mjs
1613
2228
  var geckoREgex = /^\s*(.*?)(?:\((.*?)\))?(?:^|@)?((?:[-a-z]+)?:\/.*?|\[native code\]|[^@]*(?:bundle|\d+\.js)|\/[\w\-. /=]+)(?::(\d+))?(?::(\d+))?\s*$/i;
1614
2229
  var geckoEvalRegex = /(\S+) line (\d+)(?: > eval line \d+)* > eval/i;
1615
2230
  var geckoStackLineParser = (line, platform) => {
@@ -1632,14 +2247,14 @@ var geckoStackLineParser = (line, platform) => {
1632
2247
  }
1633
2248
  };
1634
2249
 
1635
- // ../../../../../node_modules/.bun/@posthog+core@1.30.3/node_modules/@posthog/core/dist/error-tracking/parsers/winjs.mjs
2250
+ // ../../../../../node_modules/.bun/@posthog+core@1.48.6/node_modules/@posthog/core/dist/error-tracking/parsers/winjs.mjs
1636
2251
  var winjsRegex = /^\s*at (?:((?:\[object object\])?.+) )?\(?((?:[-a-z]+):.*?):(\d+)(?::(\d+))?\)?\s*$/i;
1637
2252
  var winjsStackLineParser = (line, platform) => {
1638
2253
  const parts = winjsRegex.exec(line);
1639
2254
  return parts ? createFrame(platform, parts[2], parts[1] || UNKNOWN_FUNCTION, +parts[3], parts[4] ? +parts[4] : undefined) : undefined;
1640
2255
  };
1641
2256
 
1642
- // ../../../../../node_modules/.bun/@posthog+core@1.30.3/node_modules/@posthog/core/dist/error-tracking/parsers/opera.mjs
2257
+ // ../../../../../node_modules/.bun/@posthog+core@1.48.6/node_modules/@posthog/core/dist/error-tracking/parsers/opera.mjs
1643
2258
  var opera10Regex = / line (\d+).*script (?:in )?(\S+)(?:: in function (\S+))?$/i;
1644
2259
  var opera10StackLineParser = (line, platform) => {
1645
2260
  const parts = opera10Regex.exec(line);
@@ -1651,9 +2266,12 @@ var opera11StackLineParser = (line, platform) => {
1651
2266
  return parts ? createFrame(platform, parts[5], parts[3] || parts[4] || UNKNOWN_FUNCTION, +parts[1], +parts[2]) : undefined;
1652
2267
  };
1653
2268
 
1654
- // ../../../../../node_modules/.bun/@posthog+core@1.30.3/node_modules/@posthog/core/dist/error-tracking/parsers/node.mjs
2269
+ // ../../../../../node_modules/.bun/@posthog+core@1.48.6/node_modules/@posthog/core/dist/error-tracking/parsers/node.mjs
1655
2270
  var FILENAME_MATCH = /^\s*[-]{4,}$/;
1656
2271
  var FULL_MATCH = /at (?:async )?(?:(.+?)\s+\()?(?:(.+):(\d+):(\d+)?|([^)]+))\)?/;
2272
+ var PROMISE_COMBINATOR = /^Promise\.(?:all|any)$/;
2273
+ var PROMISE_INDEX = /^index \d+$/;
2274
+ var PROMISE_FRAME_FILENAME = "node:internal/promise";
1657
2275
  var nodeStackLineParser = (line, platform) => {
1658
2276
  const lineMatch = line.match(FULL_MATCH);
1659
2277
  if (lineMatch) {
@@ -1696,6 +2314,8 @@ var nodeStackLineParser = (line, platform) => {
1696
2314
  filename = filename.slice(1);
1697
2315
  if (!filename && lineMatch[5] && !isNative)
1698
2316
  filename = lineMatch[5];
2317
+ if (PROMISE_COMBINATOR.test(functionName) && PROMISE_INDEX.test(filename || ""))
2318
+ filename = PROMISE_FRAME_FILENAME;
1699
2319
  return {
1700
2320
  filename: filename ? decodeURI(filename) : undefined,
1701
2321
  module: undefined,
@@ -1720,7 +2340,7 @@ function _parseIntOrUndefined(input) {
1720
2340
  return parseInt(input || "", 10) || undefined;
1721
2341
  }
1722
2342
 
1723
- // ../../../../../node_modules/.bun/@posthog+core@1.30.3/node_modules/@posthog/core/dist/error-tracking/parsers/index.mjs
2343
+ // ../../../../../node_modules/.bun/@posthog+core@1.48.6/node_modules/@posthog/core/dist/error-tracking/parsers/index.mjs
1724
2344
  var WEBPACK_ERROR_REGEXP = /\(error: (.*)\)/;
1725
2345
  var STACKTRACE_FRAME_LIMIT = 50;
1726
2346
  function reverseAndStripFrames(stack) {
@@ -1765,7 +2385,7 @@ function createStackParser(platform, ...parsers) {
1765
2385
  return reverseAndStripFrames(frames);
1766
2386
  };
1767
2387
  }
1768
- // ../../../../../node_modules/.bun/@posthog+core@1.30.3/node_modules/@posthog/core/dist/error-tracking/coercers/dom-exception-coercer.mjs
2388
+ // ../../../../../node_modules/.bun/@posthog+core@1.48.6/node_modules/@posthog/core/dist/error-tracking/coercers/dom-exception-coercer.mjs
1769
2389
  class DOMExceptionCoercer {
1770
2390
  match(err) {
1771
2391
  return this.isDOMException(err) || this.isDOMError(err);
@@ -1795,18 +2415,20 @@ class DOMExceptionCoercer {
1795
2415
  return isBuiltin(err, "DOMError");
1796
2416
  }
1797
2417
  }
1798
- // ../../../../../node_modules/.bun/@posthog+core@1.30.3/node_modules/@posthog/core/dist/error-tracking/coercers/error-coercer.mjs
2418
+ // ../../../../../node_modules/.bun/@posthog+core@1.48.6/node_modules/@posthog/core/dist/error-tracking/coercers/error-coercer.mjs
1799
2419
  class ErrorCoercer {
1800
2420
  match(err) {
1801
- return isPlainError(err);
2421
+ return isError(err);
1802
2422
  }
1803
2423
  coerce(err, ctx) {
2424
+ const stack = this.getStack(err);
2425
+ const synthetic = stack === undefined;
1804
2426
  return {
1805
2427
  type: this.getType(err),
1806
2428
  value: this.getMessage(err, ctx),
1807
- stack: this.getStack(err),
2429
+ stack: stack ?? ctx.syntheticException?.stack,
1808
2430
  cause: err.cause ? ctx.next(err.cause) : undefined,
1809
- synthetic: false
2431
+ synthetic
1810
2432
  };
1811
2433
  }
1812
2434
  getType(err) {
@@ -1822,25 +2444,41 @@ class ErrorCoercer {
1822
2444
  return err.stacktrace || err.stack || undefined;
1823
2445
  }
1824
2446
  }
1825
- // ../../../../../node_modules/.bun/@posthog+core@1.30.3/node_modules/@posthog/core/dist/error-tracking/coercers/error-event-coercer.mjs
2447
+ // ../../../../../node_modules/.bun/@posthog+core@1.48.6/node_modules/@posthog/core/dist/error-tracking/coercers/error-event-coercer.mjs
1826
2448
  class ErrorEventCoercer {
1827
2449
  constructor() {}
1828
2450
  match(err) {
1829
- return isErrorEvent(err) && err.error != null;
2451
+ if (!isErrorEvent(err))
2452
+ return false;
2453
+ const errorEvent = err;
2454
+ return errorEvent.error != null || this._hasUsableMessage(errorEvent);
1830
2455
  }
1831
2456
  coerce(err, ctx) {
1832
- const exceptionLike = ctx.apply(err.error);
1833
- if (!exceptionLike)
1834
- return {
1835
- type: "ErrorEvent",
1836
- value: err.message,
1837
- stack: ctx.syntheticException?.stack,
1838
- synthetic: true
1839
- };
1840
- return exceptionLike;
2457
+ if (err.error != null)
2458
+ return ctx.apply(err.error);
2459
+ const exceptionLike = ctx.apply(err.message);
2460
+ return {
2461
+ ...exceptionLike,
2462
+ stack: this._buildLocationStack(err) ?? exceptionLike.stack,
2463
+ synthetic: true
2464
+ };
2465
+ }
2466
+ _hasUsableMessage(err) {
2467
+ return isString(err.message) && err.message.length > 0;
2468
+ }
2469
+ _buildLocationStack(err) {
2470
+ const location = err;
2471
+ const lineno = location.lineno ?? 0;
2472
+ const colno = location.colno ?? 0;
2473
+ if (!isString(location.filename) || location.filename.length === 0)
2474
+ return;
2475
+ if (lineno === 0)
2476
+ return;
2477
+ return `Error
2478
+ at ${location.filename}:${lineno}:${colno}`;
1841
2479
  }
1842
2480
  }
1843
- // ../../../../../node_modules/.bun/@posthog+core@1.30.3/node_modules/@posthog/core/dist/error-tracking/coercers/string-coercer.mjs
2481
+ // ../../../../../node_modules/.bun/@posthog+core@1.48.6/node_modules/@posthog/core/dist/error-tracking/coercers/string-coercer.mjs
1844
2482
  var ERROR_TYPES_PATTERN = /^(?:[Uu]ncaught (?:exception: )?)?(?:((?:Eval|Internal|Range|Reference|Syntax|Type|URI|)Error): )?(.*)$/i;
1845
2483
 
1846
2484
  class StringCoercer {
@@ -1870,7 +2508,7 @@ class StringCoercer {
1870
2508
  ];
1871
2509
  }
1872
2510
  }
1873
- // ../../../../../node_modules/.bun/@posthog+core@1.30.3/node_modules/@posthog/core/dist/error-tracking/types.mjs
2511
+ // ../../../../../node_modules/.bun/@posthog+core@1.48.6/node_modules/@posthog/core/dist/error-tracking/types.mjs
1874
2512
  var severityLevels = [
1875
2513
  "fatal",
1876
2514
  "error",
@@ -1880,7 +2518,7 @@ var severityLevels = [
1880
2518
  "debug"
1881
2519
  ];
1882
2520
 
1883
- // ../../../../../node_modules/.bun/@posthog+core@1.30.3/node_modules/@posthog/core/dist/error-tracking/coercers/utils.mjs
2521
+ // ../../../../../node_modules/.bun/@posthog+core@1.48.6/node_modules/@posthog/core/dist/error-tracking/coercers/utils.mjs
1884
2522
  function extractExceptionKeysForMessage(err, maxLength = 40) {
1885
2523
  const keys = Object.keys(err);
1886
2524
  keys.sort();
@@ -1897,7 +2535,7 @@ function extractExceptionKeysForMessage(err, maxLength = 40) {
1897
2535
  return "";
1898
2536
  }
1899
2537
 
1900
- // ../../../../../node_modules/.bun/@posthog+core@1.30.3/node_modules/@posthog/core/dist/error-tracking/coercers/object-coercer.mjs
2538
+ // ../../../../../node_modules/.bun/@posthog+core@1.48.6/node_modules/@posthog/core/dist/error-tracking/coercers/object-coercer.mjs
1901
2539
  class ObjectCoercer {
1902
2540
  match(candidate) {
1903
2541
  return typeof candidate == "object" && candidate !== null;
@@ -1909,13 +2547,16 @@ class ObjectCoercer {
1909
2547
  return {
1910
2548
  type: this.getType(candidate),
1911
2549
  value: this.getValue(candidate),
1912
- stack: ctx.syntheticException?.stack,
2550
+ stack: this.getStack(candidate) ?? ctx.syntheticException?.stack,
1913
2551
  level: this.isSeverityLevel(candidate.level) ? candidate.level : "error",
1914
2552
  synthetic: true
1915
2553
  };
1916
2554
  }
1917
2555
  getType(err) {
1918
- return isEvent(err) ? err.constructor.name : "Error";
2556
+ if (isEvent(err))
2557
+ return err.constructor.name;
2558
+ const name = "name" in err ? err.name : undefined;
2559
+ return isString(name) && !isEmptyString(name) ? name : "Error";
1919
2560
  }
1920
2561
  getValue(err) {
1921
2562
  if ("name" in err && typeof err.name == "string") {
@@ -1933,6 +2574,15 @@ class ObjectCoercer {
1933
2574
  isSeverityLevel(x) {
1934
2575
  return isString(x) && !isEmptyString(x) && severityLevels.indexOf(x) >= 0;
1935
2576
  }
2577
+ getStack(candidate) {
2578
+ try {
2579
+ if (isString(candidate.stacktrace) && candidate.stacktrace.length > 0)
2580
+ return candidate.stacktrace;
2581
+ return isString(candidate.stack) && candidate.stack.length > 0 ? candidate.stack : undefined;
2582
+ } catch {
2583
+ return;
2584
+ }
2585
+ }
1936
2586
  getErrorPropertyFromObject(obj) {
1937
2587
  for (const prop in obj)
1938
2588
  if (Object.prototype.hasOwnProperty.call(obj, prop)) {
@@ -1950,7 +2600,7 @@ class ObjectCoercer {
1950
2600
  }
1951
2601
  }
1952
2602
  }
1953
- // ../../../../../node_modules/.bun/@posthog+core@1.30.3/node_modules/@posthog/core/dist/error-tracking/coercers/event-coercer.mjs
2603
+ // ../../../../../node_modules/.bun/@posthog+core@1.48.6/node_modules/@posthog/core/dist/error-tracking/coercers/event-coercer.mjs
1954
2604
  class EventCoercer {
1955
2605
  match(err) {
1956
2606
  return isEvent(err);
@@ -1965,7 +2615,7 @@ class EventCoercer {
1965
2615
  };
1966
2616
  }
1967
2617
  }
1968
- // ../../../../../node_modules/.bun/@posthog+core@1.30.3/node_modules/@posthog/core/dist/error-tracking/coercers/primitive-coercer.mjs
2618
+ // ../../../../../node_modules/.bun/@posthog+core@1.48.6/node_modules/@posthog/core/dist/error-tracking/coercers/primitive-coercer.mjs
1969
2619
  class PrimitiveCoercer {
1970
2620
  match(candidate) {
1971
2621
  return isPrimitive(candidate);
@@ -1979,7 +2629,7 @@ class PrimitiveCoercer {
1979
2629
  };
1980
2630
  }
1981
2631
  }
1982
- // ../../../../../node_modules/.bun/@posthog+core@1.30.3/node_modules/@posthog/core/dist/error-tracking/coercers/promise-rejection-event.mjs
2632
+ // ../../../../../node_modules/.bun/@posthog+core@1.48.6/node_modules/@posthog/core/dist/error-tracking/coercers/promise-rejection-event.mjs
1983
2633
  class PromiseRejectionEventCoercer {
1984
2634
  match(err) {
1985
2635
  return isBuiltin(err, "PromiseRejectionEvent") || this.isCustomEventWrappingRejection(err);
@@ -2015,7 +2665,7 @@ class PromiseRejectionEventCoercer {
2015
2665
  return error;
2016
2666
  }
2017
2667
  }
2018
- // ../../../../../node_modules/.bun/@posthog+core@1.30.3/node_modules/@posthog/core/dist/error-tracking/utils.mjs
2668
+ // ../../../../../node_modules/.bun/@posthog+core@1.48.6/node_modules/@posthog/core/dist/error-tracking/utils.mjs
2019
2669
  class ReduceableCache {
2020
2670
  constructor(_maxSize) {
2021
2671
  this._maxSize = _maxSize;
@@ -2040,7 +2690,7 @@ class ReduceableCache {
2040
2690
  }
2041
2691
  }
2042
2692
  }
2043
- // ../../../../../node_modules/.bun/@posthog+core@1.30.3/node_modules/@posthog/core/dist/error-tracking/exception-steps.mjs
2693
+ // ../../../../../node_modules/.bun/@posthog+core@1.48.6/node_modules/@posthog/core/dist/error-tracking/exception-steps.mjs
2044
2694
  var EXCEPTION_STEP_INTERNAL_FIELDS = {
2045
2695
  MESSAGE: "$message",
2046
2696
  TIMESTAMP: "$timestamp"
@@ -2135,9 +2785,12 @@ function normalizePositiveInteger(input, fallback) {
2135
2785
  return normalized;
2136
2786
  }
2137
2787
  function normalizeAndSerializeStep(step) {
2138
- const json = safeStringify(step);
2139
- if (!json)
2788
+ let json;
2789
+ try {
2790
+ json = safeJsonStringify(step);
2791
+ } catch {
2140
2792
  return;
2793
+ }
2141
2794
  try {
2142
2795
  const parsed = JSON.parse(json);
2143
2796
  if (!isObject(parsed))
@@ -2157,33 +2810,6 @@ function normalizeAndSerializeStep(step) {
2157
2810
  return;
2158
2811
  }
2159
2812
  }
2160
- function safeStringify(value) {
2161
- const seen = new WeakSet;
2162
- try {
2163
- return JSON.stringify(value, (_key, replacementValue) => {
2164
- if (typeof replacementValue == "bigint")
2165
- return replacementValue.toString();
2166
- if (typeof replacementValue == "function" || typeof replacementValue == "symbol")
2167
- return;
2168
- if (replacementValue instanceof Date)
2169
- return replacementValue.toISOString();
2170
- if (replacementValue instanceof Error)
2171
- return {
2172
- name: replacementValue.name,
2173
- message: replacementValue.message,
2174
- stack: replacementValue.stack
2175
- };
2176
- if (replacementValue && typeof replacementValue == "object") {
2177
- if (seen.has(replacementValue))
2178
- return "[Circular]";
2179
- seen.add(replacementValue);
2180
- }
2181
- return replacementValue;
2182
- });
2183
- } catch {
2184
- return;
2185
- }
2186
- }
2187
2813
  function getUtf8ByteLength(value) {
2188
2814
  if (typeof TextEncoder != "undefined")
2189
2815
  return new TextEncoder().encode(value).length;
@@ -2197,19 +2823,65 @@ function getUtf8ByteLength(value) {
2197
2823
  byteLength += 1;
2198
2824
  return byteLength;
2199
2825
  }
2200
- // ../../../../../node_modules/.bun/@posthog+core@1.30.3/node_modules/@posthog/core/dist/posthog-core-stateless.mjs
2826
+ // ../../../../../node_modules/.bun/@posthog+core@1.48.6/node_modules/@posthog/core/dist/error-tracking/release.mjs
2827
+ function getInjectedReleaseId() {
2828
+ const injected = globalThis._posthogReleaseId;
2829
+ return typeof injected == "string" && injected.length > 0 ? injected : undefined;
2830
+ }
2831
+ // ../../../../../node_modules/.bun/@posthog+core@1.48.6/node_modules/@posthog/core/dist/posthog-core-stateless.mjs
2201
2832
  class PostHogFetchHttpError extends Error {
2202
- constructor(response, reqByteLength) {
2203
- super("HTTP error while fetching PostHog: status=" + response.status + ", reqByteLength=" + reqByteLength), this.response = response, this.reqByteLength = reqByteLength, this.name = "PostHogFetchHttpError";
2833
+ constructor(response, reqByteLength, responseBodyDeadline, abortController) {
2834
+ super("HTTP error while fetching PostHog: status=" + response.status + ", reqByteLength=" + reqByteLength), this.response = response, this.reqByteLength = reqByteLength, this.responseBodyDeadline = responseBodyDeadline, this.abortController = abortController, this.name = "PostHogFetchHttpError", this._bodyReadTimedOut = false;
2204
2835
  }
2205
2836
  get status() {
2206
2837
  return this.response.status;
2207
2838
  }
2839
+ get bodyReadTimedOut() {
2840
+ return this._bodyReadTimedOut;
2841
+ }
2208
2842
  get text() {
2209
- return this.response.text();
2843
+ if (!this.responseBodyTextPromise)
2844
+ if (Date.now() >= this.responseBodyDeadline) {
2845
+ this._bodyReadTimedOut = true;
2846
+ const timeoutError = new Error("Response body read timed out");
2847
+ timeoutError.name = "AbortError";
2848
+ this.cancelResponseBody(timeoutError);
2849
+ this.responseBodyTextPromise = Promise.reject(timeoutError);
2850
+ } else {
2851
+ const responseBodyTimeout = new Promise((_resolve, reject) => {
2852
+ this.responseBodyTimer = safeSetTimeout(() => {
2853
+ this._bodyReadTimedOut = true;
2854
+ const timeoutError = new Error("Response body read timed out");
2855
+ timeoutError.name = "AbortError";
2856
+ reject(timeoutError);
2857
+ this.cancelResponseBody(timeoutError);
2858
+ }, this.responseBodyDeadline - Date.now());
2859
+ });
2860
+ let responseBodyText;
2861
+ try {
2862
+ responseBodyText = Promise.resolve(this.response.text());
2863
+ } catch (error) {
2864
+ responseBodyText = Promise.reject(error);
2865
+ }
2866
+ this.responseBodyTextPromise = Promise.race([
2867
+ responseBodyText,
2868
+ responseBodyTimeout
2869
+ ]).finally(() => clearTimeout(this.responseBodyTimer));
2870
+ }
2871
+ return this.responseBodyTextPromise;
2210
2872
  }
2211
2873
  get json() {
2212
- return this.response.json();
2874
+ return this.text.then((text) => JSON.parse(text));
2875
+ }
2876
+ cancelResponseBody(reason) {
2877
+ clearTimeout(this.responseBodyTimer);
2878
+ if (!this.abortController.signal.aborted)
2879
+ this.abortController.abort(reason);
2880
+ (async () => {
2881
+ try {
2882
+ await this.response.body?.cancel();
2883
+ } catch {}
2884
+ })();
2213
2885
  }
2214
2886
  }
2215
2887
 
@@ -2220,12 +2892,20 @@ class PostHogFetchNetworkError extends Error {
2220
2892
  } : {}), this.error = error, this.name = "PostHogFetchNetworkError";
2221
2893
  }
2222
2894
  }
2895
+ var applyCallerFeatureFlagOverrides = (target, callerProperties) => {
2896
+ for (const key of Object.keys(callerProperties))
2897
+ if (key.startsWith("$feature/") || key === "$active_feature_flags")
2898
+ target[key] = callerProperties[key];
2899
+ };
2223
2900
  async function logFlushError(err) {
2224
2901
  if (err instanceof PostHogFetchHttpError) {
2225
2902
  let text = "";
2226
2903
  try {
2227
2904
  text = await err.text;
2228
- } catch {}
2905
+ } catch {
2906
+ if (err.bodyReadTimedOut)
2907
+ text = "<response body read timed out>";
2908
+ }
2229
2909
  console.error(`Error while flushing PostHog: message=${err.message}, response body=${text}`, err);
2230
2910
  } else
2231
2911
  console.error("Error while flushing PostHog", err);
@@ -2237,9 +2917,28 @@ function isPostHogFetchError(err) {
2237
2917
  function isPostHogFetchNetworkError(err) {
2238
2918
  return err instanceof PostHogFetchNetworkError;
2239
2919
  }
2920
+ function isRetryableFlagsFetchError(err) {
2921
+ if (err instanceof PostHogFetchHttpError)
2922
+ return err.status === 502 || err.status === 504;
2923
+ if (!(err instanceof PostHogFetchNetworkError))
2924
+ return false;
2925
+ const cause = err.error;
2926
+ const code = cause?.code ?? cause?.cause?.code;
2927
+ return code !== "ECONNREFUSED";
2928
+ }
2240
2929
  function isPostHogFetchContentTooLargeError(err) {
2241
2930
  return typeof err == "object" && err instanceof PostHogFetchHttpError && err.status === 413;
2242
2931
  }
2932
+ function isPostHogFetchRetryableError(err) {
2933
+ if (err instanceof PostHogFetchHttpError)
2934
+ return err.status === 408 || err.status === 429 || err.status >= 500;
2935
+ return isPostHogFetchNetworkError(err);
2936
+ }
2937
+ function isPostHogEventProperties(value) {
2938
+ return value !== null && typeof value == "object" && !Array.isArray(value);
2939
+ }
2940
+ var DEFAULT_QUEUE_ROUTE = "default";
2941
+
2243
2942
  class PostHogCoreStateless {
2244
2943
  getErrorPropertiesBuilder() {
2245
2944
  if (!this._errorPropertiesBuilder)
@@ -2256,6 +2955,9 @@ class PostHogCoreStateless {
2256
2955
  }
2257
2956
  constructor(apiKey, options = {}) {
2258
2957
  this.flushPromise = null;
2958
+ this.pendingFlushPromise = null;
2959
+ this.flushPromises = new Set;
2960
+ this._dequeuedMessagesCount = 0;
2259
2961
  this.shutdownPromise = null;
2260
2962
  this.promiseQueue = new PromiseQueue;
2261
2963
  this._events = new SimpleEventEmitter;
@@ -2278,10 +2980,11 @@ class PostHogCoreStateless {
2278
2980
  this._retryOptions = {
2279
2981
  retryCount: options.fetchRetryCount ?? 3,
2280
2982
  retryDelay: options.fetchRetryDelay ?? 3000,
2281
- retryCheck: isPostHogFetchError
2983
+ retryCheck: isPostHogFetchRetryableError
2282
2984
  };
2283
2985
  this.requestTimeout = options.requestTimeout ?? 1e4;
2284
2986
  this.featureFlagsRequestTimeoutMs = options.featureFlagsRequestTimeoutMs ?? 3000;
2987
+ this.featureFlagsRequestMaxRetries = options.featureFlagsRequestMaxRetries ?? 1;
2285
2988
  this.remoteConfigRequestTimeoutMs = options.remoteConfigRequestTimeoutMs ?? 3000;
2286
2989
  this.disableGeoip = options.disableGeoip ?? true;
2287
2990
  this.disabled = (options.disabled ?? false) || missingApiKey;
@@ -2343,15 +3046,23 @@ class PostHogCoreStateless {
2343
3046
  return this.disabled;
2344
3047
  }
2345
3048
  buildPayload(payload) {
3049
+ const userProperties = payload.properties || {};
3050
+ let properties = {
3051
+ ...userProperties,
3052
+ ...this.getCommonEventProperties()
3053
+ };
3054
+ applyCallerFeatureFlagOverrides(properties, userProperties);
3055
+ if (payload.event === "$feature_flag_called" && properties.$feature_flag_has_experiment === false && this.isMinimalFlagCalledEventsEnabled())
3056
+ properties = minimizeFlagCalledEventProperties(properties);
2346
3057
  return {
2347
3058
  distinct_id: payload.distinct_id,
2348
3059
  event: payload.event,
2349
- properties: {
2350
- ...payload.properties || {},
2351
- ...this.getCommonEventProperties()
2352
- }
3060
+ properties
2353
3061
  };
2354
3062
  }
3063
+ isMinimalFlagCalledEventsEnabled() {
3064
+ return false;
3065
+ }
2355
3066
  addPendingPromise(promise) {
2356
3067
  return this.promiseQueue.add(promise);
2357
3068
  }
@@ -2436,6 +3147,19 @@ class PostHogCoreStateless {
2436
3147
  this.enqueue("capture", payload, options);
2437
3148
  });
2438
3149
  }
3150
+ async groupIdentifyStatelessImmediate(groupType, groupKey, groupProperties, options, distinctId, eventProperties) {
3151
+ const payload = this.buildPayload({
3152
+ distinct_id: distinctId || `$${groupType}_${groupKey}`,
3153
+ event: "$groupidentify",
3154
+ properties: {
3155
+ $group_type: groupType,
3156
+ $group_key: groupKey,
3157
+ $group_set: groupProperties || {},
3158
+ ...eventProperties || {}
3159
+ }
3160
+ });
3161
+ await this.sendImmediate("capture", payload, options);
3162
+ }
2439
3163
  async getRemoteConfig() {
2440
3164
  await this._initPromise;
2441
3165
  let host = this.host;
@@ -2452,8 +3176,11 @@ class PostHogCoreStateless {
2452
3176
  }
2453
3177
  };
2454
3178
  return this.fetchWithRetry(url, fetchOptions, {
3179
+ type: "required",
3180
+ consume: (response) => response.json()
3181
+ }, {
2455
3182
  retryCount: 0
2456
- }, this.remoteConfigRequestTimeoutMs).then((response) => response.json()).catch((error) => {
3183
+ }, this.remoteConfigRequestTimeoutMs).catch((error) => {
2457
3184
  this._logger.error("Remote config could not be loaded", error);
2458
3185
  this._events.emit("error", error);
2459
3186
  });
@@ -2484,8 +3211,12 @@ class PostHogCoreStateless {
2484
3211
  };
2485
3212
  this._logger.info("Flags URL", url);
2486
3213
  return this.fetchWithRetry(url, fetchOptions, {
2487
- retryCount: 0
2488
- }, this.featureFlagsRequestTimeoutMs).then((response) => response.json()).then((response) => ({
3214
+ type: "required",
3215
+ consume: (response) => response.json()
3216
+ }, {
3217
+ retryCount: this.featureFlagsRequestMaxRetries,
3218
+ retryCheck: isRetryableFlagsFetchError
3219
+ }, this.featureFlagsRequestTimeoutMs).then((response) => ({
2489
3220
  success: true,
2490
3221
  response: normalizeFlagsResponse(response)
2491
3222
  })).catch((error) => {
@@ -2585,9 +3316,9 @@ class PostHogCoreStateless {
2585
3316
  }
2586
3317
  async getFeatureFlagDetailsStateless(distinctId, groups = {}, personProperties = {}, groupProperties = {}, disableGeoip, flagKeysToEvaluate) {
2587
3318
  await this._initPromise;
2588
- const extraPayload = {};
2589
- if (disableGeoip ?? this.disableGeoip)
2590
- extraPayload["geoip_disable"] = true;
3319
+ const extraPayload = {
3320
+ geoip_disable: disableGeoip ?? this.disableGeoip
3321
+ };
2591
3322
  if (flagKeysToEvaluate)
2592
3323
  extraPayload["flag_keys_to_evaluate"] = flagKeysToEvaluate;
2593
3324
  const result = await this.getFlags(distinctId, groups, personProperties, groupProperties, extraPayload);
@@ -2624,15 +3355,18 @@ class PostHogCoreStateless {
2624
3355
  "Content-Type": "application/json"
2625
3356
  }
2626
3357
  };
2627
- const response = await this.fetchWithRetry(url, fetchOptions).then((response2) => {
2628
- if (response2.status !== 200 || !response2.json) {
2629
- const msg = `Surveys API could not be loaded: ${response2.status}`;
2630
- const error = new Error(msg);
2631
- this._logger.error(error);
2632
- this._events.emit("error", new Error(msg));
2633
- return;
3358
+ const response = await this.fetchWithRetry(url, fetchOptions, {
3359
+ type: "required",
3360
+ consume: (response2) => {
3361
+ if (response2.status !== 200 || !response2.json) {
3362
+ const msg = `Surveys API could not be loaded: ${response2.status}`;
3363
+ const error = new Error(msg);
3364
+ this._logger.error(error);
3365
+ this._events.emit("error", new Error(msg));
3366
+ return Promise.resolve(undefined);
3367
+ }
3368
+ return response2.json();
2634
3369
  }
2635
- return response2.json();
2636
3370
  }).catch((error) => {
2637
3371
  this._logger.error("Surveys API could not be loaded", error);
2638
3372
  this._events.emit("error", error);
@@ -2669,23 +3403,39 @@ class PostHogCoreStateless {
2669
3403
  return message;
2670
3404
  }
2671
3405
  async flushStorage() {}
2672
- enqueue(type, _message, options) {
3406
+ getQueueRouteKey(_message) {
3407
+ return DEFAULT_QUEUE_ROUTE;
3408
+ }
3409
+ persistedQueueKeyForRoute(_route) {
3410
+ return types_PostHogPersistedProperty.Queue;
3411
+ }
3412
+ getActiveQueueRoutes() {
3413
+ return [
3414
+ DEFAULT_QUEUE_ROUTE
3415
+ ];
3416
+ }
3417
+ getRouteQueue(route) {
3418
+ return this.getPersistedProperty(this.persistedQueueKeyForRoute(route)) || [];
3419
+ }
3420
+ enqueue(type, _message, options, explicitRoute) {
2673
3421
  this.wrap(() => {
2674
3422
  if (this.optedOut)
2675
3423
  return void this._events.emit(type, "Library is disabled. Not sending event. To re-enable, call posthog.optIn()");
2676
- let message = this.prepareMessage(type, _message, options);
3424
+ let message = this.prepareMessage(_message, options);
2677
3425
  message = this.processBeforeEnqueue(message);
2678
3426
  if (message === null)
2679
3427
  return;
2680
- const queue = this.getPersistedProperty(types_PostHogPersistedProperty.Queue) || [];
3428
+ message = this.normalizeMessage(message);
3429
+ const queueKey = this.persistedQueueKeyForRoute(explicitRoute ?? this.getQueueRouteKey(message));
3430
+ const queue = this.getPersistedProperty(queueKey) || [];
2681
3431
  if (queue.length >= this.maxQueueSize) {
2682
3432
  queue.shift();
2683
- this._logger.info("Queue is full, the oldest event is dropped.");
3433
+ this._logger.warn("Queue is full, the oldest event is dropped.");
2684
3434
  }
2685
3435
  queue.push({
2686
3436
  message
2687
3437
  });
2688
- this.setPersistedProperty(types_PostHogPersistedProperty.Queue, queue);
3438
+ this.setPersistedProperty(queueKey, queue);
2689
3439
  this._events.emit(type, message);
2690
3440
  if (queue.length >= this.flushAt)
2691
3441
  this.flushBackground();
@@ -2693,61 +3443,63 @@ class PostHogCoreStateless {
2693
3443
  this._flushTimer = safeSetTimeout(() => this.flushBackground(), this.flushInterval);
2694
3444
  });
2695
3445
  }
2696
- async sendImmediate(type, _message, options) {
3446
+ async sendImmediate(type, _message, options, explicitRoute) {
2697
3447
  if (this.disabled)
2698
3448
  return void this._logger.warn("The client is disabled");
2699
3449
  if (!this._isInitialized)
2700
3450
  await this._initPromise;
2701
3451
  if (this.optedOut)
2702
3452
  return void this._events.emit(type, "Library is disabled. Not sending event. To re-enable, call posthog.optIn()");
2703
- let message = this.prepareMessage(type, _message, options);
3453
+ let message = this.prepareMessage(_message, options);
2704
3454
  message = this.processBeforeEnqueue(message);
2705
3455
  if (message === null)
2706
3456
  return;
2707
- const data = {
2708
- api_key: this.apiKey,
2709
- batch: [
3457
+ message = this.normalizeMessage(message);
3458
+ try {
3459
+ await this.sendBatch([
2710
3460
  message
2711
- ],
2712
- sent_at: currentISOTime()
2713
- };
2714
- if (this.historicalMigration)
2715
- data.historical_migration = true;
2716
- const payload = JSON.stringify(data);
2717
- const url = `${this.host}/batch/`;
2718
- const gzippedPayload = this.disableCompression ? null : await gzipCompress(payload, this.isDebug);
2719
- const fetchOptions = {
2720
- method: "POST",
2721
- headers: {
2722
- ...this.getCustomHeaders(),
2723
- "Content-Type": "application/json",
2724
- ...gzippedPayload !== null && {
2725
- "Content-Encoding": "gzip"
2726
- }
2727
- },
2728
- body: gzippedPayload || payload
2729
- };
2730
- try {
2731
- const response = await this.fetchWithRetry(url, fetchOptions);
2732
- await response.body?.cancel()?.catch(() => {});
2733
- } catch (err) {
2734
- this._events.emit("error", err);
2735
- }
2736
- }
2737
- prepareMessage(type, _message, options) {
2738
- const message = {
2739
- ..._message,
2740
- type,
2741
- library: this.getLibraryId(),
2742
- library_version: this.getLibraryVersion(),
2743
- timestamp: options?.timestamp ? options?.timestamp : currentISOTime(),
2744
- uuid: options?.uuid ? options.uuid : uuidv7()
3461
+ ], undefined, explicitRoute ?? this.getQueueRouteKey(message));
3462
+ } catch (err) {
3463
+ this._events.emit("error", err);
3464
+ }
3465
+ }
3466
+ normalizeMessage(message) {
3467
+ const { type: _type, library, library_version, ...sanitizedMessage } = message;
3468
+ let properties = isPostHogEventProperties(sanitizedMessage.properties) ? sanitizedMessage.properties : undefined;
3469
+ if (library !== undefined && properties?.$lib === undefined)
3470
+ properties = {
3471
+ ...properties || {},
3472
+ $lib: library
3473
+ };
3474
+ if (library_version !== undefined && properties?.$lib_version === undefined)
3475
+ properties = {
3476
+ ...properties || {},
3477
+ $lib_version: library_version
3478
+ };
3479
+ if (properties)
3480
+ sanitizedMessage.properties = properties;
3481
+ sanitizedMessage.uuid = getEventUuid(sanitizedMessage.uuid, uuidv7);
3482
+ return sanitizedMessage;
3483
+ }
3484
+ normalizeTimestampForWire(timestamp) {
3485
+ const parsedTimestamp = timestamp instanceof Date ? timestamp : typeof timestamp == "string" ? new Date(timestamp) : null;
3486
+ if (!parsedTimestamp || Number.isNaN(parsedTimestamp.getTime()))
3487
+ return timestamp;
3488
+ const normalized = parsedTimestamp.toISOString();
3489
+ const fractionalSeconds = typeof timestamp == "string" ? timestamp.match(/\.(\d+)(?:Z|[+-]\d{2}:?\d{2})?$/i)?.[1] : undefined;
3490
+ return fractionalSeconds && fractionalSeconds.length > 3 ? normalized.replace(/\.\d{3}Z$/, `.${fractionalSeconds}Z`) : normalized;
3491
+ }
3492
+ prepareMessage(_message, options) {
3493
+ const message = {
3494
+ ..._message,
3495
+ timestamp: options?.timestamp ? options?.timestamp : currentISOTime(),
3496
+ uuid: getEventUuid(options?.uuid, uuidv7)
2745
3497
  };
2746
3498
  const addGeoipDisableProperty = options?.disableGeoip ?? this.disableGeoip;
2747
3499
  if (addGeoipDisableProperty) {
2748
- if (!message.properties)
3500
+ if (!isPostHogEventProperties(message.properties))
2749
3501
  message.properties = {};
2750
- message["properties"]["$geoip_disable"] = true;
3502
+ message.properties["$geoip_disable"] = true;
2751
3503
  }
2752
3504
  if (message.distinctId) {
2753
3505
  message.distinct_id = message.distinctId;
@@ -2762,21 +3514,64 @@ class PostHogCoreStateless {
2762
3514
  }
2763
3515
  }
2764
3516
  flushBackground() {
3517
+ if (this.pendingFlushPromise)
3518
+ return;
2765
3519
  this.flush().catch(async (err) => {
2766
3520
  await logFlushError(err);
2767
3521
  });
2768
3522
  }
2769
- async flush() {
3523
+ async waitForPendingPromises(maxPromiseId, ignoredPromises = []) {
3524
+ const ignoredPendingPromises = ignoredPromises.filter((promise) => !!promise);
3525
+ let iteration = 0;
3526
+ while (true) {
3527
+ const promises = this.promiseQueue.getPromises([
3528
+ ...ignoredPendingPromises,
3529
+ ...this.flushPromises
3530
+ ], maxPromiseId);
3531
+ if (promises.length === 0)
3532
+ return;
3533
+ if (iteration > 0)
3534
+ this._logger.debug(`flush() re-checking ${promises.length} pending promise(s) before flushing`);
3535
+ await Promise.all(promises.map((promise) => promise.catch(() => {})));
3536
+ iteration++;
3537
+ }
3538
+ }
3539
+ flushWithPendingPromises() {
3540
+ return this.flushInternal(true);
3541
+ }
3542
+ flush() {
3543
+ return this.flushInternal(false);
3544
+ }
3545
+ flushInternal(waitForPendingPromises) {
2770
3546
  if (this.disabled)
2771
- return;
2772
- const nextFlushPromise = allSettled([
2773
- this.flushPromise
2774
- ]).then(() => this._flush());
3547
+ return Promise.resolve();
3548
+ if (!waitForPendingPromises && this.pendingFlushPromise)
3549
+ return this.pendingFlushPromise;
3550
+ const previousFlushPromise = this.flushPromise;
3551
+ const maxPromiseId = this.promiseQueue.maxId;
3552
+ const nextFlushPromise = Promise.resolve().then(() => {
3553
+ if (waitForPendingPromises)
3554
+ return this.waitForPendingPromises(maxPromiseId, [
3555
+ previousFlushPromise,
3556
+ nextFlushPromise
3557
+ ]);
3558
+ }).then(() => allSettled([
3559
+ previousFlushPromise
3560
+ ])).then(() => {
3561
+ if (this.pendingFlushPromise === nextFlushPromise)
3562
+ this.pendingFlushPromise = null;
3563
+ return this._flush();
3564
+ });
3565
+ this.pendingFlushPromise = nextFlushPromise;
2775
3566
  this.flushPromise = nextFlushPromise;
3567
+ this.flushPromises.add(nextFlushPromise);
2776
3568
  this.addPendingPromise(nextFlushPromise);
2777
3569
  allSettled([
2778
3570
  nextFlushPromise
2779
3571
  ]).then(() => {
3572
+ this.flushPromises.delete(nextFlushPromise);
3573
+ if (this.pendingFlushPromise === nextFlushPromise)
3574
+ this.pendingFlushPromise = null;
2780
3575
  if (this.flushPromise === nextFlushPromise)
2781
3576
  this.flushPromise = null;
2782
3577
  });
@@ -2789,55 +3584,102 @@ class PostHogCoreStateless {
2789
3584
  headers["User-Agent"] = customUserAgent;
2790
3585
  return headers;
2791
3586
  }
3587
+ compressPayload(payload) {
3588
+ return gzipCompress(payload, this.isDebug);
3589
+ }
3590
+ getBatchEndpointPath(_route) {
3591
+ return "/batch/";
3592
+ }
3593
+ async sendBatch(batchMessages, retryOptions, route = DEFAULT_QUEUE_ROUTE) {
3594
+ const data = {
3595
+ api_key: this.apiKey,
3596
+ batch: batchMessages.map((message) => {
3597
+ if (!message)
3598
+ return message;
3599
+ const timestamp = this.normalizeTimestampForWire(message.timestamp);
3600
+ return timestamp === message.timestamp ? message : {
3601
+ ...message,
3602
+ timestamp
3603
+ };
3604
+ }),
3605
+ sent_at: currentISOTime()
3606
+ };
3607
+ if (this.historicalMigration)
3608
+ data.historical_migration = true;
3609
+ const payload = safeJsonStringify(data);
3610
+ const url = `${this.host}${this.getBatchEndpointPath(route)}`;
3611
+ const gzippedPayload = this.disableCompression ? null : await this.compressPayload(payload);
3612
+ const fetchOptions = {
3613
+ method: "POST",
3614
+ headers: {
3615
+ ...this.getCustomHeaders(),
3616
+ "Content-Type": "application/json",
3617
+ ...gzippedPayload !== null && {
3618
+ "Content-Encoding": "gzip"
3619
+ }
3620
+ },
3621
+ body: gzippedPayload || payload
3622
+ };
3623
+ await this.fetchWithRetry(url, fetchOptions, {
3624
+ type: "successful-write"
3625
+ }, retryOptions);
3626
+ }
2792
3627
  async _flush() {
2793
3628
  this.clearFlushTimer();
2794
3629
  await this._initPromise;
2795
- let queue = this.getPersistedProperty(types_PostHogPersistedProperty.Queue) || [];
2796
- if (!queue.length)
3630
+ const routes = this.getActiveQueueRoutes();
3631
+ if (!routes.some((route) => this.getRouteQueue(route).length > 0))
2797
3632
  return;
2798
3633
  const sentMessages = [];
3634
+ let firstError;
3635
+ for (const route of routes)
3636
+ try {
3637
+ await this._flushRoute(route, sentMessages);
3638
+ } catch (err) {
3639
+ if (firstError === undefined)
3640
+ firstError = err;
3641
+ }
3642
+ if (firstError !== undefined)
3643
+ throw firstError;
3644
+ this._events.emit("flush", sentMessages);
3645
+ }
3646
+ async _flushRoute(route, sentMessages) {
3647
+ const queueKey = this.persistedQueueKeyForRoute(route);
3648
+ let queue = this.getPersistedProperty(queueKey) || [];
3649
+ if (!queue.length)
3650
+ return;
2799
3651
  const originalQueueLength = queue.length;
2800
- while (queue.length > 0 && sentMessages.length < originalQueueLength) {
3652
+ let sentFromRoute = 0;
3653
+ while (queue.length > 0 && sentFromRoute < originalQueueLength) {
2801
3654
  const batchItems = queue.slice(0, this.maxBatchSize);
2802
- const batchMessages = batchItems.map((item) => item.message);
3655
+ const batchMessages = batchItems.map((item) => item.message === undefined ? item.message : this.normalizeMessage(item.message));
2803
3656
  const persistQueueChange = async () => {
2804
- const refreshedQueue = this.getPersistedProperty(types_PostHogPersistedProperty.Queue) || [];
2805
- const newQueue = refreshedQueue.slice(batchItems.length);
2806
- this.setPersistedProperty(types_PostHogPersistedProperty.Queue, newQueue);
3657
+ const refreshedQueue = this.getPersistedProperty(queueKey) || [];
3658
+ const remainingBatchItems = [
3659
+ ...batchItems
3660
+ ];
3661
+ const newQueue = refreshedQueue.filter((item) => {
3662
+ const itemUuid = item.message?.uuid;
3663
+ const batchItemIndex = remainingBatchItems.findIndex((batchItem) => batchItem === item || typeof itemUuid == "string" && itemUuid.length > 0 && batchItem.message?.uuid === itemUuid);
3664
+ if (batchItemIndex === -1)
3665
+ return true;
3666
+ remainingBatchItems.splice(batchItemIndex, 1);
3667
+ return false;
3668
+ });
3669
+ this.setPersistedProperty(queueKey, newQueue);
2807
3670
  queue = newQueue;
3671
+ this._dequeuedMessagesCount += batchItems.length;
2808
3672
  await this.flushStorage();
2809
3673
  };
2810
- const data = {
2811
- api_key: this.apiKey,
2812
- batch: batchMessages,
2813
- sent_at: currentISOTime()
2814
- };
2815
- if (this.historicalMigration)
2816
- data.historical_migration = true;
2817
- const payload = JSON.stringify(data);
2818
- const url = `${this.host}/batch/`;
2819
- const gzippedPayload = this.disableCompression ? null : await gzipCompress(payload, this.isDebug);
2820
- const fetchOptions = {
2821
- method: "POST",
2822
- headers: {
2823
- ...this.getCustomHeaders(),
2824
- "Content-Type": "application/json",
2825
- ...gzippedPayload !== null && {
2826
- "Content-Encoding": "gzip"
2827
- }
2828
- },
2829
- body: gzippedPayload || payload
2830
- };
2831
3674
  const retryOptions = {
2832
3675
  retryCheck: (err) => {
2833
3676
  if (isPostHogFetchContentTooLargeError(err))
2834
3677
  return false;
2835
- return isPostHogFetchError(err);
3678
+ return isPostHogFetchRetryableError(err);
2836
3679
  }
2837
3680
  };
2838
3681
  try {
2839
- const response = await this.fetchWithRetry(url, fetchOptions, retryOptions);
2840
- await response.body?.cancel()?.catch(() => {});
3682
+ await this.sendBatch(batchMessages, retryOptions, route);
2841
3683
  } catch (err) {
2842
3684
  if (isPostHogFetchContentTooLargeError(err) && batchMessages.length > 1) {
2843
3685
  this.maxBatchSize = Math.max(1, Math.floor(batchMessages.length / 2));
@@ -2851,8 +3693,8 @@ class PostHogCoreStateless {
2851
3693
  }
2852
3694
  await persistQueueChange();
2853
3695
  sentMessages.push(...batchMessages);
3696
+ sentFromRoute += batchMessages.length;
2854
3697
  }
2855
- this._events.emit("flush", sentMessages);
2856
3698
  }
2857
3699
  async _sendLogsBatch(payload) {
2858
3700
  if (this.disabled)
@@ -2862,7 +3704,7 @@ class PostHogCoreStateless {
2862
3704
  };
2863
3705
  const serialized = JSON.stringify(payload);
2864
3706
  const url = `${this.host}/i/v1/logs?token=${encodeURIComponent(this.apiKey)}`;
2865
- const gzippedPayload = this.disableCompression ? null : await gzipCompress(serialized, this.isDebug);
3707
+ const gzippedPayload = this.disableCompression ? null : await this.compressPayload(serialized);
2866
3708
  const fetchOptions = {
2867
3709
  method: "POST",
2868
3710
  headers: {
@@ -2876,10 +3718,12 @@ class PostHogCoreStateless {
2876
3718
  };
2877
3719
  try {
2878
3720
  await this.fetchWithRetry(url, fetchOptions, {
3721
+ type: "successful-write"
3722
+ }, {
2879
3723
  retryCheck: (err) => {
2880
3724
  if (isPostHogFetchContentTooLargeError(err))
2881
3725
  return false;
2882
- return isPostHogFetchError(err);
3726
+ return isPostHogFetchRetryableError(err);
2883
3727
  }
2884
3728
  });
2885
3729
  return {
@@ -2901,7 +3745,56 @@ class PostHogCoreStateless {
2901
3745
  };
2902
3746
  }
2903
3747
  }
2904
- async fetchWithRetry(url, options, retryOptions, requestTimeout) {
3748
+ async _sendMetricsBatch(payload) {
3749
+ if (this.disabled)
3750
+ return {
3751
+ kind: "fatal",
3752
+ error: new Error("The client is disabled")
3753
+ };
3754
+ const serialized = JSON.stringify(payload);
3755
+ const url = `${this.host}/i/v1/metrics?token=${encodeURIComponent(this.apiKey)}`;
3756
+ const gzippedPayload = this.disableCompression ? null : await this.compressPayload(serialized);
3757
+ const fetchOptions = {
3758
+ method: "POST",
3759
+ headers: {
3760
+ ...this.getCustomHeaders(),
3761
+ "Content-Type": "application/json",
3762
+ ...gzippedPayload !== null && {
3763
+ "Content-Encoding": "gzip"
3764
+ }
3765
+ },
3766
+ body: gzippedPayload || serialized
3767
+ };
3768
+ try {
3769
+ await this.fetchWithRetry(url, fetchOptions, {
3770
+ type: "successful-write"
3771
+ }, {
3772
+ retryCheck: (err) => {
3773
+ if (isPostHogFetchContentTooLargeError(err))
3774
+ return false;
3775
+ return isPostHogFetchRetryableError(err);
3776
+ }
3777
+ });
3778
+ return {
3779
+ kind: "ok"
3780
+ };
3781
+ } catch (err) {
3782
+ if (isPostHogFetchContentTooLargeError(err))
3783
+ return {
3784
+ kind: "too-large"
3785
+ };
3786
+ if (isPostHogFetchRetryableError(err))
3787
+ return {
3788
+ kind: "retry-later",
3789
+ error: err
3790
+ };
3791
+ return {
3792
+ kind: "fatal",
3793
+ error: err
3794
+ };
3795
+ }
3796
+ }
3797
+ async fetchWithRetry(url, options, responseHandling, retryOptions, requestTimeout) {
2905
3798
  const body = options.body ? options.body : "";
2906
3799
  let reqByteLength = -1;
2907
3800
  try {
@@ -2914,28 +3807,91 @@ class PostHogCoreStateless {
2914
3807
  reqByteLength = encoded.length;
2915
3808
  }
2916
3809
  }
3810
+ const retriableOptions = {
3811
+ ...this._retryOptions,
3812
+ ...retryOptions
3813
+ };
3814
+ let attempt = 0;
2917
3815
  return await retriable(async () => {
3816
+ attempt++;
2918
3817
  const ctrl = new AbortController;
2919
3818
  const timeoutMs = requestTimeout ?? this.requestTimeout;
2920
- const timer = safeSetTimeout(() => ctrl.abort(), timeoutMs);
2921
- let res = null;
3819
+ const requestDeadline = Date.now() + timeoutMs;
3820
+ let timer;
3821
+ const deadline = new Promise((_resolve, reject) => {
3822
+ timer = safeSetTimeout(() => {
3823
+ const timeoutError = new Error(`Request timed out after ${timeoutMs}ms`);
3824
+ timeoutError.name = "AbortError";
3825
+ reject(timeoutError);
3826
+ ctrl.abort(timeoutError);
3827
+ }, timeoutMs);
3828
+ });
3829
+ let res;
3830
+ let responseAccepted = false;
3831
+ let cancellation;
3832
+ const cancelBody = () => cancellation ??= (async () => {
3833
+ try {
3834
+ await res?.body?.cancel();
3835
+ } catch {}
3836
+ })();
2922
3837
  try {
2923
- res = await this.fetch(url, {
2924
- signal: ctrl.signal,
2925
- ...options
2926
- });
2927
- } catch (e) {
2928
- throw new PostHogFetchNetworkError(e);
3838
+ let fetchPromise;
3839
+ try {
3840
+ fetchPromise = this.fetch(url, {
3841
+ signal: ctrl.signal,
3842
+ ...options
3843
+ });
3844
+ } catch (e) {
3845
+ throw new PostHogFetchNetworkError(e);
3846
+ }
3847
+ fetchPromise.then((lateResponse) => {
3848
+ if (ctrl.signal.aborted && !responseAccepted)
3849
+ Promise.resolve(lateResponse.body?.cancel()).catch(() => {});
3850
+ }).catch(() => {});
3851
+ try {
3852
+ res = await Promise.race([
3853
+ fetchPromise,
3854
+ deadline
3855
+ ]);
3856
+ responseAccepted = true;
3857
+ } catch (e) {
3858
+ throw new PostHogFetchNetworkError(e);
3859
+ }
3860
+ const isNoCors = options.mode === "no-cors";
3861
+ if (!isNoCors && (res.status < 200 || res.status >= 400))
3862
+ throw new PostHogFetchHttpError(res, reqByteLength, requestDeadline, ctrl);
3863
+ if (responseHandling.type === "successful-write") {
3864
+ try {
3865
+ await Promise.race([
3866
+ cancelBody(),
3867
+ deadline
3868
+ ]);
3869
+ } catch {}
3870
+ return;
3871
+ }
3872
+ try {
3873
+ return await Promise.race([
3874
+ responseHandling.consume(res),
3875
+ deadline
3876
+ ]);
3877
+ } catch (e) {
3878
+ if (ctrl.signal.aborted)
3879
+ throw new PostHogFetchNetworkError(e);
3880
+ throw e;
3881
+ }
2929
3882
  } finally {
2930
3883
  clearTimeout(timer);
3884
+ if (ctrl.signal.aborted && res)
3885
+ cancelBody();
2931
3886
  }
2932
- const isNoCors = options.mode === "no-cors";
2933
- if (!isNoCors && (res.status < 200 || res.status >= 400))
2934
- throw new PostHogFetchHttpError(res, reqByteLength);
2935
- return res;
2936
3887
  }, {
2937
- ...this._retryOptions,
2938
- ...retryOptions
3888
+ ...retriableOptions,
3889
+ retryCheck: (error) => {
3890
+ const shouldRetry = retriableOptions.retryCheck(error);
3891
+ if (shouldRetry && attempt <= retriableOptions.retryCount && error instanceof PostHogFetchHttpError)
3892
+ error.cancelResponseBody();
3893
+ return shouldRetry;
3894
+ }
2939
3895
  });
2940
3896
  }
2941
3897
  async _shutdown(shutdownTimeoutMs = 30000) {
@@ -2948,12 +3904,17 @@ class PostHogCoreStateless {
2948
3904
  try {
2949
3905
  await this.promiseQueue.join();
2950
3906
  while (true) {
2951
- const queue = this.getPersistedProperty(types_PostHogPersistedProperty.Queue) || [];
2952
- if (queue.length === 0)
3907
+ const hasQueuedEvents = this.getActiveQueueRoutes().some((route) => this.getRouteQueue(route).length > 0);
3908
+ if (!hasQueuedEvents)
2953
3909
  break;
3910
+ const dequeuedBeforeFlush = this._dequeuedMessagesCount;
2954
3911
  await this.flush();
2955
3912
  if (hasTimedOut)
2956
3913
  break;
3914
+ if (this._dequeuedMessagesCount === dequeuedBeforeFlush) {
3915
+ this._logger.warn("Shutdown flush completed but did not send any queued events. Stopping drain to avoid a loop.");
3916
+ break;
3917
+ }
2957
3918
  }
2958
3919
  } catch (e) {
2959
3920
  if (!isPostHogFetchError(e))
@@ -2961,21 +3922,12 @@ class PostHogCoreStateless {
2961
3922
  await logFlushError(e);
2962
3923
  }
2963
3924
  };
2964
- let timeoutHandle;
2965
- try {
2966
- return await Promise.race([
2967
- new Promise((_, reject) => {
2968
- timeoutHandle = safeSetTimeout(() => {
2969
- this._logger.error("Timed out while shutting down PostHog");
2970
- hasTimedOut = true;
2971
- reject("Timeout while shutting down PostHog. Some events may not have been sent.");
2972
- }, shutdownTimeoutMs);
2973
- }),
2974
- doShutdown()
2975
- ]);
2976
- } finally {
2977
- clearTimeout(timeoutHandle);
2978
- }
3925
+ return raceWithTimeout(doShutdown(), shutdownTimeoutMs, () => {
3926
+ this._logger.critical("Timeout while shutting down PostHog. Some events may not have been sent.", {
3927
+ shutdownTimeoutMs
3928
+ });
3929
+ hasTimedOut = true;
3930
+ });
2979
3931
  }
2980
3932
  async shutdown(shutdownTimeoutMs = 30000) {
2981
3933
  if (this.shutdownPromise)
@@ -2987,21 +3939,30 @@ class PostHogCoreStateless {
2987
3939
  return this.shutdownPromise;
2988
3940
  }
2989
3941
  }
2990
- // ../../../../../node_modules/.bun/posthog-node@5.35.12/node_modules/posthog-node/dist/extensions/error-tracking/modifiers/context-lines.node.mjs
2991
- import { createReadStream } from "node:fs";
3942
+ // ../../../../../node_modules/.bun/posthog-node@5.49.2/node_modules/posthog-node/dist/extensions/error-tracking/modifiers/context-lines.node.mjs
3943
+ import { constants as constants2 } from "node:fs";
3944
+ import { open as promises_open } from "node:fs/promises";
3945
+ import { isAbsolute } from "node:path";
2992
3946
  import { createInterface } from "node:readline";
2993
3947
  var LRU_FILE_CONTENTS_CACHE = new exports_error_tracking.ReduceableCache(25);
2994
3948
  var LRU_FILE_CONTENTS_FS_READ_FAILED = new exports_error_tracking.ReduceableCache(20);
2995
3949
  var DEFAULT_LINES_OF_CONTEXT = 7;
2996
3950
  var MAX_CONTEXTLINES_COLNO = 1000;
2997
3951
  var MAX_CONTEXTLINES_LINENO = 1e4;
2998
- async function addSourceContext(frames) {
3952
+ var MAX_CONTEXTLINES_FILE_SIZE = 10485760;
3953
+ async function addSourceContext(frames, openSourceFile = promises_open, logger2) {
2999
3954
  const filesToLines = {};
3955
+ let basePath;
3956
+ try {
3957
+ basePath = process.cwd();
3958
+ } catch {}
3000
3959
  for (let i = frames.length - 1;i >= 0; i--) {
3001
3960
  const frame = frames[i];
3002
3961
  const filename = frame?.filename;
3003
3962
  if (!frame || typeof filename != "string" || typeof frame.lineno != "number" || shouldSkipContextLinesForFile(filename) || shouldSkipContextLinesForFrame(frame))
3004
3963
  continue;
3964
+ if (!isAbsolute(filename) && basePath === undefined)
3965
+ continue;
3005
3966
  const filesToLinesOutput = filesToLines[filename];
3006
3967
  if (!filesToLinesOutput)
3007
3968
  filesToLines[filename] = [];
@@ -3012,50 +3973,98 @@ async function addSourceContext(frames) {
3012
3973
  return frames;
3013
3974
  const readlinePromises = [];
3014
3975
  for (const file of files) {
3015
- if (LRU_FILE_CONTENTS_FS_READ_FAILED.get(file))
3976
+ const cacheKey = makeSourceCacheKey(file, basePath);
3977
+ if (cacheKey === undefined)
3978
+ continue;
3979
+ if (LRU_FILE_CONTENTS_FS_READ_FAILED.get(cacheKey))
3016
3980
  continue;
3017
3981
  const filesToLineRanges = filesToLines[file];
3018
3982
  if (!filesToLineRanges)
3019
3983
  continue;
3020
3984
  filesToLineRanges.sort((a, b) => a - b);
3021
3985
  const ranges = makeLineReaderRanges(filesToLineRanges);
3022
- if (ranges.every((r) => rangeExistsInContentCache(file, r)))
3986
+ if (ranges.every((r) => rangeExistsInContentCache(cacheKey, r)))
3023
3987
  continue;
3024
- const cache = emplace(LRU_FILE_CONTENTS_CACHE, file, {});
3025
- readlinePromises.push(getContextLinesFromFile(file, ranges, cache));
3988
+ const cache = emplace(LRU_FILE_CONTENTS_CACHE, cacheKey, {});
3989
+ readlinePromises.push(getContextLinesFromFile(file, ranges, cache, cacheKey, openSourceFile, logger2));
3026
3990
  }
3027
3991
  await Promise.all(readlinePromises).catch(() => {});
3028
3992
  if (frames && frames.length > 0)
3029
- addSourceContextToFrames(frames, LRU_FILE_CONTENTS_CACHE);
3993
+ addSourceContextToFrames(frames, LRU_FILE_CONTENTS_CACHE, basePath);
3030
3994
  LRU_FILE_CONTENTS_CACHE.reduce();
3031
3995
  return frames;
3032
3996
  }
3033
- function getContextLinesFromFile(path2, ranges, output) {
3997
+ async function openRegularSourceFile(path2, openSourceFile, logger2) {
3998
+ let fileHandle;
3999
+ let isValid = false;
4000
+ try {
4001
+ fileHandle = await openSourceFile(path2, constants2.O_RDONLY | constants2.O_NONBLOCK);
4002
+ const fileStat = await fileHandle.stat();
4003
+ if (!fileStat.isFile())
4004
+ return;
4005
+ if (fileStat.size > MAX_CONTEXTLINES_FILE_SIZE)
4006
+ return void logger2?.debug(`Skipping source context for oversized file ${path2}: ${fileStat.size} bytes exceeds ${MAX_CONTEXTLINES_FILE_SIZE}`);
4007
+ isValid = true;
4008
+ return fileHandle;
4009
+ } catch {
4010
+ return;
4011
+ } finally {
4012
+ if (fileHandle && !isValid)
4013
+ await fileHandle.close().catch(() => {});
4014
+ }
4015
+ }
4016
+ async function getContextLinesFromFile(path2, ranges, output, cacheKey, openSourceFile, logger2) {
4017
+ const fileHandle = await openRegularSourceFile(path2, openSourceFile, logger2);
4018
+ if (fileHandle === undefined)
4019
+ return void LRU_FILE_CONTENTS_FS_READ_FAILED.set(cacheKey, 1);
4020
+ const openedFileHandle = fileHandle;
3034
4021
  return new Promise((resolve) => {
3035
- const stream = createReadStream(path2);
3036
- const lineReaded = createInterface({
3037
- input: stream
3038
- });
3039
- function destroyStreamAndResolve() {
3040
- stream.destroy();
3041
- resolve();
4022
+ let finished = false;
4023
+ function destroyStreamAndResolve(stream2) {
4024
+ if (finished)
4025
+ return;
4026
+ finished = true;
4027
+ stream2?.destroy();
4028
+ openedFileHandle.close().then(resolve, resolve);
4029
+ }
4030
+ let stream;
4031
+ try {
4032
+ stream = openedFileHandle.createReadStream({
4033
+ autoClose: false,
4034
+ start: 0,
4035
+ end: MAX_CONTEXTLINES_FILE_SIZE - 1
4036
+ });
4037
+ } catch {
4038
+ LRU_FILE_CONTENTS_FS_READ_FAILED.set(cacheKey, 1);
4039
+ destroyStreamAndResolve();
4040
+ return;
4041
+ }
4042
+ let lineReaded;
4043
+ try {
4044
+ lineReaded = createInterface({
4045
+ input: stream
4046
+ });
4047
+ } catch {
4048
+ LRU_FILE_CONTENTS_FS_READ_FAILED.set(cacheKey, 1);
4049
+ destroyStreamAndResolve(stream);
4050
+ return;
3042
4051
  }
3043
4052
  let lineNumber = 0;
3044
4053
  let currentRangeIndex = 0;
3045
4054
  const range = ranges[currentRangeIndex];
3046
4055
  if (range === undefined)
3047
- return void destroyStreamAndResolve();
4056
+ return void destroyStreamAndResolve(stream);
3048
4057
  let rangeStart = range[0];
3049
4058
  let rangeEnd = range[1];
3050
4059
  function onStreamError() {
3051
- LRU_FILE_CONTENTS_FS_READ_FAILED.set(path2, 1);
4060
+ LRU_FILE_CONTENTS_FS_READ_FAILED.set(cacheKey, 1);
3052
4061
  lineReaded.close();
3053
4062
  lineReaded.removeAllListeners();
3054
- destroyStreamAndResolve();
4063
+ destroyStreamAndResolve(stream);
3055
4064
  }
3056
4065
  stream.on("error", onStreamError);
3057
4066
  lineReaded.on("error", onStreamError);
3058
- lineReaded.on("close", destroyStreamAndResolve);
4067
+ lineReaded.on("close", () => destroyStreamAndResolve(stream));
3059
4068
  lineReaded.on("line", (line) => {
3060
4069
  lineNumber++;
3061
4070
  if (lineNumber < rangeStart)
@@ -3080,10 +4089,11 @@ function getContextLinesFromFile(path2, ranges, output) {
3080
4089
  });
3081
4090
  });
3082
4091
  }
3083
- function addSourceContextToFrames(frames, cache) {
4092
+ function addSourceContextToFrames(frames, cache, basePath) {
3084
4093
  for (const frame of frames)
3085
4094
  if (frame.filename && frame.context_line === undefined && typeof frame.lineno == "number") {
3086
- const contents = cache.get(frame.filename);
4095
+ const cacheKey = makeSourceCacheKey(frame.filename, basePath);
4096
+ const contents = cacheKey === undefined ? undefined : cache.get(cacheKey);
3087
4097
  if (contents === undefined)
3088
4098
  continue;
3089
4099
  addContextToFrame(frame.lineno, frame, contents);
@@ -3126,8 +4136,19 @@ function shouldSkipContextLinesForFrame(frame) {
3126
4136
  return true;
3127
4137
  return false;
3128
4138
  }
3129
- function rangeExistsInContentCache(file, range) {
3130
- const contents = LRU_FILE_CONTENTS_CACHE.get(file);
4139
+ function makeSourceCacheKey(path2, basePath) {
4140
+ if (isAbsolute(path2))
4141
+ return JSON.stringify([
4142
+ null,
4143
+ path2
4144
+ ]);
4145
+ return basePath === undefined ? undefined : JSON.stringify([
4146
+ basePath,
4147
+ path2
4148
+ ]);
4149
+ }
4150
+ function rangeExistsInContentCache(cacheKey, range) {
4151
+ const contents = LRU_FILE_CONTENTS_CACHE.get(cacheKey);
3131
4152
  if (contents === undefined)
3132
4153
  return false;
3133
4154
  for (let i = range[0];i <= range[1]; i++)
@@ -3205,8 +4226,8 @@ function snipLine(line, colno) {
3205
4226
  return newLine;
3206
4227
  }
3207
4228
 
3208
- // ../../../../../node_modules/.bun/posthog-node@5.35.12/node_modules/posthog-node/dist/extensions/error-tracking/modifiers/relative-path.node.mjs
3209
- import { isAbsolute, relative, sep as sep2 } from "path";
4229
+ // ../../../../../node_modules/.bun/posthog-node@5.49.2/node_modules/posthog-node/dist/extensions/error-tracking/modifiers/relative-path.node.mjs
4230
+ import { isAbsolute as isAbsolute2, relative, sep as sep2 } from "path";
3210
4231
  function createRelativePathModifier(basePath = process.cwd()) {
3211
4232
  const isWindows = sep2 === "\\";
3212
4233
  const toUnix = (p) => isWindows ? p.replace(/\\/g, "/") : p;
@@ -3214,17 +4235,17 @@ function createRelativePathModifier(basePath = process.cwd()) {
3214
4235
  return async (frames) => {
3215
4236
  for (const frame of frames)
3216
4237
  if (!(!frame.filename || frame.filename.startsWith("node:") || frame.filename.startsWith("data:"))) {
3217
- if (isAbsolute(frame.filename))
4238
+ if (isAbsolute2(frame.filename))
3218
4239
  frame.filename = toUnix(relative(normalizedBase, toUnix(frame.filename)));
3219
4240
  }
3220
4241
  return frames;
3221
4242
  };
3222
4243
  }
3223
4244
 
3224
- // ../../../../../node_modules/.bun/posthog-node@5.35.12/node_modules/posthog-node/dist/version.mjs
3225
- var version = "5.35.12";
4245
+ // ../../../../../node_modules/.bun/posthog-node@5.49.2/node_modules/posthog-node/dist/version.mjs
4246
+ var version = "5.49.2";
3226
4247
 
3227
- // ../../../../../node_modules/.bun/posthog-node@5.35.12/node_modules/posthog-node/dist/types.mjs
4248
+ // ../../../../../node_modules/.bun/posthog-node@5.49.2/node_modules/posthog-node/dist/types.mjs
3228
4249
  var FeatureFlagError2 = {
3229
4250
  ERRORS_WHILE_COMPUTING: "errors_while_computing_flags",
3230
4251
  FLAG_MISSING: "flag_missing",
@@ -3232,7 +4253,7 @@ var FeatureFlagError2 = {
3232
4253
  UNKNOWN_ERROR: "unknown_error"
3233
4254
  };
3234
4255
 
3235
- // ../../../../../node_modules/.bun/posthog-node@5.35.12/node_modules/posthog-node/dist/feature-flag-evaluations.mjs
4256
+ // ../../../../../node_modules/.bun/posthog-node@5.49.2/node_modules/posthog-node/dist/feature-flag-evaluations.mjs
3236
4257
  class FeatureFlagEvaluations {
3237
4258
  constructor(init) {
3238
4259
  this._host = init.host;
@@ -3341,6 +4362,8 @@ class FeatureFlagEvaluations {
3341
4362
  $feature_flag_request_id: this._requestId,
3342
4363
  $feature_flag_evaluated_at: flag?.locallyEvaluated ? Date.now() : this._evaluatedAt
3343
4364
  };
4365
+ if (flag?.hasExperiment !== undefined)
4366
+ properties.$feature_flag_has_experiment = flag.hasExperiment;
3344
4367
  if (flag?.locallyEvaluated && this._flagDefinitionsLoadedAt !== undefined)
3345
4368
  properties.$feature_flag_definitions_loaded_at = this._flagDefinitionsLoadedAt;
3346
4369
  const errors = [];
@@ -3363,7 +4386,7 @@ class FeatureFlagEvaluations {
3363
4386
  }
3364
4387
  }
3365
4388
 
3366
- // ../../../../../node_modules/.bun/posthog-node@5.35.12/node_modules/posthog-node/dist/extensions/feature-flags/crypto.mjs
4389
+ // ../../../../../node_modules/.bun/posthog-node@5.49.2/node_modules/posthog-node/dist/extensions/feature-flags/crypto.mjs
3367
4390
  async function hashSHA1(text) {
3368
4391
  const subtle = globalThis.crypto?.subtle;
3369
4392
  if (!subtle)
@@ -3373,7 +4396,7 @@ async function hashSHA1(text) {
3373
4396
  return hashArray.map((byte) => byte.toString(16).padStart(2, "0")).join("");
3374
4397
  }
3375
4398
 
3376
- // ../../../../../node_modules/.bun/posthog-node@5.35.12/node_modules/posthog-node/dist/extensions/feature-flags/feature-flags.mjs
4399
+ // ../../../../../node_modules/.bun/posthog-node@5.49.2/node_modules/posthog-node/dist/extensions/feature-flags/feature-flags.mjs
3377
4400
  var SIXTY_SECONDS = 60000;
3378
4401
  var LONG_SCALE = 1152921504606847000;
3379
4402
  var NULL_VALUES_ALLOWED_OPERATORS = [
@@ -3390,22 +4413,23 @@ class ClientError extends Error {
3390
4413
  Object.setPrototypeOf(this, ClientError.prototype);
3391
4414
  }
3392
4415
  }
4416
+ function setCustomErrorPrototype(error, constructor) {
4417
+ error.name = constructor.name;
4418
+ Error.captureStackTrace(error, constructor);
4419
+ Object.setPrototypeOf(error, constructor.prototype);
4420
+ }
3393
4421
 
3394
4422
  class InconclusiveMatchError extends Error {
3395
4423
  constructor(message) {
3396
4424
  super(message);
3397
- this.name = this.constructor.name;
3398
- Error.captureStackTrace(this, this.constructor);
3399
- Object.setPrototypeOf(this, InconclusiveMatchError.prototype);
4425
+ setCustomErrorPrototype(this, InconclusiveMatchError);
3400
4426
  }
3401
4427
  }
3402
4428
 
3403
4429
  class RequiresServerEvaluation extends Error {
3404
4430
  constructor(message) {
3405
4431
  super(message);
3406
- this.name = this.constructor.name;
3407
- Error.captureStackTrace(this, this.constructor);
3408
- Object.setPrototypeOf(this, RequiresServerEvaluation.prototype);
4432
+ setCustomErrorPrototype(this, RequiresServerEvaluation);
3409
4433
  }
3410
4434
  }
3411
4435
 
@@ -3414,6 +4438,7 @@ class FeatureFlagsPoller {
3414
4438
  this.debugMode = false;
3415
4439
  this.shouldBeginExponentialBackoff = false;
3416
4440
  this.backOffCount = 0;
4441
+ this.pollerStopped = false;
3417
4442
  this.pollingInterval = pollingInterval;
3418
4443
  this.personalApiKey = personalApiKey;
3419
4444
  this.featureFlags = [];
@@ -3429,6 +4454,7 @@ class FeatureFlagsPoller {
3429
4454
  this.onError = options.onError;
3430
4455
  this.customHeaders = customHeaders;
3431
4456
  this.onLoad = options.onLoad;
4457
+ this.onMinimalFlagCalledEvents = options.onMinimalFlagCalledEvents;
3432
4458
  this.cacheProvider = options.cacheProvider;
3433
4459
  this.strictLocalEvaluation = options.strictLocalEvaluation ?? false;
3434
4460
  this.loadFeatureFlags();
@@ -3626,6 +4652,7 @@ class FeatureFlagsPoller {
3626
4652
  const flagFilters = flag.filters || {};
3627
4653
  const flagConditions = flagFilters.groups || [];
3628
4654
  const flagAggregation = flagFilters.aggregation_group_type_index;
4655
+ const earlyExitEnabled = flagFilters.early_exit ?? false;
3629
4656
  const { groups, groupProperties } = evaluationContext;
3630
4657
  let isInconclusive = false;
3631
4658
  let result;
@@ -3649,12 +4676,15 @@ class FeatureFlagsPoller {
3649
4676
  effectiveBucketingValue = groups[groupName];
3650
4677
  }
3651
4678
  }
3652
- if (await this.isConditionMatch(flag, effectiveBucketingValue, condition, effectiveProperties, evaluationContext)) {
4679
+ const matchResult = await this.isConditionMatch(flag, effectiveBucketingValue, condition, effectiveProperties, evaluationContext);
4680
+ if (matchResult === "match") {
3653
4681
  const variantOverride = condition.variant;
3654
4682
  const flagVariants = flagFilters.multivariate?.variants || [];
3655
4683
  result = variantOverride && flagVariants.some((variant) => variant.key === variantOverride) ? variantOverride : await this.getMatchingVariant(flag, effectiveBucketingValue) || true;
3656
4684
  break;
3657
4685
  }
4686
+ if (earlyExitEnabled && matchResult === "out_of_rollout_bound")
4687
+ return false;
3658
4688
  } catch (e) {
3659
4689
  if (e instanceof RequiresServerEvaluation)
3660
4690
  throw e;
@@ -3678,16 +4708,20 @@ class FeatureFlagsPoller {
3678
4708
  for (const prop of condition.properties) {
3679
4709
  const propertyType = prop.type;
3680
4710
  let matches = false;
3681
- matches = propertyType === "cohort" ? await matchCohort(prop, properties, this.cohorts, this.debugMode, (depProp) => this.evaluateFlagDependency(depProp, properties, evaluationContext)) : propertyType === "flag" ? await this.evaluateFlagDependency(prop, properties, evaluationContext) : matchProperty(prop, properties, warnFunction);
4711
+ if (propertyType === "cohort") {
4712
+ const inCohort = await matchCohort(prop, properties, this.cohorts, this.debugMode, (depProp) => this.evaluateFlagDependency(depProp, properties, evaluationContext));
4713
+ matches = prop.operator === "not_in" ? !inCohort : inCohort;
4714
+ } else
4715
+ matches = propertyType === "flag" ? await this.evaluateFlagDependency(prop, properties, evaluationContext) : matchProperty(prop, properties, warnFunction);
3682
4716
  if (!matches)
3683
- return false;
4717
+ return "no_match";
3684
4718
  }
3685
4719
  if (rolloutPercentage == undefined)
3686
- return true;
4720
+ return "match";
3687
4721
  }
3688
4722
  if (rolloutPercentage != null && await _hash(flag.key, bucketingValue) > rolloutPercentage / 100)
3689
- return false;
3690
- return true;
4723
+ return "out_of_rollout_bound";
4724
+ return "match";
3691
4725
  }
3692
4726
  async getMatchingVariant(flag, bucketingValue) {
3693
4727
  const hashValue = await _hash(flag.key, bucketingValue, "variant");
@@ -3718,6 +4752,7 @@ class FeatureFlagsPoller {
3718
4752
  this.groupTypeMapping = flagData.groupTypeMapping;
3719
4753
  this.cohorts = flagData.cohorts;
3720
4754
  this.loadedSuccessfullyOnce = true;
4755
+ this.onMinimalFlagCalledEvents?.(flagData.minimalFlagCalledEvents === true);
3721
4756
  }
3722
4757
  warnAboutExperienceContinuityFlags(flags) {
3723
4758
  if (this.strictLocalEvaluation)
@@ -3781,7 +4816,6 @@ class FeatureFlagsPoller {
3781
4816
  clearTimeout(this.poller);
3782
4817
  this.poller = undefined;
3783
4818
  }
3784
- this.poller = setTimeout(() => this.loadFeatureFlags(true), this.getPollingInterval());
3785
4819
  try {
3786
4820
  let shouldFetch = true;
3787
4821
  if (this.cacheProvider)
@@ -3809,17 +4843,18 @@ class FeatureFlagsPoller {
3809
4843
  return;
3810
4844
  case 401:
3811
4845
  this.beginBackoff();
3812
- throw new ClientError(`Your project key or personal API key is invalid. Setting next polling interval to ${this.getPollingInterval()}ms. More information: https://posthog.com/docs/api#rate-limiting`);
4846
+ throw new ClientError(`Your project key or secret key is invalid. Setting next polling interval to ${this.getPollingInterval()}ms. More information: https://posthog.com/docs/api#rate-limiting`);
3813
4847
  case 402:
3814
4848
  console.warn("[FEATURE FLAGS] Feature flags quota limit exceeded - unsetting all local flags. Learn more about billing limits at https://posthog.com/docs/billing/limits-alerts");
3815
4849
  this.featureFlags = [];
3816
4850
  this.featureFlagsByKey = {};
3817
4851
  this.groupTypeMapping = {};
3818
4852
  this.cohorts = {};
4853
+ this.onMinimalFlagCalledEvents?.(false);
3819
4854
  return;
3820
4855
  case 403:
3821
4856
  this.beginBackoff();
3822
- throw new ClientError(`Your personal API key does not have permission to fetch feature flag definitions for local evaluation. Setting next polling interval to ${this.getPollingInterval()}ms. Are you sure you're using the correct personal and Project API key pair? More information: https://posthog.com/docs/api/overview`);
4857
+ throw new ClientError(`Your secret key does not have permission to fetch feature flag definitions for local evaluation. Setting next polling interval to ${this.getPollingInterval()}ms. Are you sure you're using the correct secret and Project API key pair? More information: https://posthog.com/docs/api/overview`);
3823
4858
  case 429:
3824
4859
  this.beginBackoff();
3825
4860
  throw new ClientError(`You are being rate limited. Setting next polling interval to ${this.getPollingInterval()}ms. More information: https://posthog.com/docs/api#rate-limiting`);
@@ -3831,7 +4866,8 @@ class FeatureFlagsPoller {
3831
4866
  const flagData = {
3832
4867
  flags: responseJson.flags ?? [],
3833
4868
  groupTypeMapping: responseJson.group_type_mapping || {},
3834
- cohorts: responseJson.cohorts || {}
4869
+ cohorts: responseJson.cohorts || {},
4870
+ minimalFlagCalledEvents: responseJson.minimal_flag_called_events === true
3835
4871
  };
3836
4872
  this.updateFlagState(flagData);
3837
4873
  this.flagDefinitionsLoadedAt = Date.now();
@@ -3852,6 +4888,9 @@ class FeatureFlagsPoller {
3852
4888
  } catch (err) {
3853
4889
  if (err instanceof ClientError)
3854
4890
  this.onError?.(err);
4891
+ } finally {
4892
+ if (!this.pollerStopped)
4893
+ this.poller = setTimeout(() => this.loadFeatureFlags(true), this.getPollingInterval());
3855
4894
  }
3856
4895
  }
3857
4896
  getPersonalApiKeyRequestOptions(method = "GET", etag) {
@@ -3867,7 +4906,7 @@ class FeatureFlagsPoller {
3867
4906
  headers
3868
4907
  };
3869
4908
  }
3870
- _requestFeatureFlagDefinitions() {
4909
+ async _requestFeatureFlagDefinitions() {
3871
4910
  const url = `${this.host}/flags/definitions?token=${this.projectApiKey}&send_cohorts`;
3872
4911
  const options = this.getPersonalApiKeyRequestOptions("GET", this.flagsEtag);
3873
4912
  let abortTimeout = null;
@@ -3878,23 +4917,49 @@ class FeatureFlagsPoller {
3878
4917
  }, this.timeout);
3879
4918
  options.signal = controller.signal;
3880
4919
  }
4920
+ const clearAbortTimeout = () => clearTimeout(abortTimeout);
3881
4921
  try {
3882
4922
  const fetch1 = this.fetch;
3883
- return fetch1(url, options);
3884
- } finally {
3885
- clearTimeout(abortTimeout);
4923
+ const res = await fetch1(url, options);
4924
+ if (res.status !== 200) {
4925
+ clearAbortTimeout();
4926
+ return res;
4927
+ }
4928
+ return {
4929
+ status: res.status,
4930
+ headers: res.headers,
4931
+ body: res.body,
4932
+ text: async () => {
4933
+ try {
4934
+ return await res.text();
4935
+ } finally {
4936
+ clearAbortTimeout();
4937
+ }
4938
+ },
4939
+ json: async () => {
4940
+ try {
4941
+ return await res.json();
4942
+ } finally {
4943
+ clearAbortTimeout();
4944
+ }
4945
+ }
4946
+ };
4947
+ } catch (err) {
4948
+ clearAbortTimeout();
4949
+ throw err;
3886
4950
  }
3887
4951
  }
3888
4952
  async stopPoller(timeoutMs = 30000) {
4953
+ this.pollerStopped = true;
3889
4954
  clearTimeout(this.poller);
4955
+ this.poller = undefined;
3890
4956
  if (this.cacheProvider)
3891
4957
  try {
3892
4958
  const shutdownResult = this.cacheProvider.shutdown();
3893
4959
  if (shutdownResult instanceof Promise)
3894
- await Promise.race([
3895
- shutdownResult,
3896
- new Promise((_, reject) => setTimeout(() => reject(new Error(`Cache shutdown timeout after ${timeoutMs}ms`)), timeoutMs))
3897
- ]);
4960
+ await raceWithTimeout(shutdownResult, timeoutMs, () => {
4961
+ throw new Error(`Cache shutdown timeout after ${timeoutMs}ms`);
4962
+ });
3898
4963
  } catch (err) {
3899
4964
  this.onError?.(new Error(`Error during cache shutdown: ${err}`));
3900
4965
  }
@@ -3949,6 +5014,14 @@ function matchProperty(property, propertyValues, warnFunction) {
3949
5014
  return String(overrideValue).toLowerCase().includes(String(value).toLowerCase());
3950
5015
  case "not_icontains":
3951
5016
  return !String(overrideValue).toLowerCase().includes(String(value).toLowerCase());
5017
+ case "starts_with":
5018
+ return String(overrideValue).toLowerCase().startsWith(String(value).toLowerCase());
5019
+ case "not_starts_with":
5020
+ return !String(overrideValue).toLowerCase().startsWith(String(value).toLowerCase());
5021
+ case "ends_with":
5022
+ return String(overrideValue).toLowerCase().endsWith(String(value).toLowerCase());
5023
+ case "not_ends_with":
5024
+ return !String(overrideValue).toLowerCase().endsWith(String(value).toLowerCase());
3952
5025
  case "regex":
3953
5026
  return isValidRegex(String(value)) && String(overrideValue).match(String(value)) !== null;
3954
5027
  case "not_regex":
@@ -4275,19 +5348,75 @@ function relativeDateParseForFeatureFlagMatching(value) {
4275
5348
  }
4276
5349
  }
4277
5350
 
4278
- // ../../../../../node_modules/.bun/posthog-node@5.35.12/node_modules/posthog-node/dist/extensions/error-tracking/autocapture.mjs
5351
+ // ../../../../../node_modules/.bun/posthog-node@5.49.2/node_modules/posthog-node/dist/extensions/error-tracking/autocapture.mjs
5352
+ var UNHANDLED_REJECTION_OPTION_NAMES = [
5353
+ "--unhandled-rejections",
5354
+ "--unhandled_rejections"
5355
+ ];
5356
+ var UNHANDLED_REJECTION_MODES = new Set([
5357
+ "throw",
5358
+ "strict",
5359
+ "warn",
5360
+ "warn-with-error-code",
5361
+ "none"
5362
+ ]);
5363
+ var STARTUP_EXEC_ARGV = [
5364
+ ...globalThis.process?.execArgv ?? []
5365
+ ];
5366
+ var STARTUP_NODE_OPTIONS = globalThis.process?.env?.NODE_OPTIONS;
5367
+ function splitNodeOptions(nodeOptions) {
5368
+ const args = [];
5369
+ let current = "";
5370
+ let isInString = false;
5371
+ for (let index = 0;index < nodeOptions.length; index++) {
5372
+ const character = nodeOptions[index];
5373
+ if (character === "\\" && isInString && index + 1 < nodeOptions.length)
5374
+ current += nodeOptions[++index];
5375
+ else if (character !== " " || isInString)
5376
+ if (character === '"')
5377
+ isInString = !isInString;
5378
+ else
5379
+ current += character;
5380
+ else if (current) {
5381
+ args.push(current);
5382
+ current = "";
5383
+ }
5384
+ }
5385
+ if (current)
5386
+ args.push(current);
5387
+ return args;
5388
+ }
5389
+ function findUnhandledRejectionMode(args) {
5390
+ let mode;
5391
+ for (let index = 0;index < args.length; index++) {
5392
+ const argument = args[index];
5393
+ const optionName = UNHANDLED_REJECTION_OPTION_NAMES.find((name) => argument === name || argument.startsWith(`${name}=`));
5394
+ if (!optionName)
5395
+ continue;
5396
+ const value = argument === optionName ? args[++index] : argument.slice(optionName.length + 1);
5397
+ if (UNHANDLED_REJECTION_MODES.has(value))
5398
+ mode = value;
5399
+ }
5400
+ return mode;
5401
+ }
5402
+ function getUnhandledRejectionMode(execArgv = STARTUP_EXEC_ARGV, nodeOptions = STARTUP_NODE_OPTIONS) {
5403
+ return findUnhandledRejectionMode(execArgv) ?? findUnhandledRejectionMode(splitNodeOptions(nodeOptions ?? "")) ?? "throw";
5404
+ }
5405
+ var STARTUP_UNHANDLED_REJECTION_MODE = getUnhandledRejectionMode();
5406
+ function captureUncaughtException(captureFn, error, origin) {
5407
+ captureFn(error, {
5408
+ mechanism: {
5409
+ type: origin === "unhandledRejection" ? "onunhandledrejection" : "onuncaughtexception",
5410
+ handled: false
5411
+ }
5412
+ });
5413
+ }
4279
5414
  function makeUncaughtExceptionHandler(captureFn, onFatalFn) {
4280
5415
  let calledFatalError = false;
4281
- return Object.assign((error) => {
5416
+ return Object.assign((error, origin) => {
4282
5417
  const userProvidedListenersCount = global.process.listeners("uncaughtException").filter((listener) => listener.name !== "domainUncaughtExceptionClear" && listener._posthogErrorHandler !== true).length;
4283
- const processWouldExit = userProvidedListenersCount === 0;
4284
- captureFn(error, {
4285
- mechanism: {
4286
- type: "onuncaughtexception",
4287
- handled: false
4288
- }
4289
- });
4290
- if (!calledFatalError && processWouldExit) {
5418
+ captureUncaughtException(captureFn, error, origin);
5419
+ if (!calledFatalError && userProvidedListenersCount === 0) {
4291
5420
  calledFatalError = true;
4292
5421
  onFatalFn(error);
4293
5422
  }
@@ -4295,29 +5424,38 @@ function makeUncaughtExceptionHandler(captureFn, onFatalFn) {
4295
5424
  _posthogErrorHandler: true
4296
5425
  });
4297
5426
  }
4298
- function addUncaughtExceptionListener(captureFn, onFatalFn) {
4299
- globalThis.process?.on("uncaughtException", makeUncaughtExceptionHandler(captureFn, onFatalFn));
5427
+ function addUncaughtExceptionListener(captureFn, onFatalFn, mode = STARTUP_UNHANDLED_REJECTION_MODE) {
5428
+ const process2 = globalThis.process;
5429
+ if (!process2)
5430
+ return;
5431
+ if (mode === "strict")
5432
+ return void process2.on("uncaughtExceptionMonitor", (error, origin) => captureUncaughtException(captureFn, error, origin));
5433
+ process2.on("uncaughtException", makeUncaughtExceptionHandler(captureFn, onFatalFn));
4300
5434
  }
4301
- function addUnhandledRejectionListener(captureFn) {
4302
- globalThis.process?.on("unhandledRejection", (reason) => captureFn(reason, {
4303
- mechanism: {
4304
- type: "onunhandledrejection",
4305
- handled: false
4306
- }
4307
- }));
5435
+ function addUnhandledRejectionListener(captureFn, mode = STARTUP_UNHANDLED_REJECTION_MODE) {
5436
+ const process2 = globalThis.process;
5437
+ if (!process2 || mode === "throw" || mode === "strict" || mode === "warn-with-error-code")
5438
+ return;
5439
+ process2.on("unhandledRejection", (reason) => {
5440
+ captureFn(reason, {
5441
+ mechanism: {
5442
+ type: "onunhandledrejection",
5443
+ handled: false
5444
+ }
5445
+ });
5446
+ });
4308
5447
  }
4309
5448
 
4310
- // ../../../../../node_modules/.bun/posthog-node@5.35.12/node_modules/posthog-node/dist/extensions/error-tracking/index.mjs
5449
+ // ../../../../../node_modules/.bun/posthog-node@5.49.2/node_modules/posthog-node/dist/extensions/error-tracking/index.mjs
4311
5450
  var SHUTDOWN_TIMEOUT = 2000;
4312
5451
 
4313
- class ErrorTracking {
5452
+ class error_tracking_ErrorTracking {
4314
5453
  constructor(client, options, _logger) {
4315
5454
  this.client = client;
4316
5455
  this._exceptionAutocaptureEnabled = options.enableExceptionAutocapture || false;
4317
5456
  this._logger = _logger;
4318
5457
  this._rateLimiter = new BucketedRateLimiter({
4319
- refillRate: 1,
4320
- bucketSize: 10,
5458
+ ...resolveExceptionRateLimiterConfig(options),
4321
5459
  refillInterval: 1e4,
4322
5460
  _logger: this._logger
4323
5461
  });
@@ -4332,6 +5470,9 @@ class ErrorTracking {
4332
5470
  };
4333
5471
  const exceptionProperties = builder.buildFromUnknown(error, hint);
4334
5472
  exceptionProperties.$exception_list = await builder.modifyFrames(exceptionProperties.$exception_list);
5473
+ const injectedReleaseId = exports_error_tracking.getInjectedReleaseId();
5474
+ if (injectedReleaseId)
5475
+ properties.$release_id = injectedReleaseId;
4335
5476
  return {
4336
5477
  event: "$exception",
4337
5478
  distinctId,
@@ -4350,8 +5491,8 @@ class ErrorTracking {
4350
5491
  }
4351
5492
  onException(exception, hint) {
4352
5493
  this.client.addPendingPromise((async () => {
4353
- if (!ErrorTracking.isPreviouslyCapturedError(exception)) {
4354
- const eventMessage = await ErrorTracking.buildEventMessage(this.client.getErrorPropertiesBuilder(), exception, hint);
5494
+ if (!error_tracking_ErrorTracking.isPreviouslyCapturedError(exception)) {
5495
+ const eventMessage = await error_tracking_ErrorTracking.buildEventMessage(this.client.getErrorPropertiesBuilder(), exception, hint);
4355
5496
  const exceptionProperties = eventMessage.properties;
4356
5497
  const exceptionType = exceptionProperties?.$exception_list[0]?.type ?? "Exception";
4357
5498
  const isRateLimited = this._rateLimiter.consumeRateLimit(exceptionType);
@@ -4359,14 +5500,14 @@ class ErrorTracking {
4359
5500
  return void this._logger.info("Skipping exception capture because of client rate limiting.", {
4360
5501
  exception: exceptionType
4361
5502
  });
4362
- return this.client.capture(eventMessage);
5503
+ return this.client._capturePreparedEvent(eventMessage, false);
4363
5504
  }
4364
5505
  })());
4365
5506
  }
4366
5507
  async onFatalError(exception) {
4367
5508
  console.error(exception);
4368
5509
  await this.client.shutdown(SHUTDOWN_TIMEOUT);
4369
- process.exit(1);
5510
+ globalThis.process.exit(1);
4370
5511
  }
4371
5512
  isEnabled() {
4372
5513
  return !this.client.isDisabled && this._exceptionAutocaptureEnabled;
@@ -4376,7 +5517,7 @@ class ErrorTracking {
4376
5517
  }
4377
5518
  }
4378
5519
 
4379
- // ../../../../../node_modules/.bun/posthog-node@5.35.12/node_modules/posthog-node/dist/storage-memory.mjs
5520
+ // ../../../../../node_modules/.bun/posthog-node@5.49.2/node_modules/posthog-node/dist/storage-memory.mjs
4380
5521
  class PostHogMemoryStorage {
4381
5522
  getProperty(key) {
4382
5523
  return this._memoryStorage[key];
@@ -4389,7 +5530,452 @@ class PostHogMemoryStorage {
4389
5530
  }
4390
5531
  }
4391
5532
 
4392
- // ../../../../../node_modules/.bun/posthog-node@5.35.12/node_modules/posthog-node/dist/client.mjs
5533
+ // ../../../../../node_modules/.bun/posthog-node@5.49.2/node_modules/posthog-node/dist/capture-v1/config.mjs
5534
+ function isCaptureMode(value) {
5535
+ return value === "v0" || value === "v1";
5536
+ }
5537
+ function resolveCaptureMode() {
5538
+ const envMode = typeof process != "undefined" ? process.env?.POSTHOG_CAPTURE_MODE : undefined;
5539
+ return isCaptureMode(envMode) ? envMode : "v0";
5540
+ }
5541
+
5542
+ // ../../../../../node_modules/.bun/posthog-node@5.49.2/node_modules/posthog-node/dist/capture-v1/routing.mjs
5543
+ var AI_EVENT_PREFIX = "$ai_";
5544
+ var ANALYTICS_ROUTE = "analytics";
5545
+ var AI_ROUTE = "ai";
5546
+ function isLegacyOnlyEvent(message) {
5547
+ return typeof message.event == "string" && message.event.startsWith(AI_EVENT_PREFIX);
5548
+ }
5549
+
5550
+ // ../../../../../node_modules/.bun/posthog-node@5.49.2/node_modules/posthog-node/dist/capture-v1/errors.mjs
5551
+ class CaptureV1Error extends Error {
5552
+ constructor({ requestId, drops, retryExhausted, cause }) {
5553
+ super(CaptureV1Error.buildMessage(requestId, drops, retryExhausted, cause)), this.name = "CaptureV1Error";
5554
+ this.requestId = requestId;
5555
+ this.drops = drops;
5556
+ this.retryExhausted = retryExhausted;
5557
+ this.cause = cause;
5558
+ }
5559
+ static buildMessage(requestId, drops, retryExhausted, cause) {
5560
+ let message = `Capture V1 batch ${requestId} did not fully deliver: ${drops.length} dropped, ${retryExhausted.length} undelivered`;
5561
+ if (cause instanceof Error)
5562
+ message += ` (${cause.message})`;
5563
+ return message;
5564
+ }
5565
+ }
5566
+
5567
+ // ../../../../../node_modules/.bun/posthog-node@5.49.2/node_modules/posthog-node/dist/capture-v1/transform.mjs
5568
+ function coerceBool(value) {
5569
+ if (typeof value == "boolean")
5570
+ return value;
5571
+ if (typeof value == "number")
5572
+ return value !== 0;
5573
+ if (typeof value == "string") {
5574
+ const normalized = value.trim().toLowerCase();
5575
+ if (normalized === "true" || normalized === "1")
5576
+ return true;
5577
+ if (normalized === "false" || normalized === "0")
5578
+ return false;
5579
+ }
5580
+ }
5581
+ function coerceString(value) {
5582
+ return typeof value == "string" ? value : undefined;
5583
+ }
5584
+ var OPTION_SENTINELS = [
5585
+ {
5586
+ property: "$cookieless_mode",
5587
+ optionKey: "cookieless_mode",
5588
+ coerce: coerceBool
5589
+ },
5590
+ {
5591
+ property: "$ignore_sent_at",
5592
+ optionKey: "disable_skew_correction",
5593
+ coerce: coerceBool
5594
+ },
5595
+ {
5596
+ property: "$process_person_profile",
5597
+ optionKey: "process_person_profile",
5598
+ coerce: coerceBool
5599
+ },
5600
+ {
5601
+ property: "$product_tour_id",
5602
+ optionKey: "product_tour_id",
5603
+ coerce: coerceString
5604
+ }
5605
+ ];
5606
+ var TOPLEVEL_SENTINELS = [
5607
+ {
5608
+ property: "$session_id",
5609
+ field: "session_id"
5610
+ },
5611
+ {
5612
+ property: "$window_id",
5613
+ field: "window_id"
5614
+ }
5615
+ ];
5616
+ function isRecord2(value) {
5617
+ return typeof value == "object" && value !== null && !Array.isArray(value);
5618
+ }
5619
+ function toRfc3339(timestamp) {
5620
+ if (typeof timestamp == "string") {
5621
+ const asDate2 = new Date(timestamp);
5622
+ if (Number.isNaN(asDate2.getTime()))
5623
+ return new Date().toISOString();
5624
+ const normalized = asDate2.toISOString();
5625
+ const fractionalSeconds = timestamp.match(/\.(\d+)(?:Z|[+-]\d{2}:?\d{2})?$/i)?.[1];
5626
+ return fractionalSeconds && fractionalSeconds.length > 3 ? normalized.replace(/\.\d{3}Z$/, `.${fractionalSeconds}Z`) : normalized;
5627
+ }
5628
+ if (timestamp instanceof Date)
5629
+ return Number.isNaN(timestamp.getTime()) ? new Date().toISOString() : timestamp.toISOString();
5630
+ const asDate = timestamp == null ? new Date : new Date(timestamp);
5631
+ return Number.isNaN(asDate.getTime()) ? new Date().toISOString() : asDate.toISOString();
5632
+ }
5633
+ function relocateInto(properties, key, value) {
5634
+ if (value !== undefined && !(key in properties))
5635
+ properties[key] = value;
5636
+ }
5637
+ function buildV1Event(message) {
5638
+ const sourceProperties = isRecord2(message.properties) ? message.properties : {};
5639
+ const properties = {
5640
+ ...sourceProperties
5641
+ };
5642
+ const options = {};
5643
+ for (const { property, optionKey, coerce } of OPTION_SENTINELS)
5644
+ if (property in properties) {
5645
+ const coerced = coerce(properties[property]);
5646
+ if (coerced !== undefined)
5647
+ options[optionKey] = coerced;
5648
+ delete properties[property];
5649
+ }
5650
+ const topLevel = {};
5651
+ for (const { property, field } of TOPLEVEL_SENTINELS)
5652
+ if (property in properties) {
5653
+ const value = properties[property];
5654
+ if (typeof value == "string")
5655
+ topLevel[field] = value;
5656
+ delete properties[property];
5657
+ }
5658
+ delete properties.$lib;
5659
+ delete properties.$lib_version;
5660
+ relocateInto(properties, "$set", message.$set);
5661
+ relocateInto(properties, "$set_once", message.$set_once);
5662
+ return {
5663
+ event: String(message.event ?? ""),
5664
+ uuid: String(message.uuid ?? ""),
5665
+ distinct_id: String(message.distinct_id ?? ""),
5666
+ timestamp: toRfc3339(message.timestamp),
5667
+ ...topLevel,
5668
+ options,
5669
+ properties
5670
+ };
5671
+ }
5672
+ function buildV1Batch(messages, { createdAt, historicalMigration }) {
5673
+ const batch = {
5674
+ created_at: createdAt,
5675
+ batch: messages.map(buildV1Event)
5676
+ };
5677
+ if (historicalMigration)
5678
+ batch.historical_migration = true;
5679
+ return batch;
5680
+ }
5681
+
5682
+ // ../../../../../node_modules/.bun/posthog-node@5.49.2/node_modules/posthog-node/dist/capture-v1/sender.mjs
5683
+ var V1_ANALYTICS_PATH = "/i/v1/analytics/events";
5684
+ var DEFAULT_MAX_BACKOFF_MS = 30000;
5685
+ var RETRYABLE_STATUSES = new Set([
5686
+ 408,
5687
+ 500,
5688
+ 502,
5689
+ 503,
5690
+ 504
5691
+ ]);
5692
+
5693
+ class V1CaptureSender {
5694
+ constructor(config, hooks) {
5695
+ this.config = config;
5696
+ this.maxBackoffMs = config.maxBackoffMs ?? DEFAULT_MAX_BACKOFF_MS;
5697
+ this.fetchFn = hooks.fetch;
5698
+ this.onError = hooks.onError;
5699
+ this.now = hooks.now ?? Date.now;
5700
+ this.sleep = hooks.sleep ?? ((ms) => new Promise((resolve) => safeSetTimeout(resolve, ms)));
5701
+ this.generateRequestId = hooks.generateRequestId ?? uuidv7;
5702
+ this.compress = hooks.compress ?? gzipCompress;
5703
+ }
5704
+ async sendV1Batch(messages) {
5705
+ if (messages.length === 0)
5706
+ return;
5707
+ const requestId = this.generateRequestId();
5708
+ const createdAt = new Date(this.now()).toISOString();
5709
+ const { batch } = buildV1Batch(messages, {
5710
+ createdAt,
5711
+ historicalMigration: this.config.historicalMigration
5712
+ });
5713
+ const url = `${this.config.host}${V1_ANALYTICS_PATH}`;
5714
+ const drops = [];
5715
+ let pending = batch;
5716
+ const maxAttempts = Math.max(1, this.config.maxAttempts);
5717
+ for (let attempt = 1;attempt <= maxAttempts; attempt++) {
5718
+ const isLastAttempt = attempt === maxAttempts;
5719
+ const payload = safeJsonStringify({
5720
+ created_at: createdAt,
5721
+ ...this.config.historicalMigration ? {
5722
+ historical_migration: true
5723
+ } : {},
5724
+ batch: pending
5725
+ });
5726
+ let captureAttempt;
5727
+ let retryDelayMs;
5728
+ try {
5729
+ captureAttempt = await this.sendOnce(url, payload, attempt, requestId);
5730
+ const { response, signal } = captureAttempt;
5731
+ const { status } = response;
5732
+ if (status < 200 || status >= 300)
5733
+ if (!isLastAttempt && RETRYABLE_STATUSES.has(status)) {
5734
+ const retryAfterMs = this.parseRetryAfter(response);
5735
+ await captureAttempt.waitFor(captureAttempt.cancelBody()).catch(() => {});
5736
+ retryDelayMs = this.backoffDelay(attempt, retryAfterMs);
5737
+ } else {
5738
+ const httpError = await this.buildHttpError(response, status, captureAttempt.waitFor);
5739
+ return this.surfaceBatchFailure(requestId, drops, pending, httpError);
5740
+ }
5741
+ else {
5742
+ let parsed;
5743
+ try {
5744
+ parsed = await captureAttempt.waitFor(this.parseResponse(response));
5745
+ } catch (error) {
5746
+ if (signal.aborted)
5747
+ throw error;
5748
+ return this.surfaceBatchFailure(requestId, drops, pending, new Error(`Capture V1 returned an unparseable ${status} response body`));
5749
+ }
5750
+ const retryable = this.classify(pending, parsed, drops);
5751
+ if (retryable.length === 0)
5752
+ return this.surfacePartialDrops(requestId, drops);
5753
+ if (isLastAttempt)
5754
+ return void this.onError(new CaptureV1Error({
5755
+ requestId,
5756
+ drops,
5757
+ retryExhausted: retryable.map((event) => event.uuid)
5758
+ }));
5759
+ pending = retryable;
5760
+ const retryAfterMs = this.parseRetryAfter(response);
5761
+ retryDelayMs = this.backoffDelay(attempt, retryAfterMs);
5762
+ }
5763
+ } catch (transportError) {
5764
+ if (captureAttempt && !captureAttempt.signal.aborted)
5765
+ throw transportError;
5766
+ if (isLastAttempt)
5767
+ return this.surfaceBatchFailure(requestId, drops, pending, transportError);
5768
+ retryDelayMs = this.backoffDelay(attempt);
5769
+ } finally {
5770
+ captureAttempt?.cleanup();
5771
+ }
5772
+ if (retryDelayMs !== undefined)
5773
+ await this.sleep(retryDelayMs);
5774
+ }
5775
+ }
5776
+ async sendOnce(url, payload, attempt, requestId) {
5777
+ const headers = this.buildHeaders(attempt, requestId);
5778
+ let body = payload;
5779
+ if (this.config.compressionEnabled) {
5780
+ const compressed = await this.compress(payload, this.config.isDebug);
5781
+ if (compressed !== null) {
5782
+ body = compressed;
5783
+ headers["Content-Encoding"] = "gzip";
5784
+ }
5785
+ }
5786
+ const controller = new AbortController;
5787
+ let timeoutPhase = "waiting for response headers";
5788
+ let timer;
5789
+ const deadline = new Promise((_resolve, reject) => {
5790
+ timer = safeSetTimeout(() => {
5791
+ const timeoutError = new Error(`Capture V1 request timed out ${timeoutPhase} after ${this.config.requestTimeoutMs}ms`);
5792
+ timeoutError.name = "AbortError";
5793
+ reject(timeoutError);
5794
+ controller.abort(timeoutError);
5795
+ }, this.config.requestTimeoutMs);
5796
+ });
5797
+ try {
5798
+ const fetchPromise = this.fetchFn(url, {
5799
+ method: "POST",
5800
+ headers,
5801
+ body,
5802
+ signal: controller.signal
5803
+ });
5804
+ let responseAccepted = false;
5805
+ fetchPromise.then((lateResponse) => {
5806
+ if (controller.signal.aborted && !responseAccepted)
5807
+ this.cancelBody(lateResponse);
5808
+ }).catch(() => {});
5809
+ const response = await Promise.race([
5810
+ fetchPromise,
5811
+ deadline
5812
+ ]);
5813
+ responseAccepted = true;
5814
+ timeoutPhase = "while reading the response body";
5815
+ let cleanedUp = false;
5816
+ let cancellation;
5817
+ const cancelBody = () => cancellation ??= this.cancelBody(response);
5818
+ return {
5819
+ response,
5820
+ signal: controller.signal,
5821
+ waitFor: (operation) => Promise.race([
5822
+ operation,
5823
+ deadline
5824
+ ]),
5825
+ cancelBody,
5826
+ cleanup: () => {
5827
+ if (cleanedUp)
5828
+ return;
5829
+ cleanedUp = true;
5830
+ clearTimeout(timer);
5831
+ if (controller.signal.aborted)
5832
+ cancelBody();
5833
+ }
5834
+ };
5835
+ } catch (error) {
5836
+ clearTimeout(timer);
5837
+ throw error;
5838
+ }
5839
+ }
5840
+ buildHeaders(attempt, requestId) {
5841
+ const sdkInfo = `${this.config.libraryId}/${this.config.libraryVersion}`;
5842
+ const headers = {
5843
+ "Content-Type": "application/json",
5844
+ Authorization: `Bearer ${this.config.apiKey}`,
5845
+ "PostHog-Sdk-Info": sdkInfo,
5846
+ "PostHog-Attempt": String(attempt),
5847
+ "PostHog-Request-Id": requestId,
5848
+ "PostHog-Request-Timestamp": new Date(this.now()).toISOString()
5849
+ };
5850
+ if (this.config.userAgent)
5851
+ headers["User-Agent"] = this.config.userAgent;
5852
+ return headers;
5853
+ }
5854
+ classify(pending, parsed, drops) {
5855
+ const results = parsed.results ?? {};
5856
+ const retryable = [];
5857
+ for (const event of pending) {
5858
+ const result = results[event.uuid];
5859
+ if (result) {
5860
+ if (result.result === "drop")
5861
+ drops.push({
5862
+ uuid: event.uuid,
5863
+ details: result.details ?? undefined
5864
+ });
5865
+ else if (result.result === "retry")
5866
+ retryable.push(event);
5867
+ }
5868
+ }
5869
+ return retryable;
5870
+ }
5871
+ backoffDelay(attempt, retryAfterMs) {
5872
+ const exponential = Math.min(this.config.initialRetryDelayMs * 2 ** (attempt - 1), this.maxBackoffMs);
5873
+ if (retryAfterMs === undefined)
5874
+ return exponential;
5875
+ return Math.max(exponential, Math.min(retryAfterMs, this.maxBackoffMs));
5876
+ }
5877
+ parseRetryAfter(response) {
5878
+ const raw = response.headers?.get("Retry-After");
5879
+ if (!raw)
5880
+ return;
5881
+ const trimmed = raw.trim();
5882
+ if (/^\d+$/.test(trimmed)) {
5883
+ const seconds = parseInt(trimmed, 10);
5884
+ return Number.isFinite(seconds) && seconds > 0 ? 1000 * seconds : undefined;
5885
+ }
5886
+ const dateMs = Date.parse(trimmed);
5887
+ if (Number.isNaN(dateMs))
5888
+ return;
5889
+ const delta = dateMs - this.now();
5890
+ return delta > 0 ? delta : undefined;
5891
+ }
5892
+ async parseResponse(response) {
5893
+ const text = await response.text();
5894
+ const parsed = JSON.parse(text);
5895
+ if (typeof parsed != "object" || parsed === null || Array.isArray(parsed))
5896
+ throw new Error("unexpected response shape");
5897
+ const results = parsed.results;
5898
+ if (results !== undefined && (typeof results != "object" || results === null || Array.isArray(results)))
5899
+ throw new Error("unexpected results shape");
5900
+ return {
5901
+ results: results ?? {}
5902
+ };
5903
+ }
5904
+ async buildHttpError(response, status, waitFor) {
5905
+ let bodyText = "";
5906
+ try {
5907
+ bodyText = (await waitFor(response.text())).slice(0, 512);
5908
+ } catch {}
5909
+ const suffix = bodyText ? `: ${bodyText}` : "";
5910
+ return new Error(`Capture V1 request failed with HTTP ${status}${suffix}`);
5911
+ }
5912
+ surfaceBatchFailure(requestId, drops, pending, cause) {
5913
+ this.onError(new CaptureV1Error({
5914
+ requestId,
5915
+ drops,
5916
+ retryExhausted: pending.map((event) => event.uuid),
5917
+ cause
5918
+ }));
5919
+ }
5920
+ surfacePartialDrops(requestId, drops) {
5921
+ if (drops.length > 0)
5922
+ this.onError(new CaptureV1Error({
5923
+ requestId,
5924
+ drops,
5925
+ retryExhausted: []
5926
+ }));
5927
+ }
5928
+ async cancelBody(response) {
5929
+ try {
5930
+ await response.body?.cancel();
5931
+ } catch {}
5932
+ }
5933
+ }
5934
+
5935
+ // ../../../../../node_modules/.bun/posthog-node@5.49.2/node_modules/posthog-node/dist/ai-capture/routing.mjs
5936
+ var AI_CAPTURE_ROUTE = "ai-capture";
5937
+ var AI_CAPTURE_ENDPOINT_PATH = "/i/v0/ai/batch/";
5938
+ var AI_MAX_EVENT_BYTES = 8388608;
5939
+ var AI_BATCH_TARGET_BYTES = 5242880;
5940
+
5941
+ // ../../../../../node_modules/.bun/posthog-node@5.49.2/node_modules/posthog-node/dist/ai-capture/batching.mjs
5942
+ var encoder = new TextEncoder;
5943
+ function eventByteSize(message) {
5944
+ return encoder.encode(safeJsonStringify(message)).length;
5945
+ }
5946
+ function partitionAiBatch(messages, maxEventBytes = AI_MAX_EVENT_BYTES, targetBatchBytes = AI_BATCH_TARGET_BYTES) {
5947
+ const batches = [];
5948
+ const dropped = [];
5949
+ let current = [];
5950
+ let currentBytes = 0;
5951
+ for (const message of messages) {
5952
+ if (message === undefined)
5953
+ continue;
5954
+ const bytes = eventByteSize(message);
5955
+ if (bytes > maxEventBytes) {
5956
+ dropped.push({
5957
+ event: typeof message.event == "string" ? message.event : "unknown",
5958
+ bytes
5959
+ });
5960
+ continue;
5961
+ }
5962
+ if (current.length > 0 && currentBytes + bytes > targetBatchBytes) {
5963
+ batches.push(current);
5964
+ current = [];
5965
+ currentBytes = 0;
5966
+ }
5967
+ current.push(message);
5968
+ currentBytes += bytes;
5969
+ }
5970
+ if (current.length > 0)
5971
+ batches.push(current);
5972
+ return {
5973
+ batches,
5974
+ dropped
5975
+ };
5976
+ }
5977
+
5978
+ // ../../../../../node_modules/.bun/posthog-node@5.49.2/node_modules/posthog-node/dist/client.mjs
4393
5979
  var MINIMUM_POLLING_INTERVAL = 100;
4394
5980
  var THIRTY_SECONDS = 30000;
4395
5981
  var MAX_CACHE_SIZE = 50000;
@@ -4414,6 +6000,12 @@ function normalizeHost(value) {
4414
6000
  const normalizedValue = typeof value == "string" ? value.trim() : "";
4415
6001
  return normalizedValue || DEFAULT_NODE_HOST;
4416
6002
  }
6003
+ function normalizeUnsetPersonProperties(value) {
6004
+ const propertyNames = Array.isArray(value) ? value : [
6005
+ value
6006
+ ];
6007
+ return propertyNames.filter((propertyName) => typeof propertyName == "string" && propertyName.trim().length > 0);
6008
+ }
4417
6009
  function buildFlagEventProperties(flagValues) {
4418
6010
  if (!flagValues)
4419
6011
  return {};
@@ -4431,11 +6023,15 @@ class PostHogBackendClient extends PostHogCoreStateless {
4431
6023
  const normalizedApiKey = normalizeApiKey(apiKey);
4432
6024
  const normalizedOptions = {
4433
6025
  ...options,
6026
+ maxQueueSize: options.maxQueueSize ?? 1e4,
6027
+ flushInterval: options.flushInterval ?? 5000,
4434
6028
  host: normalizeHost(options.host),
4435
- personalApiKey: normalizePersonalApiKey(options.personalApiKey)
6029
+ personalApiKey: normalizePersonalApiKey(options.secretKey ?? options.personalApiKey)
4436
6030
  };
4437
- super(normalizedApiKey, normalizedOptions), this._memoryStorage = new PostHogMemoryStorage;
6031
+ super(normalizedApiKey, normalizedOptions), this._memoryStorage = new PostHogMemoryStorage, this._aiCaptureRouteActive = false, this._minimalFlagCalledEvents = false;
4438
6032
  this.options = normalizedOptions;
6033
+ this.captureMode = resolveCaptureMode();
6034
+ this.enableFullAiCapture = normalizedOptions.enableFullAiCapture === true;
4439
6035
  this.context = this.initializeContext();
4440
6036
  this.options.featureFlagsPollingInterval = typeof normalizedOptions.featureFlagsPollingInterval == "number" ? Math.max(normalizedOptions.featureFlagsPollingInterval, MINIMUM_POLLING_INTERVAL) : THIRTY_SECONDS;
4441
6037
  if (typeof normalizedOptions.waitUntilDebounceMs == "number")
@@ -4460,21 +6056,24 @@ class PostHogBackendClient extends PostHogCoreStateless {
4460
6056
  onLoad: (count) => {
4461
6057
  this._events.emit("localEvaluationFlagsLoaded", count);
4462
6058
  },
6059
+ onMinimalFlagCalledEvents: (enabled) => {
6060
+ this._minimalFlagCalledEvents = enabled;
6061
+ },
4463
6062
  customHeaders: this.getCustomHeaders(),
4464
6063
  cacheProvider: normalizedOptions.flagDefinitionCacheProvider,
4465
6064
  strictLocalEvaluation: normalizedOptions.strictLocalEvaluation
4466
6065
  });
4467
6066
  }
4468
- this.errorTracking = new ErrorTracking(this, normalizedOptions, this._logger);
6067
+ this.errorTracking = new error_tracking_ErrorTracking(this, normalizedOptions, this._logger);
4469
6068
  this.distinctIdHasSentFlagCalls = {};
4470
6069
  this.maxCacheSize = normalizedOptions.maxCacheSize || MAX_CACHE_SIZE;
4471
6070
  }
4472
- enqueue(type, message, options) {
4473
- super.enqueue(type, message, options);
6071
+ enqueue(type, message, options, explicitRoute) {
6072
+ super.enqueue(type, message, options, explicitRoute);
4474
6073
  this.scheduleDebouncedFlush();
4475
6074
  }
4476
6075
  async flush() {
4477
- const flushPromise = super.flush();
6076
+ const flushPromise = this.flushWithPendingPromises();
4478
6077
  const waitUntil = this.options.waitUntil;
4479
6078
  if (waitUntil && !this._waitUntilCycle)
4480
6079
  try {
@@ -4527,7 +6126,7 @@ class PostHogBackendClient extends PostHogCoreStateless {
4527
6126
  async resolveWaitUntilFlush() {
4528
6127
  const resolve = this._consumeWaitUntilCycle();
4529
6128
  try {
4530
- await super.flush();
6129
+ await this.flushWithPendingPromises();
4531
6130
  } catch {} finally {
4532
6131
  resolve?.();
4533
6132
  }
@@ -4541,12 +6140,103 @@ class PostHogBackendClient extends PostHogCoreStateless {
4541
6140
  fetch(url, options) {
4542
6141
  return this.options.fetch ? this.options.fetch(url, options) : fetch(url, options);
4543
6142
  }
6143
+ getQueueRouteKey(message) {
6144
+ return this.captureMode === "v1" && isLegacyOnlyEvent(message) ? AI_ROUTE : ANALYTICS_ROUTE;
6145
+ }
6146
+ persistedQueueKeyForRoute(route) {
6147
+ if (route === AI_CAPTURE_ROUTE)
6148
+ return types_PostHogPersistedProperty.AiCaptureQueue;
6149
+ return route === AI_ROUTE ? types_PostHogPersistedProperty.AiQueue : types_PostHogPersistedProperty.Queue;
6150
+ }
6151
+ getActiveQueueRoutes() {
6152
+ const routes = this.captureMode === "v1" ? [
6153
+ ANALYTICS_ROUTE,
6154
+ AI_ROUTE
6155
+ ] : [
6156
+ ANALYTICS_ROUTE
6157
+ ];
6158
+ if (this._aiCaptureRouteActive)
6159
+ routes.push(AI_CAPTURE_ROUTE);
6160
+ return routes;
6161
+ }
6162
+ getBatchEndpointPath(route) {
6163
+ return route === AI_CAPTURE_ROUTE ? AI_CAPTURE_ENDPOINT_PATH : super.getBatchEndpointPath(route);
6164
+ }
6165
+ async sendBatch(batchMessages, retryOptions, route = ANALYTICS_ROUTE) {
6166
+ if (route === AI_CAPTURE_ROUTE)
6167
+ return this.sendAiCaptureBatch(batchMessages, retryOptions);
6168
+ if (this.captureMode !== "v1" || route === AI_ROUTE)
6169
+ return super.sendBatch(batchMessages, retryOptions, route);
6170
+ const v1Events = batchMessages.filter((message) => message !== undefined);
6171
+ await this.getV1Sender().sendV1Batch(v1Events);
6172
+ }
6173
+ async sendAiCaptureBatch(batchMessages, retryOptions) {
6174
+ const { batches, dropped } = partitionAiBatch(batchMessages);
6175
+ for (const { event, bytes } of dropped) {
6176
+ const message = `Event ${event} (${bytes} bytes) exceeds the ${AI_MAX_EVENT_BYTES / 1048576}MiB limit for ${AI_CAPTURE_ENDPOINT_PATH}, dropping.`;
6177
+ this._logger.error(message);
6178
+ this._events.emit("error", new Error(message));
6179
+ }
6180
+ for (const batch of batches)
6181
+ await this.sendAiSubBatch(batch, retryOptions);
6182
+ }
6183
+ async sendAiSubBatch(batch, retryOptions) {
6184
+ try {
6185
+ await super.sendBatch(batch, retryOptions, AI_CAPTURE_ROUTE);
6186
+ } catch (err) {
6187
+ if (!isPostHogFetchContentTooLargeError(err))
6188
+ throw err;
6189
+ if (batch.length === 1) {
6190
+ const [event] = batch;
6191
+ const eventName = typeof event.event == "string" ? event.event : "unknown";
6192
+ const message = `Event ${eventName} (${eventByteSize(event)} bytes) was rejected with 413 by ${AI_CAPTURE_ENDPOINT_PATH} on its own, dropping.`;
6193
+ this._logger.error(message);
6194
+ this._events.emit("error", new Error(message));
6195
+ return;
6196
+ }
6197
+ const mid = Math.ceil(batch.length / 2);
6198
+ await this.sendAiSubBatch(batch.slice(0, mid), retryOptions);
6199
+ await this.sendAiSubBatch(batch.slice(mid), retryOptions);
6200
+ }
6201
+ }
6202
+ getV1Sender() {
6203
+ if (!this._v1Sender)
6204
+ this._v1Sender = new V1CaptureSender({
6205
+ host: this.host,
6206
+ apiKey: this.apiKey,
6207
+ libraryId: this.getLibraryId(),
6208
+ libraryVersion: this.getLibraryVersion(),
6209
+ userAgent: this.getCustomUserAgent() || undefined,
6210
+ historicalMigration: this.historicalMigration,
6211
+ compressionEnabled: !this.disableCompression,
6212
+ requestTimeoutMs: this.requestTimeout,
6213
+ maxAttempts: (this.options.fetchRetryCount ?? 3) + 1,
6214
+ initialRetryDelayMs: this.options.fetchRetryDelay ?? 3000,
6215
+ isDebug: this.isDebug
6216
+ }, {
6217
+ fetch: (url, fetchOptions) => this.fetch(url, fetchOptions),
6218
+ onError: (error) => this._events.emit("error", error),
6219
+ compress: (payload) => this.compressPayload(payload)
6220
+ });
6221
+ return this._v1Sender;
6222
+ }
4544
6223
  getLibraryVersion() {
4545
6224
  return version;
4546
6225
  }
6226
+ get metrics() {
6227
+ if (!this._metrics)
6228
+ this._metrics = new PostHogMetrics(this, resolveMetricsConfig(this.options.metrics), this._logger);
6229
+ return this._metrics;
6230
+ }
4547
6231
  getCustomUserAgent() {
4548
6232
  return `${this.getLibraryId()}/${this.getLibraryVersion()}`;
4549
6233
  }
6234
+ getCommonEventProperties() {
6235
+ const commonProperties = super.getCommonEventProperties();
6236
+ if (this.options.isServer ?? true)
6237
+ commonProperties.$is_server = true;
6238
+ return commonProperties;
6239
+ }
4550
6240
  enable() {
4551
6241
  return super.optIn();
4552
6242
  }
@@ -4557,33 +6247,69 @@ class PostHogBackendClient extends PostHogCoreStateless {
4557
6247
  super.debug(enabled);
4558
6248
  this.featureFlagsPoller?.debug(enabled);
4559
6249
  }
4560
- capture(props) {
6250
+ _warnIfInvalidCapture(props, stringArgumentWarning, exceptionCaptureWarning) {
4561
6251
  if (typeof props == "string")
4562
- this._logger.warn("Called capture() with a string as the first argument when an object was expected.");
6252
+ this._logger.warn(stringArgumentWarning);
4563
6253
  if (props.event === "$exception" && !props._originatedFromCaptureException)
4564
- this._logger.warn("Using `posthog.capture('$exception')` is unreliable because it does not attach required metadata. Use `posthog.captureException(error)` instead, which attaches required metadata automatically.");
4565
- this.addPendingPromise(this.prepareEventMessage(props).then(({ distinctId, event, properties, options }) => super.captureStateless(distinctId, event, properties, {
4566
- timestamp: options.timestamp,
4567
- disableGeoip: options.disableGeoip,
4568
- uuid: options.uuid
4569
- })).catch((err) => {
6254
+ this._logger.warn(exceptionCaptureWarning);
6255
+ }
6256
+ _sendPreparedEvent(type, props, immediate, prepareOptions, explicitRoute) {
6257
+ return this.addPendingPromise(this._prepareEventMessage(props, prepareOptions).then(({ distinctId, event, properties, options }) => {
6258
+ const captureOptions = {
6259
+ timestamp: options.timestamp,
6260
+ disableGeoip: options.disableGeoip,
6261
+ uuid: options.uuid
6262
+ };
6263
+ const message = {
6264
+ distinctId,
6265
+ event,
6266
+ properties: {
6267
+ ...properties,
6268
+ ...this.getCommonEventProperties()
6269
+ }
6270
+ };
6271
+ return immediate ? this.sendImmediate(type, message, captureOptions, explicitRoute) : this.enqueue(type, message, captureOptions, explicitRoute);
6272
+ }).catch((err) => {
4570
6273
  if (err)
4571
6274
  console.error(err);
4572
6275
  }));
4573
6276
  }
6277
+ _capturePreparedEvent(props, immediate) {
6278
+ return this._sendPreparedEvent("capture", props, immediate);
6279
+ }
6280
+ capture(props) {
6281
+ this._warnIfInvalidCapture(props, "Called capture() with a string as the first argument when an object was expected.", "Using `posthog.capture('$exception')` is unreliable because it does not attach required metadata. Use `posthog.captureException(error)` instead, which attaches required metadata automatically.");
6282
+ this._capturePreparedEvent(props, false);
6283
+ }
4574
6284
  async captureImmediate(props) {
4575
- if (typeof props == "string")
4576
- this._logger.warn("Called captureImmediate() with a string as the first argument when an object was expected.");
4577
- if (props.event === "$exception" && !props._originatedFromCaptureException)
4578
- this._logger.warn("Capturing a `$exception` event via `posthog.captureImmediate('$exception')` is unreliable because it does not attach required metadata. Use `posthog.captureExceptionImmediate(error)` instead, which attaches this metadata by default.");
4579
- return this.addPendingPromise(this.prepareEventMessage(props).then(({ distinctId, event, properties, options }) => super.captureStatelessImmediate(distinctId, event, properties, {
4580
- timestamp: options.timestamp,
4581
- disableGeoip: options.disableGeoip,
4582
- uuid: options.uuid
4583
- })).catch((err) => {
4584
- if (err)
4585
- console.error(err);
4586
- }));
6285
+ this._warnIfInvalidCapture(props, "Called captureImmediate() with a string as the first argument when an object was expected.", "Capturing a `$exception` event via `posthog.captureImmediate('$exception')` is unreliable because it does not attach required metadata. Use `posthog.captureExceptionImmediate(error)` instead, which attaches this metadata by default.");
6286
+ return this._capturePreparedEvent(props, true);
6287
+ }
6288
+ captureAi(props) {
6289
+ if (this.disabled)
6290
+ return;
6291
+ const uuid = getEventUuid(props.uuid, uuidv7);
6292
+ this._sendPreparedAiEvent({
6293
+ ...props,
6294
+ uuid
6295
+ }, false);
6296
+ return uuid;
6297
+ }
6298
+ async captureAiImmediate(props) {
6299
+ if (this.disabled)
6300
+ return;
6301
+ const uuid = getEventUuid(props.uuid, uuidv7);
6302
+ await this._sendPreparedAiEvent({
6303
+ ...props,
6304
+ uuid
6305
+ }, true);
6306
+ return uuid;
6307
+ }
6308
+ _sendPreparedAiEvent(props, immediate) {
6309
+ if (typeof props?.event == "string" && !props.event.startsWith("$ai_"))
6310
+ this._logger.debug(`captureAi called with non-AI event ${props.event}; routing it to the AI endpoint anyway.`);
6311
+ this._aiCaptureRouteActive = true;
6312
+ return this._sendPreparedEvent("capture", props, immediate, undefined, AI_CAPTURE_ROUTE);
4587
6313
  }
4588
6314
  identify({ distinctId, properties = {}, disableGeoip }) {
4589
6315
  const { $set, $set_once, $anon_distinct_id, ...rest } = properties;
@@ -4594,8 +6320,13 @@ class PostHogBackendClient extends PostHogCoreStateless {
4594
6320
  $set_once: setOnceProps,
4595
6321
  $anon_distinct_id: $anon_distinct_id ?? undefined
4596
6322
  };
4597
- super.identifyStateless(distinctId, eventProperties, {
6323
+ this._sendPreparedEvent("identify", {
6324
+ distinctId,
6325
+ event: "$identify",
6326
+ properties: eventProperties,
4598
6327
  disableGeoip
6328
+ }, false, {
6329
+ includeContextProperties: false
4599
6330
  });
4600
6331
  }
4601
6332
  async identifyImmediate({ distinctId, properties = {}, disableGeoip }) {
@@ -4607,18 +6338,65 @@ class PostHogBackendClient extends PostHogCoreStateless {
4607
6338
  $set_once: setOnceProps,
4608
6339
  $anon_distinct_id: $anon_distinct_id ?? undefined
4609
6340
  };
4610
- await super.identifyStatelessImmediate(distinctId, eventProperties, {
6341
+ await this._sendPreparedEvent("identify", {
6342
+ distinctId,
6343
+ event: "$identify",
6344
+ properties: eventProperties,
4611
6345
  disableGeoip
6346
+ }, true, {
6347
+ includeContextProperties: false
6348
+ });
6349
+ }
6350
+ setPersonProperties({ distinctId, properties = {}, propertiesOnce = {} }) {
6351
+ if (Object.keys(properties).length === 0 && Object.keys(propertiesOnce).length === 0)
6352
+ return;
6353
+ const eventProperties = {};
6354
+ if (Object.keys(properties).length > 0)
6355
+ eventProperties.$set = properties;
6356
+ if (Object.keys(propertiesOnce).length > 0)
6357
+ eventProperties.$set_once = propertiesOnce;
6358
+ this.capture({
6359
+ distinctId,
6360
+ event: "$set",
6361
+ properties: eventProperties
6362
+ });
6363
+ }
6364
+ unsetPersonProperties({ distinctId, properties }) {
6365
+ const propertyNames = normalizeUnsetPersonProperties(properties);
6366
+ if (propertyNames.length === 0)
6367
+ return;
6368
+ this.capture({
6369
+ distinctId,
6370
+ event: "$set",
6371
+ properties: {
6372
+ $unset: propertyNames
6373
+ }
4612
6374
  });
4613
6375
  }
4614
6376
  alias(data) {
4615
- super.aliasStateless(data.alias, data.distinctId, undefined, {
6377
+ this._sendPreparedEvent("alias", {
6378
+ distinctId: data.distinctId,
6379
+ event: "$create_alias",
6380
+ properties: {
6381
+ distinct_id: data.distinctId,
6382
+ alias: data.alias
6383
+ },
4616
6384
  disableGeoip: data.disableGeoip
6385
+ }, false, {
6386
+ includeContextProperties: false
4617
6387
  });
4618
6388
  }
4619
6389
  async aliasImmediate(data) {
4620
- await super.aliasStatelessImmediate(data.alias, data.distinctId, undefined, {
6390
+ await this._sendPreparedEvent("alias", {
6391
+ distinctId: data.distinctId,
6392
+ event: "$create_alias",
6393
+ properties: {
6394
+ distinct_id: data.distinctId,
6395
+ alias: data.alias
6396
+ },
4621
6397
  disableGeoip: data.disableGeoip
6398
+ }, true, {
6399
+ includeContextProperties: false
4622
6400
  });
4623
6401
  }
4624
6402
  isLocalEvaluationReady() {
@@ -4673,7 +6451,7 @@ class PostHogBackendClient extends PostHogCoreStateless {
4673
6451
  const adjustedProperties = this.addLocalPersonAndGroupProperties(distinctId, groups, personProperties, groupProperties);
4674
6452
  personProperties = adjustedProperties.allPersonProperties;
4675
6453
  groupProperties = adjustedProperties.allGroupProperties;
4676
- const evaluationContext = this.createFeatureFlagEvaluationContext(distinctId, groups, personProperties, groupProperties);
6454
+ const evaluationContext = this.createFeatureFlagEvaluationContext(distinctId, groups, this.personPropertiesForLocalEvaluation(distinctId, personProperties), groupProperties);
4677
6455
  if (onlyEvaluateLocally == undefined)
4678
6456
  onlyEvaluateLocally = this.options.strictLocalEvaluation ?? false;
4679
6457
  let result;
@@ -4684,6 +6462,7 @@ class PostHogBackendClient extends PostHogCoreStateless {
4684
6462
  let flagId;
4685
6463
  let flagVersion;
4686
6464
  let flagReason;
6465
+ let flagHasExperiment;
4687
6466
  const localEvaluationEnabled = this.featureFlagsPoller !== undefined;
4688
6467
  if (localEvaluationEnabled) {
4689
6468
  await this.featureFlagsPoller?.loadFeatureFlags();
@@ -4698,6 +6477,7 @@ class PostHogBackendClient extends PostHogCoreStateless {
4698
6477
  const value = localResult.value;
4699
6478
  flagId = flag.id;
4700
6479
  flagReason = "Evaluated locally";
6480
+ flagHasExperiment = flag.has_experiment;
4701
6481
  result = {
4702
6482
  key,
4703
6483
  enabled: value !== false,
@@ -4713,12 +6493,13 @@ class PostHogBackendClient extends PostHogCoreStateless {
4713
6493
  }
4714
6494
  }
4715
6495
  if (!flagWasLocallyEvaluated && !onlyEvaluateLocally) {
4716
- const flagsResponse = await super.getFeatureFlagDetailsStateless(evaluationContext.distinctId, evaluationContext.groups, evaluationContext.personProperties, evaluationContext.groupProperties, disableGeoip, [
6496
+ const flagsResponse = await super.getFeatureFlagDetailsStateless(evaluationContext.distinctId, evaluationContext.groups, personProperties, groupProperties, disableGeoip, [
4717
6497
  key
4718
6498
  ]);
4719
6499
  if (flagsResponse === undefined)
4720
6500
  featureFlagError = FeatureFlagError2.UNKNOWN_ERROR;
4721
6501
  else {
6502
+ this._minimalFlagCalledEvents = flagsResponse.minimalFlagCalledEvents === true;
4722
6503
  requestId = flagsResponse.requestId;
4723
6504
  evaluatedAt = flagsResponse.evaluatedAt;
4724
6505
  const errors = [];
@@ -4733,6 +6514,7 @@ class PostHogBackendClient extends PostHogCoreStateless {
4733
6514
  flagId = flagDetail.metadata?.id;
4734
6515
  flagVersion = flagDetail.metadata?.version;
4735
6516
  flagReason = flagDetail.reason?.description ?? flagDetail.reason?.code;
6517
+ flagHasExperiment = flagDetail.metadata?.has_experiment;
4736
6518
  let parsedPayload;
4737
6519
  if (flagDetail.metadata?.payload !== undefined)
4738
6520
  try {
@@ -4764,6 +6546,8 @@ class PostHogBackendClient extends PostHogCoreStateless {
4764
6546
  $feature_flag_request_id: requestId,
4765
6547
  $feature_flag_evaluated_at: flagWasLocallyEvaluated ? Date.now() : evaluatedAt
4766
6548
  };
6549
+ if (flagHasExperiment !== undefined)
6550
+ properties.$feature_flag_has_experiment = flagHasExperiment;
4767
6551
  if (flagWasLocallyEvaluated && this.featureFlagsPoller) {
4768
6552
  const flagDefinitionsLoadedAt = this.featureFlagsPoller.getFlagDefinitionsLoadedAt();
4769
6553
  if (flagDefinitionsLoadedAt !== undefined)
@@ -4878,7 +6662,7 @@ class PostHogBackendClient extends PostHogCoreStateless {
4878
6662
  const adjustedProperties = this.addLocalPersonAndGroupProperties(resolvedDistinctId, groups, personProperties, groupProperties);
4879
6663
  personProperties = adjustedProperties.allPersonProperties;
4880
6664
  groupProperties = adjustedProperties.allGroupProperties;
4881
- const evaluationContext = this.createFeatureFlagEvaluationContext(resolvedDistinctId, groups, personProperties, groupProperties);
6665
+ const evaluationContext = this.createFeatureFlagEvaluationContext(resolvedDistinctId, groups, this.personPropertiesForLocalEvaluation(resolvedDistinctId, personProperties), groupProperties);
4882
6666
  if (onlyEvaluateLocally == undefined)
4883
6667
  onlyEvaluateLocally = this.options.strictLocalEvaluation ?? false;
4884
6668
  const localEvaluationResult = await this.featureFlagsPoller?.getAllFlagsAndPayloads(evaluationContext, flagKeys);
@@ -4891,7 +6675,7 @@ class PostHogBackendClient extends PostHogCoreStateless {
4891
6675
  fallbackToFlags = localEvaluationResult.fallbackToFlags;
4892
6676
  }
4893
6677
  if (fallbackToFlags && !onlyEvaluateLocally) {
4894
- const remoteEvaluationResult = await super.getFeatureFlagsAndPayloadsStateless(evaluationContext.distinctId, evaluationContext.groups, evaluationContext.personProperties, evaluationContext.groupProperties, disableGeoip, flagKeys);
6678
+ const remoteEvaluationResult = await super.getFeatureFlagsAndPayloadsStateless(evaluationContext.distinctId, evaluationContext.groups, personProperties, groupProperties, disableGeoip, flagKeys);
4895
6679
  featureFlags = {
4896
6680
  ...featureFlags,
4897
6681
  ...remoteEvaluationResult.flags || {}
@@ -4939,7 +6723,7 @@ class PostHogBackendClient extends PostHogCoreStateless {
4939
6723
  const adjustedProperties = this.addLocalPersonAndGroupProperties(resolvedDistinctId, groups, personProperties, groupProperties);
4940
6724
  personProperties = adjustedProperties.allPersonProperties;
4941
6725
  groupProperties = adjustedProperties.allGroupProperties;
4942
- const evaluationContext = this.createFeatureFlagEvaluationContext(resolvedDistinctId, groups, personProperties, groupProperties);
6726
+ const evaluationContext = this.createFeatureFlagEvaluationContext(resolvedDistinctId, groups, this.personPropertiesForLocalEvaluation(resolvedDistinctId, personProperties), groupProperties);
4943
6727
  if (onlyEvaluateLocally == undefined)
4944
6728
  onlyEvaluateLocally = this.options.strictLocalEvaluation ?? false;
4945
6729
  const records = {};
@@ -4960,14 +6744,16 @@ class PostHogBackendClient extends PostHogCoreStateless {
4960
6744
  id: flagDef?.id,
4961
6745
  version: undefined,
4962
6746
  reason: "Evaluated locally",
4963
- locallyEvaluated: true
6747
+ locallyEvaluated: true,
6748
+ hasExperiment: flagDef?.has_experiment
4964
6749
  };
4965
6750
  locallyEvaluatedKeys.add(key);
4966
6751
  }
4967
6752
  const fallbackToFlags = localResult ? localResult.fallbackToFlags : true;
4968
6753
  if (fallbackToFlags && !onlyEvaluateLocally) {
4969
- const details = await super.getFeatureFlagDetailsStateless(evaluationContext.distinctId, evaluationContext.groups, evaluationContext.personProperties, evaluationContext.groupProperties, disableGeoip, flagKeys);
6754
+ const details = await super.getFeatureFlagDetailsStateless(evaluationContext.distinctId, evaluationContext.groups, personProperties, groupProperties, disableGeoip, flagKeys);
4970
6755
  if (details) {
6756
+ this._minimalFlagCalledEvents = details.minimalFlagCalledEvents === true;
4971
6757
  requestId = details.requestId;
4972
6758
  evaluatedAt = details.evaluatedAt;
4973
6759
  errorsWhileComputing = Boolean(details.errorsWhileComputingFlags);
@@ -4990,7 +6776,8 @@ class PostHogBackendClient extends PostHogCoreStateless {
4990
6776
  id: detail.metadata?.id,
4991
6777
  version: detail.metadata?.version,
4992
6778
  reason: detail.reason?.description ?? detail.reason?.code,
4993
- locallyEvaluated: false
6779
+ locallyEvaluated: false,
6780
+ hasExperiment: detail.metadata?.has_experiment
4994
6781
  };
4995
6782
  }
4996
6783
  }
@@ -5010,7 +6797,8 @@ class PostHogBackendClient extends PostHogCoreStateless {
5010
6797
  id: existing?.id,
5011
6798
  version: existing?.version,
5012
6799
  reason: existing?.reason,
5013
- locallyEvaluated: existing?.locallyEvaluated ?? false
6800
+ locallyEvaluated: existing?.locallyEvaluated ?? false,
6801
+ hasExperiment: existing?.hasExperiment
5014
6802
  };
5015
6803
  }
5016
6804
  if (this._payloadOverrides !== undefined)
@@ -5035,6 +6823,9 @@ class PostHogBackendClient extends PostHogCoreStateless {
5035
6823
  quotaLimited
5036
6824
  });
5037
6825
  }
6826
+ _shouldSendMinimalFlagCalledEvent(event, properties) {
6827
+ return event === "$feature_flag_called" && this._minimalFlagCalledEvents && properties.$feature_flag_has_experiment === false;
6828
+ }
5038
6829
  _captureFlagCalledEventIfNeeded(params) {
5039
6830
  const { distinctId, key, response, groups, disableGeoip, properties } = params;
5040
6831
  const groupSuffix = groups && Object.keys(groups).length > 0 ? `_${JSON.stringify(Object.entries(groups).sort(([a], [b]) => a < b ? -1 : a > b ? 1 : 0))}` : "";
@@ -5069,9 +6860,32 @@ class PostHogBackendClient extends PostHogCoreStateless {
5069
6860
  return this._featureFlagEvaluationsHost;
5070
6861
  }
5071
6862
  groupIdentify({ groupType, groupKey, properties, distinctId, disableGeoip }) {
5072
- super.groupIdentifyStateless(groupType, groupKey, properties, {
6863
+ this._sendPreparedEvent("capture", {
6864
+ distinctId: distinctId || `$${groupType}_${groupKey}`,
6865
+ event: "$groupidentify",
6866
+ properties: {
6867
+ $group_type: groupType,
6868
+ $group_key: groupKey,
6869
+ $group_set: properties || {}
6870
+ },
5073
6871
  disableGeoip
5074
- }, distinctId);
6872
+ }, false, {
6873
+ includeContextProperties: false
6874
+ });
6875
+ }
6876
+ async groupIdentifyImmediate({ groupType, groupKey, properties, distinctId, disableGeoip }) {
6877
+ await this._sendPreparedEvent("capture", {
6878
+ distinctId: distinctId || `$${groupType}_${groupKey}`,
6879
+ event: "$groupidentify",
6880
+ properties: {
6881
+ $group_type: groupType,
6882
+ $group_key: groupKey,
6883
+ $group_set: properties || {}
6884
+ },
6885
+ disableGeoip
6886
+ }, true, {
6887
+ includeContextProperties: false
6888
+ });
5075
6889
  }
5076
6890
  async reloadFeatureFlags() {
5077
6891
  await this.featureFlagsPoller?.loadFeatureFlags(true);
@@ -5143,12 +6957,18 @@ class PostHogBackendClient extends PostHogCoreStateless {
5143
6957
  this.context?.enter(data, options);
5144
6958
  }
5145
6959
  async _shutdown(shutdownTimeoutMs) {
6960
+ const shutdownDeadlineMs = Date.now() + (shutdownTimeoutMs ?? 30000);
5146
6961
  const resolve = this._consumeWaitUntilCycle();
5147
6962
  await this.featureFlagsPoller?.stopPoller(shutdownTimeoutMs);
5148
6963
  this.errorTracking.shutdown();
6964
+ if (this._metrics) {
6965
+ await raceWithTimeout(this._metrics.flush().catch(() => {}), Math.max(0, shutdownDeadlineMs - Date.now()));
6966
+ this._metrics.reset();
6967
+ }
5149
6968
  try {
5150
- return await super._shutdown(shutdownTimeoutMs);
6969
+ return await super._shutdown(Math.max(0, shutdownDeadlineMs - Date.now()));
5151
6970
  } finally {
6971
+ this.distinctIdHasSentFlagCalls = {};
5152
6972
  resolve?.();
5153
6973
  }
5154
6974
  }
@@ -5243,7 +7063,6 @@ class PostHogBackendClient extends PostHogCoreStateless {
5243
7063
  }
5244
7064
  addLocalPersonAndGroupProperties(distinctId, groups, personProperties, groupProperties) {
5245
7065
  const allPersonProperties = {
5246
- distinct_id: distinctId,
5247
7066
  ...personProperties || {}
5248
7067
  };
5249
7068
  const allGroupProperties = {};
@@ -5258,6 +7077,12 @@ class PostHogBackendClient extends PostHogCoreStateless {
5258
7077
  allGroupProperties
5259
7078
  };
5260
7079
  }
7080
+ personPropertiesForLocalEvaluation(distinctId, personProperties) {
7081
+ return {
7082
+ distinct_id: distinctId,
7083
+ ...personProperties || {}
7084
+ };
7085
+ }
5261
7086
  createFeatureFlagEvaluationContext(distinctId, groups, personProperties, groupProperties) {
5262
7087
  return {
5263
7088
  distinctId,
@@ -5268,21 +7093,21 @@ class PostHogBackendClient extends PostHogCoreStateless {
5268
7093
  };
5269
7094
  }
5270
7095
  captureException(error, distinctId, additionalProperties, uuid, flags) {
5271
- if (!ErrorTracking.isPreviouslyCapturedError(error)) {
7096
+ if (!error_tracking_ErrorTracking.isPreviouslyCapturedError(error)) {
5272
7097
  const syntheticException = new Error("PostHog syntheticException");
5273
- this.addPendingPromise(ErrorTracking.buildEventMessage(this.getErrorPropertiesBuilder(), error, {
7098
+ this.addPendingPromise(error_tracking_ErrorTracking.buildEventMessage(this.getErrorPropertiesBuilder(), error, {
5274
7099
  syntheticException
5275
- }, distinctId, additionalProperties).then((msg) => this.capture({
7100
+ }, distinctId, additionalProperties).then((msg) => this._capturePreparedEvent({
5276
7101
  ...msg,
5277
7102
  uuid,
5278
7103
  flags
5279
- })));
7104
+ }, false)));
5280
7105
  }
5281
7106
  }
5282
7107
  async captureExceptionImmediate(error, distinctId, additionalProperties, flags) {
5283
- if (!ErrorTracking.isPreviouslyCapturedError(error)) {
7108
+ if (!error_tracking_ErrorTracking.isPreviouslyCapturedError(error)) {
5284
7109
  const syntheticException = new Error("PostHog syntheticException");
5285
- return this.addPendingPromise(ErrorTracking.buildEventMessage(this.getErrorPropertiesBuilder(), error, {
7110
+ return this.addPendingPromise(error_tracking_ErrorTracking.buildEventMessage(this.getErrorPropertiesBuilder(), error, {
5286
7111
  syntheticException
5287
7112
  }, distinctId, additionalProperties).then((msg) => this.captureImmediate({
5288
7113
  ...msg,
@@ -5291,24 +7116,31 @@ class PostHogBackendClient extends PostHogCoreStateless {
5291
7116
  }
5292
7117
  }
5293
7118
  async prepareEventMessage(props) {
7119
+ return this._prepareEventMessage(props);
7120
+ }
7121
+ async _prepareEventMessage(props, options = {}) {
5294
7122
  const { distinctId, event, properties, groups, flags, sendFeatureFlags, timestamp, disableGeoip, uuid } = props;
5295
7123
  const contextData = this.context?.get();
7124
+ const includeContextProperties = options.includeContextProperties ?? true;
5296
7125
  let mergedDistinctId = distinctId || contextData?.distinctId;
5297
- const mergedProperties = {
7126
+ const mergedProperties = includeContextProperties ? {
5298
7127
  ...this.props,
5299
7128
  ...contextData?.properties || {},
5300
7129
  ...properties || {}
7130
+ } : {
7131
+ ...properties || {}
5301
7132
  };
5302
7133
  if (!mergedDistinctId) {
5303
7134
  mergedDistinctId = uuidv7();
5304
7135
  mergedProperties.$process_person_profile = false;
5305
7136
  }
5306
- if (contextData?.sessionId && !mergedProperties.$session_id)
7137
+ if (includeContextProperties && contextData?.sessionId && !mergedProperties.$session_id)
5307
7138
  mergedProperties.$session_id = contextData.sessionId;
7139
+ const finalProperties = this._shouldSendMinimalFlagCalledEvent(event, mergedProperties) ? minimizeFlagCalledEventProperties(mergedProperties) : mergedProperties;
5308
7140
  const eventMessage = this._runBeforeSend({
5309
7141
  distinctId: mergedDistinctId,
5310
7142
  event,
5311
- properties: mergedProperties,
7143
+ properties: finalProperties,
5312
7144
  groups,
5313
7145
  flags,
5314
7146
  sendFeatureFlags,
@@ -5332,12 +7164,14 @@ class PostHogBackendClient extends PostHogCoreStateless {
5332
7164
  }
5333
7165
  return {};
5334
7166
  }).catch(() => ({})).then((additionalProperties) => {
5335
- const props2 = {
7167
+ const resolvedGroups = eventMessage.groups || groups;
7168
+ return {
5336
7169
  ...additionalProperties,
5337
7170
  ...eventMessage.properties || {},
5338
- $groups: eventMessage.groups || groups
7171
+ ...resolvedGroups !== undefined && Object.keys(resolvedGroups).length > 0 ? {
7172
+ $groups: resolvedGroups
7173
+ } : {}
5339
7174
  };
5340
- return props2;
5341
7175
  });
5342
7176
  if (eventMessage.event === "$pageview" && this.options.__preview_capture_bot_pageviews && typeof eventProperties.$raw_user_agent == "string") {
5343
7177
  if (isBlockedUA(eventProperties.$raw_user_agent, this.options.custom_blocked_useragents || [])) {
@@ -5364,22 +7198,26 @@ class PostHogBackendClient extends PostHogCoreStateless {
5364
7198
  beforeSend
5365
7199
  ];
5366
7200
  let result = eventMessage;
5367
- for (const fn of fns) {
5368
- result = fn(result);
5369
- if (!result) {
5370
- this._logger.info(`Event '${eventMessage.event}' was rejected in beforeSend function`);
7201
+ for (const fn of fns)
7202
+ try {
7203
+ result = fn(result);
7204
+ if (!result) {
7205
+ this._logger.info(`Event '${eventMessage.event}' was rejected in beforeSend function`);
7206
+ return null;
7207
+ }
7208
+ if (!result.properties || Object.keys(result.properties).length === 0) {
7209
+ const message = `Event '${result.event}' has no properties after beforeSend function, this is likely an error.`;
7210
+ this._logger.warn(message);
7211
+ }
7212
+ } catch (error) {
7213
+ this._logger.error(`Error in before_send function for event '${eventMessage.event}':`, error);
5371
7214
  return null;
5372
7215
  }
5373
- if (!result.properties || Object.keys(result.properties).length === 0) {
5374
- const message = `Event '${result.event}' has no properties after beforeSend function, this is likely an error.`;
5375
- this._logger.warn(message);
5376
- }
5377
- }
5378
7216
  return result;
5379
7217
  }
5380
7218
  }
5381
7219
 
5382
- // ../../../../../node_modules/.bun/posthog-node@5.35.12/node_modules/posthog-node/dist/extensions/context/context.mjs
7220
+ // ../../../../../node_modules/.bun/posthog-node@5.49.2/node_modules/posthog-node/dist/extensions/context/context.mjs
5383
7221
  import { AsyncLocalStorage } from "node:async_hooks";
5384
7222
 
5385
7223
  class PostHogContext {
@@ -5410,7 +7248,24 @@ class PostHogContext {
5410
7248
  }
5411
7249
  }
5412
7250
 
5413
- // ../../../../../node_modules/.bun/posthog-node@5.35.12/node_modules/posthog-node/dist/extensions/sentry-integration.mjs
7251
+ // ../../../../../node_modules/.bun/posthog-node@5.49.2/node_modules/posthog-node/dist/gzip.node.mjs
7252
+ import { gzip } from "node:zlib";
7253
+ import { promisify } from "node:util";
7254
+ var gzipAsync = promisify(gzip);
7255
+ async function gzipCompress2(input, isDebug = true) {
7256
+ try {
7257
+ const compressed = await gzipAsync(input);
7258
+ return new Blob([
7259
+ new Uint8Array(compressed)
7260
+ ]);
7261
+ } catch (error) {
7262
+ if (isDebug)
7263
+ console.error("Failed to gzip compress data", error);
7264
+ return null;
7265
+ }
7266
+ }
7267
+
7268
+ // ../../../../../node_modules/.bun/posthog-node@5.49.2/node_modules/posthog-node/dist/extensions/sentry-integration.mjs
5414
7269
  var NAME = "posthog-node";
5415
7270
  function createEventProcessor(_posthog, { organization, projectId, prefix, severityAllowList = [
5416
7271
  "error"
@@ -5450,6 +7305,9 @@ function createEventProcessor(_posthog, { organization, projectId, prefix, sever
5450
7305
  $sentry_exception_type: exceptions[0]?.type,
5451
7306
  $sentry_tags: event.tags
5452
7307
  };
7308
+ const injectedReleaseId = exports_error_tracking.getInjectedReleaseId();
7309
+ if (injectedReleaseId)
7310
+ properties.$release_id = injectedReleaseId;
5453
7311
  if (organization && projectId)
5454
7312
  properties["$sentry_url"] = (prefix || "https://sentry.io/organizations/") + organization + "/issues/?project=" + projectId + "&query=" + event.event_id;
5455
7313
  if (sendExceptionsToPostHog)
@@ -5478,11 +7336,14 @@ class PostHogSentryIntegration {
5478
7336
  };
5479
7337
  }
5480
7338
  }
5481
- // ../../../../../node_modules/.bun/posthog-node@5.35.12/node_modules/posthog-node/dist/entrypoints/index.node.mjs
7339
+ // ../../../../../node_modules/.bun/posthog-node@5.49.2/node_modules/posthog-node/dist/entrypoints/index.node.mjs
5482
7340
  class PostHog extends PostHogBackendClient {
5483
7341
  getLibraryId() {
5484
7342
  return "posthog-node";
5485
7343
  }
7344
+ compressPayload(payload) {
7345
+ return gzipCompress2(payload, this.isDebug);
7346
+ }
5486
7347
  initializeContext() {
5487
7348
  return new PostHogContext;
5488
7349
  }
@@ -5495,7 +7356,7 @@ class PostHog extends PostHogBackendClient {
5495
7356
  new exports_error_tracking.PrimitiveCoercer
5496
7357
  ], exports_error_tracking.createStackParser("node:javascript", exports_error_tracking.nodeStackLineParser), [
5497
7358
  createModulerModifier(),
5498
- addSourceContext,
7359
+ (frames) => addSourceContext(frames, undefined, this._logger),
5499
7360
  createRelativePathModifier()
5500
7361
  ]);
5501
7362
  }