posthog-node 4.11.2 → 4.11.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md CHANGED
@@ -1,8 +1,11 @@
1
+ # 4.11.3 - 2025-04-08
2
+
3
+ 1. fix: do not access `fs` or `readline` in when not available e.g. edge environments
4
+
1
5
  # 4.11.2 - 2025-04-07
2
6
 
3
7
  1. chore: bump axios to 1.8.2 (fixes [CVE-2025-27152](https://github.com/advisories/GHSA-jr5f-v2jv-69x6))
4
8
 
5
-
6
9
  # 4.11.1 - 2025-03-28
7
10
 
8
11
  ## Fixed
@@ -28,7 +31,6 @@
28
31
  1. Fix: only set `platform` on PostHog exception frame properties
29
32
  1. Fix: prevent fetch floods when rate-limited.
30
33
 
31
-
32
34
  # 4.10.0 – 2025-03-06
33
35
 
34
36
  1. Attach requestId to $feature_flag_called if present in /decide response
@@ -320,4 +322,4 @@ Breaking changes:
320
322
  What's new:
321
323
 
322
324
  1. You can now evaluate feature flags locally (i.e. without sending a request to your PostHog servers) by setting a personal API key, and passing in groups and person properties to `isFeatureEnabled` and `getFeatureFlag` calls.
323
- 2. Introduces a `getAllFlags` method that returns all feature flags. This is useful for when you want to seed your frontend with some initial flags, given a user ID.
325
+ 2. Introduces a `getAllFlags` method that returns all feature flags. This is useful for when you want to seed your frontend with some initial flags, given a user ID.
package/lib/index.cjs.js CHANGED
@@ -2,8 +2,6 @@
2
2
 
3
3
  Object.defineProperty(exports, '__esModule', { value: true });
4
4
 
5
- var node_fs = require('node:fs');
6
- var node_readline = require('node:readline');
7
5
  var node_path = require('node:path');
8
6
 
9
7
  function _interopNamespace(e) {
@@ -24,7 +22,7 @@ function _interopNamespace(e) {
24
22
  return Object.freeze(n);
25
23
  }
26
24
 
27
- var version = "4.11.2";
25
+ var version = "4.11.3";
28
26
 
29
27
  var PostHogPersistedProperty;
30
28
  (function (PostHogPersistedProperty) {
@@ -2536,6 +2534,26 @@ class ReduceableCache {
2536
2534
  }
2537
2535
  }
2538
2536
 
2537
+ const nodeFs = new Lazy(async () => {
2538
+ try {
2539
+ return await Promise.resolve().then(function () { return /*#__PURE__*/_interopNamespace(require('node:fs')); });
2540
+ } catch {
2541
+ return undefined;
2542
+ }
2543
+ });
2544
+ async function getNodeFs() {
2545
+ return await nodeFs.getValue();
2546
+ }
2547
+ const nodeReadline = new Lazy(async () => {
2548
+ try {
2549
+ return await Promise.resolve().then(function () { return /*#__PURE__*/_interopNamespace(require('node:readline')); });
2550
+ } catch {
2551
+ return undefined;
2552
+ }
2553
+ });
2554
+ async function getNodeReadline() {
2555
+ return await nodeReadline.getValue();
2556
+ }
2539
2557
  const LRU_FILE_CONTENTS_CACHE = new ReduceableCache(25);
2540
2558
  const LRU_FILE_CONTENTS_FS_READ_FAILED = new ReduceableCache(20);
2541
2559
  const DEFAULT_LINES_OF_CONTEXT = 7;
@@ -2603,70 +2621,79 @@ async function addSourceContext(frames) {
2603
2621
  */
2604
2622
  function getContextLinesFromFile(path, ranges, output) {
2605
2623
  return new Promise(resolve => {
2606
- // It is important *not* to have any async code between createInterface and the 'line' event listener
2607
- // as it will cause the 'line' event to
2608
- // be emitted before the listener is attached.
2609
- const stream = node_fs.createReadStream(path);
2610
- const lineReaded = node_readline.createInterface({
2611
- input: stream
2612
- });
2613
- // We need to explicitly destroy the stream to prevent memory leaks,
2614
- // removing the listeners on the readline interface is not enough.
2615
- // See: https://github.com/nodejs/node/issues/9002 and https://github.com/getsentry/sentry-javascript/issues/14892
2616
- function destroyStreamAndResolve() {
2617
- stream.destroy();
2618
- resolve();
2619
- }
2620
- // Init at zero and increment at the start of the loop because lines are 1 indexed.
2621
- let lineNumber = 0;
2622
- let currentRangeIndex = 0;
2623
- const range = ranges[currentRangeIndex];
2624
- if (range === undefined) {
2625
- // We should never reach this point, but if we do, we should resolve the promise to prevent it from hanging.
2626
- destroyStreamAndResolve();
2627
- return;
2628
- }
2629
- let rangeStart = range[0];
2630
- let rangeEnd = range[1];
2631
- // We use this inside Promise.all, so we need to resolve the promise even if there is an error
2632
- // to prevent Promise.all from short circuiting the rest.
2633
- function onStreamError() {
2634
- // Mark file path as failed to read and prevent multiple read attempts.
2635
- LRU_FILE_CONTENTS_FS_READ_FAILED.set(path, 1);
2636
- lineReaded.close();
2637
- lineReaded.removeAllListeners();
2638
- destroyStreamAndResolve();
2639
- }
2640
- // We need to handle the error event to prevent the process from crashing in < Node 16
2641
- // https://github.com/nodejs/node/pull/31603
2642
- stream.on('error', onStreamError);
2643
- lineReaded.on('error', onStreamError);
2644
- lineReaded.on('close', destroyStreamAndResolve);
2645
- lineReaded.on('line', line => {
2646
- lineNumber++;
2647
- if (lineNumber < rangeStart) {
2624
+ // KLUDGE: edge runtimes do not support node:fs or node:readline
2625
+ // until we have separate packages for each environment this will skip
2626
+ // trying to access the filesystem when not accessible
2627
+ Promise.all([getNodeFs(), getNodeReadline()]).then(([nodeFs, nodeReadline]) => {
2628
+ if (!nodeFs || !nodeReadline) {
2629
+ resolve();
2630
+ return;
2631
+ }
2632
+ // It is important *not* to have any async code between createInterface and the 'line' event listener
2633
+ // as it will cause the 'line' event to
2634
+ // be emitted before the listener is attached.
2635
+ const stream = nodeFs.createReadStream(path);
2636
+ const lineReaded = nodeReadline.createInterface({
2637
+ input: stream
2638
+ });
2639
+ // We need to explicitly destroy the stream to prevent memory leaks,
2640
+ // removing the listeners on the readline interface is not enough.
2641
+ // See: https://github.com/nodejs/node/issues/9002 and https://github.com/getsentry/sentry-javascript/issues/14892
2642
+ function destroyStreamAndResolve() {
2643
+ stream.destroy();
2644
+ resolve();
2645
+ }
2646
+ // Init at zero and increment at the start of the loop because lines are 1 indexed.
2647
+ let lineNumber = 0;
2648
+ let currentRangeIndex = 0;
2649
+ const range = ranges[currentRangeIndex];
2650
+ if (range === undefined) {
2651
+ // We should never reach this point, but if we do, we should resolve the promise to prevent it from hanging.
2652
+ destroyStreamAndResolve();
2648
2653
  return;
2649
2654
  }
2650
- // !Warning: This mutates the cache by storing the snipped line into the cache.
2651
- output[lineNumber] = snipLine(line, 0);
2652
- if (lineNumber >= rangeEnd) {
2653
- if (currentRangeIndex === ranges.length - 1) {
2654
- // We need to close the file stream and remove listeners, else the reader will continue to run our listener;
2655
- lineReaded.close();
2656
- lineReaded.removeAllListeners();
2655
+ let rangeStart = range[0];
2656
+ let rangeEnd = range[1];
2657
+ // We use this inside Promise.all, so we need to resolve the promise even if there is an error
2658
+ // to prevent Promise.all from short circuiting the rest.
2659
+ function onStreamError() {
2660
+ // Mark file path as failed to read and prevent multiple read attempts.
2661
+ LRU_FILE_CONTENTS_FS_READ_FAILED.set(path, 1);
2662
+ lineReaded.close();
2663
+ lineReaded.removeAllListeners();
2664
+ destroyStreamAndResolve();
2665
+ }
2666
+ // We need to handle the error event to prevent the process from crashing in < Node 16
2667
+ // https://github.com/nodejs/node/pull/31603
2668
+ stream.on('error', onStreamError);
2669
+ lineReaded.on('error', onStreamError);
2670
+ lineReaded.on('close', destroyStreamAndResolve);
2671
+ lineReaded.on('line', line => {
2672
+ lineNumber++;
2673
+ if (lineNumber < rangeStart) {
2657
2674
  return;
2658
2675
  }
2659
- currentRangeIndex++;
2660
- const range = ranges[currentRangeIndex];
2661
- if (range === undefined) {
2662
- // This should never happen as it means we have a bug in the context.
2663
- lineReaded.close();
2664
- lineReaded.removeAllListeners();
2665
- return;
2676
+ // !Warning: This mutates the cache by storing the snipped line into the cache.
2677
+ output[lineNumber] = snipLine(line, 0);
2678
+ if (lineNumber >= rangeEnd) {
2679
+ if (currentRangeIndex === ranges.length - 1) {
2680
+ // We need to close the file stream and remove listeners, else the reader will continue to run our listener;
2681
+ lineReaded.close();
2682
+ lineReaded.removeAllListeners();
2683
+ return;
2684
+ }
2685
+ currentRangeIndex++;
2686
+ const range = ranges[currentRangeIndex];
2687
+ if (range === undefined) {
2688
+ // This should never happen as it means we have a bug in the context.
2689
+ lineReaded.close();
2690
+ lineReaded.removeAllListeners();
2691
+ return;
2692
+ }
2693
+ rangeStart = range[0];
2694
+ rangeEnd = range[1];
2666
2695
  }
2667
- rangeStart = range[0];
2668
- rangeEnd = range[1];
2669
- }
2696
+ });
2670
2697
  });
2671
2698
  });
2672
2699
  }