@zuplo/cli 6.71.21 → 6.71.23

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 (109) hide show
  1. package/node_modules/@posthog/core/dist/error-tracking/exception-steps.d.ts.map +1 -1
  2. package/node_modules/@posthog/core/dist/error-tracking/exception-steps.js +6 -24
  3. package/node_modules/@posthog/core/dist/error-tracking/exception-steps.mjs +7 -25
  4. package/node_modules/@posthog/core/dist/posthog-core-stateless.d.ts +6 -0
  5. package/node_modules/@posthog/core/dist/posthog-core-stateless.d.ts.map +1 -1
  6. package/node_modules/@posthog/core/dist/posthog-core-stateless.js +75 -17
  7. package/node_modules/@posthog/core/dist/posthog-core-stateless.mjs +73 -18
  8. package/node_modules/@posthog/core/dist/posthog-core.d.ts +2 -2
  9. package/node_modules/@posthog/core/dist/posthog-core.d.ts.map +1 -1
  10. package/node_modules/@posthog/core/dist/posthog-core.js +10 -6
  11. package/node_modules/@posthog/core/dist/posthog-core.mjs +11 -7
  12. package/node_modules/@posthog/core/dist/testing/PostHogCoreTestClient.d.ts +1 -0
  13. package/node_modules/@posthog/core/dist/testing/PostHogCoreTestClient.d.ts.map +1 -1
  14. package/node_modules/@posthog/core/dist/testing/PostHogCoreTestClient.js +3 -0
  15. package/node_modules/@posthog/core/dist/testing/PostHogCoreTestClient.mjs +3 -0
  16. package/node_modules/@posthog/core/dist/utils/promise-queue.d.ts +3 -0
  17. package/node_modules/@posthog/core/dist/utils/promise-queue.d.ts.map +1 -1
  18. package/node_modules/@posthog/core/dist/utils/promise-queue.js +15 -3
  19. package/node_modules/@posthog/core/dist/utils/promise-queue.mjs +15 -3
  20. package/node_modules/@posthog/core/dist/utils/string-utils.d.ts +1 -0
  21. package/node_modules/@posthog/core/dist/utils/string-utils.d.ts.map +1 -1
  22. package/node_modules/@posthog/core/dist/utils/string-utils.js +21 -0
  23. package/node_modules/@posthog/core/dist/utils/string-utils.mjs +19 -1
  24. package/node_modules/@posthog/core/package.json +1 -1
  25. package/node_modules/@posthog/core/src/error-tracking/exception-steps.ts +5 -42
  26. package/node_modules/@posthog/core/src/posthog-core-stateless.ts +118 -23
  27. package/node_modules/@posthog/core/src/posthog-core.ts +18 -7
  28. package/node_modules/@posthog/core/src/testing/PostHogCoreTestClient.ts +4 -0
  29. package/node_modules/@posthog/core/src/utils/promise-queue.ts +17 -4
  30. package/node_modules/@posthog/core/src/utils/string-utils.spec.ts +38 -1
  31. package/node_modules/@posthog/core/src/utils/string-utils.ts +42 -0
  32. package/node_modules/@posthog/types/dist/posthog.d.ts +12 -0
  33. package/node_modules/@posthog/types/dist/posthog.d.ts.map +1 -1
  34. package/node_modules/@posthog/types/package.json +1 -1
  35. package/node_modules/@posthog/types/src/posthog.ts +13 -0
  36. package/node_modules/@types/node/README.md +1 -1
  37. package/node_modules/@types/node/buffer.d.ts +64 -25
  38. package/node_modules/@types/node/crypto.d.ts +18 -5
  39. package/node_modules/@types/node/diagnostics_channel.d.ts +237 -3
  40. package/node_modules/@types/node/dns.d.ts +1 -1
  41. package/node_modules/@types/node/ffi.d.ts +486 -0
  42. package/node_modules/@types/node/fs/promises.d.ts +3 -0
  43. package/node_modules/@types/node/fs.d.ts +21 -6
  44. package/node_modules/@types/node/http.d.ts +25 -0
  45. package/node_modules/@types/node/index.d.ts +1 -0
  46. package/node_modules/@types/node/package.json +2 -2
  47. package/node_modules/@types/node/process.d.ts +14 -1
  48. package/node_modules/@types/node/quic.d.ts +92 -11
  49. package/node_modules/@types/node/sqlite.d.ts +55 -0
  50. package/node_modules/@types/node/stream/iter.d.ts +150 -0
  51. package/node_modules/@types/node/stream.d.ts +32 -0
  52. package/node_modules/@types/node/test.d.ts +112 -2
  53. package/node_modules/@types/node/ts5.6/index.d.ts +1 -0
  54. package/node_modules/@types/node/ts5.7/index.d.ts +1 -0
  55. package/node_modules/@types/node/util.d.ts +19 -2
  56. package/node_modules/@types/node/v8.d.ts +84 -2
  57. package/node_modules/@types/node/worker_threads.d.ts +8 -7
  58. package/node_modules/@zuplo/core/customer.cli.minified.js +2 -2
  59. package/node_modules/@zuplo/core/index.minified.js +2 -2
  60. package/node_modules/@zuplo/core/package.json +1 -1
  61. package/node_modules/@zuplo/graphql/out/esm/index.js +11 -11
  62. package/node_modules/@zuplo/graphql/out/esm/index.js.map +1 -1
  63. package/node_modules/@zuplo/graphql/package.json +1 -1
  64. package/node_modules/@zuplo/openapi-tools/package.json +1 -1
  65. package/node_modules/@zuplo/otel/package.json +1 -1
  66. package/node_modules/@zuplo/runtime/out/esm/{chunk-DQ4ANJLR.js → chunk-4MNJC7E2.js} +2 -2
  67. package/node_modules/@zuplo/runtime/out/esm/chunk-4MNJC7E2.js.map +1 -0
  68. package/node_modules/@zuplo/runtime/out/esm/{chunk-2Y72LML3.js → chunk-4QJJMELB.js} +2 -2
  69. package/node_modules/@zuplo/runtime/out/esm/{chunk-2Y72LML3.js.map → chunk-4QJJMELB.js.map} +1 -1
  70. package/node_modules/@zuplo/runtime/out/esm/chunk-5CYWMN74.js +402 -0
  71. package/node_modules/@zuplo/runtime/out/esm/chunk-5CYWMN74.js.map +1 -0
  72. package/node_modules/@zuplo/runtime/out/esm/{chunk-L3MZGNQA.js → chunk-DSZS6PZJ.js} +10 -10
  73. package/node_modules/@zuplo/runtime/out/esm/chunk-DSZS6PZJ.js.map +1 -0
  74. package/node_modules/@zuplo/runtime/out/esm/index.js +1 -1
  75. package/node_modules/@zuplo/runtime/out/esm/index.js.map +1 -1
  76. package/node_modules/@zuplo/runtime/out/esm/internal/index.js +1 -1
  77. package/node_modules/@zuplo/runtime/out/esm/mcp-gateway/index.js +7 -7
  78. package/node_modules/@zuplo/runtime/out/esm/mcp-gateway/index.js.map +1 -1
  79. package/node_modules/@zuplo/runtime/out/esm/mocks/index.js +1 -1
  80. package/node_modules/@zuplo/runtime/out/types/index.d.ts +1050 -18
  81. package/node_modules/@zuplo/runtime/out/types/mcp-gateway/index.d.ts +33 -7
  82. package/node_modules/@zuplo/runtime/package.json +1 -1
  83. package/node_modules/iconv-lite/encodings/sbcs-data.js +2 -0
  84. package/node_modules/iconv-lite/encodings/utf32.js +10 -3
  85. package/node_modules/iconv-lite/package.json +2 -2
  86. package/node_modules/iconv-lite/types/encodings.d.ts +2 -0
  87. package/node_modules/protobufjs/dist/light/protobuf.js +2 -2
  88. package/node_modules/protobufjs/dist/light/protobuf.min.js +2 -2
  89. package/node_modules/protobufjs/dist/minimal/protobuf.js +2 -2
  90. package/node_modules/protobufjs/dist/minimal/protobuf.min.js +2 -2
  91. package/node_modules/protobufjs/dist/protobuf.js +5 -2
  92. package/node_modules/protobufjs/dist/protobuf.js.map +1 -1
  93. package/node_modules/protobufjs/dist/protobuf.min.js +3 -3
  94. package/node_modules/protobufjs/dist/protobuf.min.js.map +1 -1
  95. package/node_modules/protobufjs/package.json +1 -1
  96. package/node_modules/protobufjs/src/parse.js +3 -0
  97. package/node_modules/toad-cache/README.md +10 -9
  98. package/node_modules/toad-cache/dist/toad-cache.cjs +139 -139
  99. package/node_modules/toad-cache/dist/toad-cache.mjs +136 -140
  100. package/node_modules/toad-cache/package.json +8 -8
  101. package/node_modules/toad-cache/toad-cache.d.cts +20 -14
  102. package/node_modules/toad-cache/toad-cache.d.ts +18 -14
  103. package/package.json +6 -6
  104. package/node_modules/@zuplo/runtime/out/esm/chunk-DQ4ANJLR.js.map +0 -1
  105. package/node_modules/@zuplo/runtime/out/esm/chunk-I5HLAHUY.js +0 -357
  106. package/node_modules/@zuplo/runtime/out/esm/chunk-I5HLAHUY.js.map +0 -1
  107. package/node_modules/@zuplo/runtime/out/esm/chunk-L3MZGNQA.js.map +0 -1
  108. /package/node_modules/@zuplo/runtime/out/esm/{chunk-I5HLAHUY.js.LEGAL.txt → chunk-5CYWMN74.js.LEGAL.txt} +0 -0
  109. /package/node_modules/@zuplo/runtime/out/esm/{chunk-L3MZGNQA.js.LEGAL.txt → chunk-DSZS6PZJ.js.LEGAL.txt} +0 -0
@@ -123,13 +123,16 @@ class PostHogCore extends external_posthog_core_stateless_js_namespaceObject.Pos
123
123
  };
124
124
  }
125
125
  enrichProperties(properties) {
126
- return {
126
+ const userProperties = properties || {};
127
+ const enriched = {
127
128
  ...this.props,
128
129
  ...this.sessionProps,
129
- ...properties || {},
130
+ ...userProperties,
130
131
  ...this.getCommonEventProperties(),
131
132
  $session_id: this.getSessionId()
132
133
  };
134
+ (0, external_posthog_core_stateless_js_namespaceObject.applyCallerFeatureFlagOverrides)(enriched, userProperties);
135
+ return enriched;
133
136
  }
134
137
  getSessionId() {
135
138
  if (!this._isInitialized) return '';
@@ -606,9 +609,10 @@ class PostHogCore extends external_posthog_core_stateless_js_namespaceObject.Pos
606
609
  payload
607
610
  };
608
611
  }
609
- getFeatureFlag(key) {
612
+ getFeatureFlag(key, options) {
610
613
  const result = this._getFeatureFlagResult(key, {
611
- missingFlagBehavior: 'getFeatureFlag'
614
+ missingFlagBehavior: 'getFeatureFlag',
615
+ sendEvent: options?.sendEvent
612
616
  });
613
617
  return result?.variant ?? result?.enabled;
614
618
  }
@@ -653,8 +657,8 @@ class PostHogCore extends external_posthog_core_stateless_js_namespaceObject.Pos
653
657
  payloads
654
658
  };
655
659
  }
656
- isFeatureEnabled(key) {
657
- const response = this.getFeatureFlag(key);
660
+ isFeatureEnabled(key, options) {
661
+ const response = this.getFeatureFlag(key, options);
658
662
  if (void 0 === response) return;
659
663
  return !!response;
660
664
  }
@@ -1,6 +1,6 @@
1
1
  import { createFlagsResponseFromFlagsAndPayloads, flagDetailsToResults, getEnabledFromValue, getFeatureFlagValue, getFlagValuesFromFlags, getPayloadsFromFlags, getVariantFromValue, normalizeFlagsResponse, parsePayload, updateFlagValue } from "./featureFlagUtils.mjs";
2
2
  import { Compression, FeatureFlagError, PostHogPersistedProperty } from "./types.mjs";
3
- import { PostHogCoreStateless, QuotaLimitedFeature, maybeAdd } from "./posthog-core-stateless.mjs";
3
+ import { PostHogCoreStateless, QuotaLimitedFeature, applyCallerFeatureFlagOverrides, maybeAdd } from "./posthog-core-stateless.mjs";
4
4
  import { uuidv7 } from "./vendor/uuidv7.mjs";
5
5
  import { getEventUuid, getPersonPropertiesHash, isArray, isEmptyObject, isNullish, isObject, isString } from "./utils/index.mjs";
6
6
  class PostHogCore extends PostHogCoreStateless {
@@ -95,13 +95,16 @@ class PostHogCore extends PostHogCoreStateless {
95
95
  };
96
96
  }
97
97
  enrichProperties(properties) {
98
- return {
98
+ const userProperties = properties || {};
99
+ const enriched = {
99
100
  ...this.props,
100
101
  ...this.sessionProps,
101
- ...properties || {},
102
+ ...userProperties,
102
103
  ...this.getCommonEventProperties(),
103
104
  $session_id: this.getSessionId()
104
105
  };
106
+ applyCallerFeatureFlagOverrides(enriched, userProperties);
107
+ return enriched;
105
108
  }
106
109
  getSessionId() {
107
110
  if (!this._isInitialized) return '';
@@ -578,9 +581,10 @@ class PostHogCore extends PostHogCoreStateless {
578
581
  payload
579
582
  };
580
583
  }
581
- getFeatureFlag(key) {
584
+ getFeatureFlag(key, options) {
582
585
  const result = this._getFeatureFlagResult(key, {
583
- missingFlagBehavior: 'getFeatureFlag'
586
+ missingFlagBehavior: 'getFeatureFlag',
587
+ sendEvent: options?.sendEvent
584
588
  });
585
589
  return result?.variant ?? result?.enabled;
586
590
  }
@@ -625,8 +629,8 @@ class PostHogCore extends PostHogCoreStateless {
625
629
  payloads
626
630
  };
627
631
  }
628
- isFeatureEnabled(key) {
629
- const response = this.getFeatureFlag(key);
632
+ isFeatureEnabled(key, options) {
633
+ const response = this.getFeatureFlag(key, options);
630
634
  if (void 0 === response) return;
631
635
  return !!response;
632
636
  }
@@ -12,6 +12,7 @@ export declare class PostHogCoreTestClient extends PostHogCore {
12
12
  _cachedDistinctId?: string;
13
13
  constructor(mocks: PostHogCoreTestClientMocks, apiKey: string, options?: PostHogCoreOptions);
14
14
  getFlags(distinctId: string, groups?: Record<string, string | number>, personProperties?: Record<string, string>, groupProperties?: Record<string, Record<string, string>>, extraPayload?: Record<string, any>): Promise<GetFlagsResult>;
15
+ flushWithPendingPromises(): Promise<void>;
15
16
  getPersistedProperty<T>(key: string): T;
16
17
  setPersistedProperty<T>(key: string, value: T | null): void;
17
18
  fetch(url: string, options: PostHogFetchOptions): Promise<PostHogFetchResponse>;
@@ -1 +1 @@
1
- {"version":3,"file":"PostHogCoreTestClient.d.ts","sourceRoot":"","sources":["../../src/testing/PostHogCoreTestClient.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,MAAM,gBAAgB,CAAA;AAC5C,OAAO,KAAK,EAAE,cAAc,EAAE,QAAQ,EAAE,kBAAkB,EAAE,mBAAmB,EAAE,oBAAoB,EAAE,MAAM,SAAS,CAAA;AAItH,MAAM,WAAW,0BAA0B;IACzC,KAAK,EAAE,IAAI,CAAC,IAAI,CAAC,OAAO,CAAC,oBAAoB,CAAC,EAAE,CAAC,MAAM,EAAE,mBAAmB,CAAC,CAAC,CAAA;IAC9E,OAAO,EAAE;QACP,OAAO,EAAE,IAAI,CAAC,IAAI,CAAC,GAAG,GAAG,SAAS,EAAE,CAAC,MAAM,CAAC,CAAC,CAAA;QAC7C,OAAO,EAAE,IAAI,CAAC,IAAI,CAAC,IAAI,EAAE,CAAC,MAAM,EAAE,GAAG,GAAG,IAAI,CAAC,CAAC,CAAA;KAC/C,CAAA;CACF;AAED,qBAAa,qBAAsB,SAAQ,WAAW;IAIlD,OAAO,CAAC,KAAK;IAHR,iBAAiB,CAAC,EAAE,MAAM,CAAA;gBAGvB,KAAK,EAAE,0BAA0B,EACzC,MAAM,EAAE,MAAM,EACd,OAAO,CAAC,EAAE,kBAAkB;IAQvB,QAAQ,CACb,UAAU,EAAE,MAAM,EAClB,MAAM,GAAE,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,CAAM,EAC5C,gBAAgB,GAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAM,EAC7C,eAAe,GAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAM,EAC5D,YAAY,GAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAM,GACrC,OAAO,CAAC,cAAc,CAAC;IAI1B,oBAAoB,CAAC,CAAC,EAAE,GAAG,EAAE,MAAM,GAAG,CAAC;IAGvC,oBAAoB,CAAC,CAAC,EAAE,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,CAAC,GAAG,IAAI,GAAG,IAAI;IAG3D,KAAK,CAAC,GAAG,EAAE,MAAM,EAAE,OAAO,EAAE,mBAAmB,GAAG,OAAO,CAAC,oBAAoB,CAAC;IAG/E,YAAY,IAAI,MAAM;IAGtB,iBAAiB,IAAI,MAAM;IAG3B,kBAAkB,IAAI,MAAM;CAG7B;AAED,eAAO,MAAM,gBAAgB,GAC3B,QAAQ,MAAM,EACd,UAAU,kBAAkB,EAC5B,aAAa,CAAC,KAAK,EAAE,0BAA0B,KAAK,IAAI,EACxD,eAAc;IAAE,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,GAAG,QAAQ,CAAA;CAAO,KACtD,CAAC,qBAAqB,EAAE,0BAA0B,CAsBpD,CAAA"}
1
+ {"version":3,"file":"PostHogCoreTestClient.d.ts","sourceRoot":"","sources":["../../src/testing/PostHogCoreTestClient.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,MAAM,gBAAgB,CAAA;AAC5C,OAAO,KAAK,EAAE,cAAc,EAAE,QAAQ,EAAE,kBAAkB,EAAE,mBAAmB,EAAE,oBAAoB,EAAE,MAAM,SAAS,CAAA;AAItH,MAAM,WAAW,0BAA0B;IACzC,KAAK,EAAE,IAAI,CAAC,IAAI,CAAC,OAAO,CAAC,oBAAoB,CAAC,EAAE,CAAC,MAAM,EAAE,mBAAmB,CAAC,CAAC,CAAA;IAC9E,OAAO,EAAE;QACP,OAAO,EAAE,IAAI,CAAC,IAAI,CAAC,GAAG,GAAG,SAAS,EAAE,CAAC,MAAM,CAAC,CAAC,CAAA;QAC7C,OAAO,EAAE,IAAI,CAAC,IAAI,CAAC,IAAI,EAAE,CAAC,MAAM,EAAE,GAAG,GAAG,IAAI,CAAC,CAAC,CAAA;KAC/C,CAAA;CACF;AAED,qBAAa,qBAAsB,SAAQ,WAAW;IAIlD,OAAO,CAAC,KAAK;IAHR,iBAAiB,CAAC,EAAE,MAAM,CAAA;gBAGvB,KAAK,EAAE,0BAA0B,EACzC,MAAM,EAAE,MAAM,EACd,OAAO,CAAC,EAAE,kBAAkB;IAQvB,QAAQ,CACb,UAAU,EAAE,MAAM,EAClB,MAAM,GAAE,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,CAAM,EAC5C,gBAAgB,GAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAM,EAC7C,eAAe,GAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAM,EAC5D,YAAY,GAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAM,GACrC,OAAO,CAAC,cAAc,CAAC;IAInB,wBAAwB,IAAI,OAAO,CAAC,IAAI,CAAC;IAIhD,oBAAoB,CAAC,CAAC,EAAE,GAAG,EAAE,MAAM,GAAG,CAAC;IAGvC,oBAAoB,CAAC,CAAC,EAAE,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,CAAC,GAAG,IAAI,GAAG,IAAI;IAG3D,KAAK,CAAC,GAAG,EAAE,MAAM,EAAE,OAAO,EAAE,mBAAmB,GAAG,OAAO,CAAC,oBAAoB,CAAC;IAG/E,YAAY,IAAI,MAAM;IAGtB,iBAAiB,IAAI,MAAM;IAG3B,kBAAkB,IAAI,MAAM;CAG7B;AAED,eAAO,MAAM,gBAAgB,GAC3B,QAAQ,MAAM,EACd,UAAU,kBAAkB,EAC5B,aAAa,CAAC,KAAK,EAAE,0BAA0B,KAAK,IAAI,EACxD,eAAc;IAAE,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,GAAG,QAAQ,CAAA;CAAO,KACtD,CAAC,qBAAqB,EAAE,0BAA0B,CAsBpD,CAAA"}
@@ -37,6 +37,9 @@ class PostHogCoreTestClient extends external_posthog_core_js_namespaceObject.Pos
37
37
  getFlags(distinctId, groups = {}, personProperties = {}, groupProperties = {}, extraPayload = {}) {
38
38
  return super.getFlags(distinctId, groups, personProperties, groupProperties, extraPayload);
39
39
  }
40
+ flushWithPendingPromises() {
41
+ return super.flushWithPendingPromises();
42
+ }
40
43
  getPersistedProperty(key) {
41
44
  return this.mocks.storage.getItem(key);
42
45
  }
@@ -8,6 +8,9 @@ class PostHogCoreTestClient extends PostHogCore {
8
8
  getFlags(distinctId, groups = {}, personProperties = {}, groupProperties = {}, extraPayload = {}) {
9
9
  return super.getFlags(distinctId, groups, personProperties, groupProperties, extraPayload);
10
10
  }
11
+ flushWithPendingPromises() {
12
+ return super.flushWithPendingPromises();
13
+ }
11
14
  getPersistedProperty(key) {
12
15
  return this.mocks.storage.getItem(key);
13
16
  }
@@ -1,7 +1,10 @@
1
1
  export declare class PromiseQueue {
2
2
  private promiseByIds;
3
+ private nextId;
3
4
  add(promise: Promise<any>): Promise<any>;
4
5
  join(): Promise<void>;
6
+ getPromises(ignoredPromises?: Promise<any>[], maxId?: number): Promise<any>[];
7
+ get maxId(): number;
5
8
  get length(): number;
6
9
  }
7
10
  //# sourceMappingURL=promise-queue.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"promise-queue.d.ts","sourceRoot":"","sources":["../../src/utils/promise-queue.ts"],"names":[],"mappings":"AAEA,qBAAa,YAAY;IACvB,OAAO,CAAC,YAAY,CAAmC;IAEhD,GAAG,CAAC,OAAO,EAAE,OAAO,CAAC,GAAG,CAAC,GAAG,OAAO,CAAC,GAAG,CAAC;IAWlC,IAAI,IAAI,OAAO,CAAC,IAAI,CAAC;IAUlC,IAAW,MAAM,IAAI,MAAM,CAE1B;CACF"}
1
+ {"version":3,"file":"promise-queue.d.ts","sourceRoot":"","sources":["../../src/utils/promise-queue.ts"],"names":[],"mappings":"AAEA,qBAAa,YAAY;IACvB,OAAO,CAAC,YAAY,CAA4D;IAChF,OAAO,CAAC,MAAM,CAAY;IAEnB,GAAG,CAAC,OAAO,EAAE,OAAO,CAAC,GAAG,CAAC,GAAG,OAAO,CAAC,GAAG,CAAC;IAYlC,IAAI,IAAI,OAAO,CAAC,IAAI,CAAC;IAU3B,WAAW,CAAC,eAAe,GAAE,OAAO,CAAC,GAAG,CAAC,EAAO,EAAE,KAAK,GAAE,MAAoB,GAAG,OAAO,CAAC,GAAG,CAAC,EAAE;IAOrG,IAAW,KAAK,IAAI,MAAM,CAEzB;IAED,IAAW,MAAM,IAAI,MAAM,CAE1B;CACF"}
@@ -30,26 +30,38 @@ const uuidv7_js_namespaceObject = require("../vendor/uuidv7.js");
30
30
  class PromiseQueue {
31
31
  add(promise) {
32
32
  const promiseUUID = (0, uuidv7_js_namespaceObject.uuidv7)();
33
- this.promiseByIds[promiseUUID] = promise;
33
+ const id = ++this.nextId;
34
+ this.promiseByIds[promiseUUID] = {
35
+ id,
36
+ promise
37
+ };
34
38
  promise.catch(()=>{}).finally(()=>{
35
39
  delete this.promiseByIds[promiseUUID];
36
40
  });
37
41
  return promise;
38
42
  }
39
43
  async join() {
40
- let promises = Object.values(this.promiseByIds);
44
+ let promises = Object.values(this.promiseByIds).map((item)=>item.promise);
41
45
  let length = promises.length;
42
46
  while(length > 0){
43
47
  await Promise.all(promises);
44
- promises = Object.values(this.promiseByIds);
48
+ promises = Object.values(this.promiseByIds).map((item)=>item.promise);
45
49
  length = promises.length;
46
50
  }
47
51
  }
52
+ getPromises(ignoredPromises = [], maxId = this.nextId) {
53
+ const ignoredPromiseSet = new Set(ignoredPromises);
54
+ return Object.values(this.promiseByIds).filter((item)=>item.id <= maxId && !ignoredPromiseSet.has(item.promise)).map((item)=>item.promise);
55
+ }
56
+ get maxId() {
57
+ return this.nextId;
58
+ }
48
59
  get length() {
49
60
  return Object.keys(this.promiseByIds).length;
50
61
  }
51
62
  constructor(){
52
63
  this.promiseByIds = {};
64
+ this.nextId = 0;
53
65
  }
54
66
  }
55
67
  exports.PromiseQueue = __webpack_exports__.PromiseQueue;
@@ -2,26 +2,38 @@ import { uuidv7 } from "../vendor/uuidv7.mjs";
2
2
  class PromiseQueue {
3
3
  add(promise) {
4
4
  const promiseUUID = uuidv7();
5
- this.promiseByIds[promiseUUID] = promise;
5
+ const id = ++this.nextId;
6
+ this.promiseByIds[promiseUUID] = {
7
+ id,
8
+ promise
9
+ };
6
10
  promise.catch(()=>{}).finally(()=>{
7
11
  delete this.promiseByIds[promiseUUID];
8
12
  });
9
13
  return promise;
10
14
  }
11
15
  async join() {
12
- let promises = Object.values(this.promiseByIds);
16
+ let promises = Object.values(this.promiseByIds).map((item)=>item.promise);
13
17
  let length = promises.length;
14
18
  while(length > 0){
15
19
  await Promise.all(promises);
16
- promises = Object.values(this.promiseByIds);
20
+ promises = Object.values(this.promiseByIds).map((item)=>item.promise);
17
21
  length = promises.length;
18
22
  }
19
23
  }
24
+ getPromises(ignoredPromises = [], maxId = this.nextId) {
25
+ const ignoredPromiseSet = new Set(ignoredPromises);
26
+ return Object.values(this.promiseByIds).filter((item)=>item.id <= maxId && !ignoredPromiseSet.has(item.promise)).map((item)=>item.promise);
27
+ }
28
+ get maxId() {
29
+ return this.nextId;
30
+ }
20
31
  get length() {
21
32
  return Object.keys(this.promiseByIds).length;
22
33
  }
23
34
  constructor(){
24
35
  this.promiseByIds = {};
36
+ this.nextId = 0;
25
37
  }
26
38
  }
27
39
  export { PromiseQueue };
@@ -4,6 +4,7 @@ export declare function includes<T>(arr: T[], needle: T): boolean;
4
4
  export declare const trim: (str: string) => string;
5
5
  export declare const stripLeadingDollar: (s: string) => string;
6
6
  export declare function isDistinctIdStringLike(value: string): boolean;
7
+ export declare function safeJsonStringify(value: unknown): string;
7
8
  /**
8
9
  * Creates a hash string from distinct_id and person properties.
9
10
  * Used to detect if person properties have changed to avoid duplicate $set events.
@@ -1 +1 @@
1
- {"version":3,"file":"string-utils.d.ts","sourceRoot":"","sources":["../../src/utils/string-utils.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,UAAU,CAAA;AAExC,wBAAgB,QAAQ,CAAC,GAAG,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,OAAO,CAAA;AAC9D,wBAAgB,QAAQ,CAAC,CAAC,EAAE,GAAG,EAAE,CAAC,EAAE,EAAE,MAAM,EAAE,CAAC,GAAG,OAAO,CAAA;AAKzD,eAAO,MAAM,IAAI,GAAa,KAAK,MAAM,KAAG,MAM3C,CAAA;AAID,eAAO,MAAM,kBAAkB,GAAa,GAAG,MAAM,KAAG,MAEvD,CAAA;AAED,wBAAgB,sBAAsB,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAE7D;AAuBD;;;;GAIG;AACH,wBAAgB,uBAAuB,CACrC,WAAW,EAAE,MAAM,EACnB,mBAAmB,CAAC,EAAE;IAAE,CAAC,GAAG,EAAE,MAAM,GAAG,QAAQ,CAAA;CAAE,EACjD,uBAAuB,CAAC,EAAE;IAAE,CAAC,GAAG,EAAE,MAAM,GAAG,QAAQ,CAAA;CAAE,GACpD,MAAM,CAMR"}
1
+ {"version":3,"file":"string-utils.d.ts","sourceRoot":"","sources":["../../src/utils/string-utils.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,UAAU,CAAA;AAExC,wBAAgB,QAAQ,CAAC,GAAG,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,OAAO,CAAA;AAC9D,wBAAgB,QAAQ,CAAC,CAAC,EAAE,GAAG,EAAE,CAAC,EAAE,EAAE,MAAM,EAAE,CAAC,GAAG,OAAO,CAAA;AAKzD,eAAO,MAAM,IAAI,GAAa,KAAK,MAAM,KAAG,MAM3C,CAAA;AAID,eAAO,MAAM,kBAAkB,GAAa,GAAG,MAAM,KAAG,MAEvD,CAAA;AAED,wBAAgB,sBAAsB,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAE7D;AAED,wBAAgB,iBAAiB,CAAC,KAAK,EAAE,OAAO,GAAG,MAAM,CAwCxD;AAuBD;;;;GAIG;AACH,wBAAgB,uBAAuB,CACrC,WAAW,EAAE,MAAM,EACnB,mBAAmB,CAAC,EAAE;IAAE,CAAC,GAAG,EAAE,MAAM,GAAG,QAAQ,CAAA;CAAE,EACjD,uBAAuB,CAAC,EAAE;IAAE,CAAC,GAAG,EAAE,MAAM,GAAG,QAAQ,CAAA;CAAE,GACpD,MAAM,CAMR"}
@@ -27,6 +27,7 @@ __webpack_require__.d(__webpack_exports__, {
27
27
  getPersonPropertiesHash: ()=>getPersonPropertiesHash,
28
28
  includes: ()=>includes,
29
29
  isDistinctIdStringLike: ()=>isDistinctIdStringLike,
30
+ safeJsonStringify: ()=>safeJsonStringify,
30
31
  stripLeadingDollar: ()=>stripLeadingDollar,
31
32
  trim: ()=>trim
32
33
  });
@@ -45,6 +46,24 @@ function isDistinctIdStringLike(value) {
45
46
  'distinctid'
46
47
  ].includes(value.toLowerCase());
47
48
  }
49
+ function safeJsonStringify(value) {
50
+ const ancestors = [];
51
+ return JSON.stringify(value, function(_key, replacementValue) {
52
+ if ('bigint' == typeof replacementValue) return replacementValue.toString();
53
+ if ('function' == typeof replacementValue || 'symbol' == typeof replacementValue) return;
54
+ if (replacementValue instanceof Error) return {
55
+ name: replacementValue.name,
56
+ message: replacementValue.message,
57
+ stack: replacementValue.stack
58
+ };
59
+ if (replacementValue && 'object' == typeof replacementValue) {
60
+ while(ancestors.length > 0 && ancestors[ancestors.length - 1] !== this)ancestors.pop();
61
+ if (ancestors.includes(replacementValue)) return '[Circular]';
62
+ ancestors.push(replacementValue);
63
+ }
64
+ return replacementValue;
65
+ }) ?? 'null';
66
+ }
48
67
  function deepSortKeys(value) {
49
68
  if (null === value || 'object' != typeof value) return value;
50
69
  if (Array.isArray(value)) return value.map(deepSortKeys);
@@ -63,12 +82,14 @@ function getPersonPropertiesHash(distinct_id, userPropertiesToSet, userPropertie
63
82
  exports.getPersonPropertiesHash = __webpack_exports__.getPersonPropertiesHash;
64
83
  exports.includes = __webpack_exports__.includes;
65
84
  exports.isDistinctIdStringLike = __webpack_exports__.isDistinctIdStringLike;
85
+ exports.safeJsonStringify = __webpack_exports__.safeJsonStringify;
66
86
  exports.stripLeadingDollar = __webpack_exports__.stripLeadingDollar;
67
87
  exports.trim = __webpack_exports__.trim;
68
88
  for(var __webpack_i__ in __webpack_exports__)if (-1 === [
69
89
  "getPersonPropertiesHash",
70
90
  "includes",
71
91
  "isDistinctIdStringLike",
92
+ "safeJsonStringify",
72
93
  "stripLeadingDollar",
73
94
  "trim"
74
95
  ].indexOf(__webpack_i__)) exports[__webpack_i__] = __webpack_exports__[__webpack_i__];
@@ -13,6 +13,24 @@ function isDistinctIdStringLike(value) {
13
13
  'distinctid'
14
14
  ].includes(value.toLowerCase());
15
15
  }
16
+ function safeJsonStringify(value) {
17
+ const ancestors = [];
18
+ return JSON.stringify(value, function(_key, replacementValue) {
19
+ if ('bigint' == typeof replacementValue) return replacementValue.toString();
20
+ if ('function' == typeof replacementValue || 'symbol' == typeof replacementValue) return;
21
+ if (replacementValue instanceof Error) return {
22
+ name: replacementValue.name,
23
+ message: replacementValue.message,
24
+ stack: replacementValue.stack
25
+ };
26
+ if (replacementValue && 'object' == typeof replacementValue) {
27
+ while(ancestors.length > 0 && ancestors[ancestors.length - 1] !== this)ancestors.pop();
28
+ if (ancestors.includes(replacementValue)) return '[Circular]';
29
+ ancestors.push(replacementValue);
30
+ }
31
+ return replacementValue;
32
+ }) ?? 'null';
33
+ }
16
34
  function deepSortKeys(value) {
17
35
  if (null === value || 'object' != typeof value) return value;
18
36
  if (Array.isArray(value)) return value.map(deepSortKeys);
@@ -28,4 +46,4 @@ function getPersonPropertiesHash(distinct_id, userPropertiesToSet, userPropertie
28
46
  userPropertiesToSetOnce: userPropertiesToSetOnce ? deepSortKeys(userPropertiesToSetOnce) : void 0
29
47
  });
30
48
  }
31
- export { getPersonPropertiesHash, includes, isDistinctIdStringLike, stripLeadingDollar, trim };
49
+ export { getPersonPropertiesHash, includes, isDistinctIdStringLike, safeJsonStringify, stripLeadingDollar, trim };
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@posthog/core",
3
- "version": "1.38.1",
3
+ "version": "1.39.6",
4
4
  "bugs": {
5
5
  "url": "https://github.com/PostHog/posthog-js/issues"
6
6
  },
@@ -1,4 +1,4 @@
1
- import { isArray, isNumber, isObject, isString } from '@/utils'
1
+ import { isArray, isNumber, isObject, isString, safeJsonStringify } from '@/utils'
2
2
 
3
3
  export const EXCEPTION_STEP_INTERNAL_FIELDS = {
4
4
  MESSAGE: '$message',
@@ -134,8 +134,10 @@ function normalizePositiveInteger(input: number | undefined, fallback: number):
134
134
  }
135
135
 
136
136
  function normalizeAndSerializeStep(step: ExceptionStep): { step: ExceptionStep; json: string } | undefined {
137
- const json = safeStringify(step)
138
- if (!json) {
137
+ let json: string
138
+ try {
139
+ json = safeJsonStringify(step)
140
+ } catch {
139
141
  return undefined
140
142
  }
141
143
 
@@ -166,45 +168,6 @@ function normalizeAndSerializeStep(step: ExceptionStep): { step: ExceptionStep;
166
168
  }
167
169
  }
168
170
 
169
- function safeStringify(value: unknown): string | undefined {
170
- const seen = new WeakSet<object>()
171
-
172
- try {
173
- return JSON.stringify(value, (_key, replacementValue: unknown) => {
174
- if (typeof replacementValue === 'bigint') {
175
- return replacementValue.toString()
176
- }
177
-
178
- if (typeof replacementValue === 'function' || typeof replacementValue === 'symbol') {
179
- return undefined
180
- }
181
-
182
- if (replacementValue instanceof Date) {
183
- return replacementValue.toISOString()
184
- }
185
-
186
- if (replacementValue instanceof Error) {
187
- return {
188
- name: replacementValue.name,
189
- message: replacementValue.message,
190
- stack: replacementValue.stack,
191
- }
192
- }
193
-
194
- if (replacementValue && typeof replacementValue === 'object') {
195
- if (seen.has(replacementValue)) {
196
- return '[Circular]'
197
- }
198
- seen.add(replacementValue)
199
- }
200
-
201
- return replacementValue
202
- })
203
- } catch {
204
- return undefined
205
- }
206
- }
207
-
208
171
  export function getUtf8ByteLength(value: string): number {
209
172
  if (typeof TextEncoder !== 'undefined') {
210
173
  return new TextEncoder().encode(value).length
@@ -34,6 +34,7 @@ import {
34
34
  STRING_FORMAT,
35
35
  createLogger,
36
36
  getEventUuid,
37
+ safeJsonStringify,
37
38
  } from './utils'
38
39
  import { uuidv7 } from './vendor/uuidv7'
39
40
  import {
@@ -82,6 +83,18 @@ class PostHogFetchNetworkError extends Error {
82
83
  export const maybeAdd = (key: string, value: JsonType | undefined): Record<string, JsonType> =>
83
84
  value !== undefined ? { [key]: value } : {}
84
85
 
86
+ // Caller-supplied `$feature/*` and `$active_feature_flags` win over the SDK's cached flag values.
87
+ export const applyCallerFeatureFlagOverrides = (
88
+ target: PostHogEventProperties,
89
+ callerProperties: PostHogEventProperties
90
+ ): void => {
91
+ for (const key of Object.keys(callerProperties)) {
92
+ if (key.startsWith('$feature/') || key === '$active_feature_flags') {
93
+ target[key] = callerProperties[key]
94
+ }
95
+ }
96
+ }
97
+
85
98
  export async function logFlushError(err: any): Promise<void> {
86
99
  if (err instanceof PostHogFetchHttpError) {
87
100
  let text = ''
@@ -112,7 +125,13 @@ export function isPostHogFetchNetworkError(err: unknown): err is PostHogFetchNet
112
125
  return err instanceof PostHogFetchNetworkError
113
126
  }
114
127
 
115
- function isRetryableFlagsFetchError(err: unknown): err is PostHogFetchNetworkError {
128
+ function isRetryableFlagsFetchError(
129
+ err: unknown
130
+ ): err is PostHogFetchNetworkError | (PostHogFetchHttpError & { status: 502 | 504 }) {
131
+ if (err instanceof PostHogFetchHttpError) {
132
+ return err.status === 502 || err.status === 504
133
+ }
134
+
116
135
  if (!(err instanceof PostHogFetchNetworkError)) {
117
136
  return false
118
137
  }
@@ -126,6 +145,13 @@ function isPostHogFetchContentTooLargeError(err: unknown): err is PostHogFetchHt
126
145
  return typeof err === 'object' && err instanceof PostHogFetchHttpError && err.status === 413
127
146
  }
128
147
 
148
+ function isPostHogFetchRetryableError(err: unknown): err is PostHogFetchHttpError | PostHogFetchNetworkError {
149
+ if (err instanceof PostHogFetchHttpError) {
150
+ return err.status === 408 || err.status === 429 || err.status >= 500
151
+ }
152
+ return isPostHogFetchNetworkError(err)
153
+ }
154
+
129
155
  function isPostHogEventProperties(value: JsonType | undefined): value is PostHogEventProperties {
130
156
  return value !== null && typeof value === 'object' && !Array.isArray(value)
131
157
  }
@@ -163,6 +189,7 @@ export abstract class PostHogCoreStateless {
163
189
  private maxQueueSize: number
164
190
  private flushInterval: number
165
191
  private flushPromise: Promise<any> | null = null
192
+ private flushPromises: Set<Promise<any>> = new Set()
166
193
  private shutdownPromise: Promise<void> | null = null
167
194
  private requestTimeout: number
168
195
  private featureFlagsRequestTimeoutMs: number
@@ -250,7 +277,7 @@ export abstract class PostHogCoreStateless {
250
277
  this._retryOptions = {
251
278
  retryCount: options.fetchRetryCount ?? 3,
252
279
  retryDelay: options.fetchRetryDelay ?? 3000, // 3 seconds
253
- retryCheck: isPostHogFetchError,
280
+ retryCheck: isPostHogFetchRetryableError,
254
281
  }
255
282
  this.requestTimeout = options.requestTimeout ?? 10000 // 10 seconds
256
283
  this.featureFlagsRequestTimeoutMs = options.featureFlagsRequestTimeoutMs ?? 3000 // 3 seconds
@@ -369,13 +396,16 @@ export abstract class PostHogCoreStateless {
369
396
  event: string
370
397
  properties?: PostHogEventProperties
371
398
  }): PostHogEventProperties {
399
+ const userProperties = payload.properties || {}
400
+ const properties: PostHogEventProperties = {
401
+ ...userProperties,
402
+ ...this.getCommonEventProperties(), // Common PH props
403
+ }
404
+ applyCallerFeatureFlagOverrides(properties, userProperties)
372
405
  return {
373
406
  distinct_id: payload.distinct_id,
374
407
  event: payload.event,
375
- properties: {
376
- ...(payload.properties || {}),
377
- ...this.getCommonEventProperties(), // Common PH props
378
- },
408
+ properties,
379
409
  }
380
410
  }
381
411
 
@@ -515,6 +545,28 @@ export abstract class PostHogCoreStateless {
515
545
  })
516
546
  }
517
547
 
548
+ protected async groupIdentifyStatelessImmediate(
549
+ groupType: string,
550
+ groupKey: string | number,
551
+ groupProperties?: PostHogEventProperties,
552
+ options?: PostHogCaptureOptions,
553
+ distinctId?: string,
554
+ eventProperties?: PostHogEventProperties
555
+ ): Promise<void> {
556
+ const payload = this.buildPayload({
557
+ distinct_id: distinctId || `$${groupType}_${groupKey}`,
558
+ event: '$groupidentify',
559
+ properties: {
560
+ $group_type: groupType,
561
+ $group_key: groupKey,
562
+ $group_set: groupProperties || {},
563
+ ...(eventProperties || {}),
564
+ },
565
+ })
566
+
567
+ await this.sendImmediate('capture', payload, options)
568
+ }
569
+
518
570
  protected async getRemoteConfig(): Promise<PostHogRemoteConfig | undefined> {
519
571
  await this._initPromise
520
572
 
@@ -585,7 +637,7 @@ export abstract class PostHogCoreStateless {
585
637
 
586
638
  this._logger.info('Flags URL', url)
587
639
 
588
- // Retry only network/transport/timeout failures for /flags. HTTP/API status errors are surfaced immediately.
640
+ // Retry only network/transport/timeout failures and selected gateway HTTP errors for /flags.
589
641
  return this.fetchWithRetry(
590
642
  url,
591
643
  fetchOptions,
@@ -831,9 +883,8 @@ export abstract class PostHogCoreStateless {
831
883
  ): Promise<PostHogFeatureFlagDetails | undefined> {
832
884
  await this._initPromise
833
885
 
834
- const extraPayload: Record<string, any> = {}
835
- if (disableGeoip ?? this.disableGeoip) {
836
- extraPayload['geoip_disable'] = true
886
+ const extraPayload: Record<string, any> = {
887
+ geoip_disable: disableGeoip ?? this.disableGeoip,
837
888
  }
838
889
  if (flagKeysToEvaluate) {
839
890
  extraPayload['flag_keys_to_evaluate'] = flagKeysToEvaluate
@@ -1054,7 +1105,7 @@ export abstract class PostHogCoreStateless {
1054
1105
  data.historical_migration = true
1055
1106
  }
1056
1107
 
1057
- const payload = JSON.stringify(data)
1108
+ const payload = safeJsonStringify(data)
1058
1109
 
1059
1110
  const url = `${this.host}/batch/`
1060
1111
 
@@ -1145,6 +1196,28 @@ export abstract class PostHogCoreStateless {
1145
1196
  })
1146
1197
  }
1147
1198
 
1199
+ private async waitForPendingPromises(
1200
+ maxPromiseId: number,
1201
+ ignoredPromises: (Promise<any> | null | undefined)[] = []
1202
+ ): Promise<void> {
1203
+ const ignoredPendingPromises = ignoredPromises.filter((promise): promise is Promise<any> => !!promise)
1204
+ let iteration = 0
1205
+
1206
+ while (true) {
1207
+ const promises = this.promiseQueue.getPromises([...ignoredPendingPromises, ...this.flushPromises], maxPromiseId)
1208
+ if (promises.length === 0) {
1209
+ return
1210
+ }
1211
+
1212
+ if (iteration > 0) {
1213
+ this._logger.debug(`flush() re-checking ${promises.length} pending promise(s) before flushing`)
1214
+ }
1215
+
1216
+ await Promise.all(promises.map((promise) => promise.catch(() => {})))
1217
+ iteration++
1218
+ }
1219
+ }
1220
+
1148
1221
  /**
1149
1222
  * Flushes the queue of pending events.
1150
1223
  *
@@ -1173,22 +1246,44 @@ export abstract class PostHogCoreStateless {
1173
1246
  * @throws PostHogFetchNetworkError
1174
1247
  * @throws Error
1175
1248
  */
1176
- async flush(): Promise<void> {
1249
+ protected flushWithPendingPromises(): Promise<void> {
1250
+ return this.flushInternal(true)
1251
+ }
1252
+
1253
+ flush(): Promise<void> {
1254
+ return this.flushInternal(false)
1255
+ }
1256
+
1257
+ private flushInternal(waitForPendingPromises: boolean): Promise<void> {
1177
1258
  if (this.disabled) {
1178
- return
1259
+ return Promise.resolve()
1179
1260
  }
1180
1261
 
1181
- // Wait for the current flush operation to finish (regardless of success or failure), then try to flush again.
1182
- // Use allSettled instead of finally to be defensive around flush throwing errors immediately rather than rejecting.
1183
- // Use a custom allSettled implementation to avoid issues with patching Promise on RN
1184
- const nextFlushPromise = allSettled([this.flushPromise]).then(() => {
1185
- return this._flush()
1186
- })
1262
+ const previousFlushPromise = this.flushPromise
1263
+ const maxPromiseId = this.promiseQueue.maxId
1264
+
1265
+ // Register this flush in the promise queue synchronously so shutdown() can't miss it,
1266
+ // but exclude it from the pending-work wait to avoid self-waiting.
1267
+ const nextFlushPromise: Promise<void> = Promise.resolve()
1268
+ .then(() => {
1269
+ if (waitForPendingPromises) {
1270
+ return this.waitForPendingPromises(maxPromiseId, [previousFlushPromise, nextFlushPromise])
1271
+ }
1272
+ })
1273
+ // Wait for the current flush operation to finish (regardless of success or failure), then try to flush again.
1274
+ // Use allSettled instead of finally to be defensive around flush throwing errors immediately rather than rejecting.
1275
+ // Use a custom allSettled implementation to avoid issues with patching Promise on RN
1276
+ .then(() => allSettled([previousFlushPromise]))
1277
+ .then(() => {
1278
+ return this._flush()
1279
+ })
1187
1280
 
1188
1281
  this.flushPromise = nextFlushPromise
1282
+ this.flushPromises.add(nextFlushPromise)
1189
1283
  void this.addPendingPromise(nextFlushPromise)
1190
1284
 
1191
1285
  allSettled([nextFlushPromise]).then(() => {
1286
+ this.flushPromises.delete(nextFlushPromise)
1192
1287
  // If there are no others waiting to flush, clear the promise.
1193
1288
  // We don't strictly need to do this, but it could make debugging easier
1194
1289
  if (this.flushPromise === nextFlushPromise) {
@@ -1250,7 +1345,7 @@ export abstract class PostHogCoreStateless {
1250
1345
  data.historical_migration = true
1251
1346
  }
1252
1347
 
1253
- const payload = JSON.stringify(data)
1348
+ const payload = safeJsonStringify(data)
1254
1349
 
1255
1350
  const url = `${this.host}/batch/`
1256
1351
 
@@ -1271,8 +1366,8 @@ export abstract class PostHogCoreStateless {
1271
1366
  if (isPostHogFetchContentTooLargeError(err)) {
1272
1367
  return false
1273
1368
  }
1274
- // otherwise, retry on network errors
1275
- return isPostHogFetchError(err)
1369
+ // otherwise, retry on transient HTTP and network errors
1370
+ return isPostHogFetchRetryableError(err)
1276
1371
  },
1277
1372
  }
1278
1373
 
@@ -1345,7 +1440,7 @@ export abstract class PostHogCoreStateless {
1345
1440
  if (isPostHogFetchContentTooLargeError(err)) {
1346
1441
  return false
1347
1442
  }
1348
- return isPostHogFetchError(err)
1443
+ return isPostHogFetchRetryableError(err)
1349
1444
  },
1350
1445
  })
1351
1446
  return { kind: 'ok' }