Repository navigation
fix(core): resolve @posthog/core/surveys on Metro without package exports - #5209
Conversation
…orts Adds a surveys/package.json stub so React Native 0.71-0.78 apps bundle posthog-react-native 4.44.0+ without enabling unstable_enablePackageExports.
|
[Medium risk] Adds a package stub to support older React Native bundlers. The PR appears safe to merge; the identified issues are non-blocking gaps in regression coverage. Reviews (1) · Last reviewed commit: "fix(core): resolve @posthog/core/surveys..." |
|
|
||
| expect(subpaths.size).toBeGreaterThan(0) | ||
| for (const subpath of subpaths) { | ||
| expect(existsSync(join(coreDir, subpath, 'package.json')), `@posthog/core/${subpath}`).toBe(true) |
There was a problem hiding this comment.
Stub existence does not prove resolution A future core subpath can have a
package.json but still point to missing files or be absent from the published package. This test would pass while older Metro versions fail to resolve the import. Check resolution against the built, packed core package instead of checking file existence alone.
Prompt To Fix With AI
This is a comment left during a code review.
Path: packages/react-native/test/core-subpath-stubs.spec.ts
Line: 25
Comment:
**Stub existence does not prove resolution** A future core subpath can have a `package.json` but still point to missing files or be absent from the published package. This test would pass while older Metro versions fail to resolve the import. Check resolution against the built, packed core package instead of checking file existence alone.
---
For each issue above, determine whether it is valid and should be fixed. If so, fix it directly.| it('each has a resolvable stub in @posthog/core', () => { | ||
| const subpaths = new Set( | ||
| sourceFiles(srcDir).flatMap((file) => | ||
| [...readFileSync(file, 'utf8').matchAll(/['"]@posthog\/core\/([\w-]+)['"]/g)].map((match) => match[1]) |
There was a problem hiding this comment.
Template literal imports escape scan The expression matches only single- and double-quoted paths. A static template-literal import of a new core subpath would be missed, while the existing surveys imports keep the test passing. Include static template-literal imports so the test requires a stub for them too.
Prompt To Fix With AI
This is a comment left during a code review.
Path: packages/react-native/test/core-subpath-stubs.spec.ts
Line: 19
Comment:
**Template literal imports escape scan** The expression matches only single- and double-quoted paths. A static template-literal import of a new core subpath would be missed, while the existing surveys imports keep the test passing. Include static template-literal imports so the test requires a stub for them too.
---
For each issue above, determine whether it is valid and should be fixed. If so, fix it directly.|
Size Change: +6.49 kB (+0.03%) Total Size: 23.6 MB 📦 View Changed
ℹ️ View Unchanged
|
Node SDK compliance v2Commit: e216e29 Capture v0✅ 55 passed / ❌ 1 non-passing / Drill-down: run artifacts → ❌ migration:yaml-parity-v1:feature_flags:disable_geoip_omitted_defaults_to_false — failed_assertionFlags field differs Code: Failed step: migration/yaml-parity-v1/remote-flags-v1.feature:143 the first flags request field "geoip_disable" should equal JSON false Operation: Field: Expected: false Actual value: true Harness exit: 1; report validation exit: 1. Capture v1✅ 120 passed / ❌ 1 non-passing / Drill-down: run artifacts → ❌ migration:yaml-parity-v1:feature_flags:disable_geoip_omitted_defaults_to_false — failed_assertionFlags field differs Code: Failed step: migration/yaml-parity-v1/remote-flags-v1.feature:143 the first flags request field "geoip_disable" should equal JSON false Operation: Field: Expected: false Actual value: true Harness exit: 1; report validation exit: 1. |
posthog-js Compliance ReportDate: 2026-10-05 21:47:08 UTC ✅ All Tests Passed!26/26 tests passed Capture Tests✅ 26/26 tests passed View Details
|
Discussed in https://posthog.slack.com/archives/C0ACMS2BNTU/p1791299008022149?thread_ts=1791290787.624229&cid=C0ACMS2BNTU |
Problem
Since posthog-react-native 4.44.0 (May 1, 2026, #3492), the SDK imports
@posthog/core/surveys.@posthog/coreexposes that path only throughpackage.jsonexports, and Metro ignoresexportsunless package exports are enabled. That's on by default only from React Native 0.79. On RN 0.71–0.78, a fresh app bundling posthog-react-native 4.44.0+ fails with:This has been broken for about 5 months. A workaround exists on RN 0.72–0.78 (
resolver.unstable_enablePackageExports: trueinmetro.config.js); RN 0.71's Metro has no such option. The same failure happened before with@posthog/core/error-tracking(#2437, 5+ reports), fixed in #2457 by importing from the package root.Changes
packages/core/surveys/package.json: a stub that pointsmain/module/typesat../dist/surveys/*, so Metro without package exports resolves the subpath as a folder. Bundlers that readexportsignore it."surveys"added to core'sfiles, so the stub ships.packages/core/src/__tests__/subpath-stubs.spec.ts: the stub must point at the same files asexports["./surveys"].packages/react-native/test/core-subpath-stubs.spec.ts: every@posthog/core/<subpath>import in posthog-react-native must have a stub. A new subpath import fails CI instead of breaking older RN apps.@posthog/coreand posthog-react-native. The posthog-react-native release only raises its@posthog/corefloor to the fixed version, so upgrading posthog-react-native fixes the build even with a lockfile. Apps on posthog-react-native 4.47.0 or later can also get the fix by updating@posthog/corealone. 4.44.0–4.46.x pin@posthog/coreexactly, so those apps need to upgrade posthog-react-native.Alternative considered: raise the supported React Native floor
posthog-react-native could instead declare RN 0.79+ (or document
unstable_enablePackageExportsfor 0.72–0.78). That would drop RN 0.71–0.78, which shipped from Jan 2023 to Feb 2025 and is about 12% of last week'sreact-nativenpm downloads. It would also turn an accidental regression into a breaking requirement. The stub is one file, non-breaking, and restores 0.71+ out of the box, which matches the RN 0.71 floor planned for@posthog/react-native-plugin3.0 (#5194).Alternative considered: import from the package root (as in #2457)
#2457 fixed the same failure for
error-trackingby importing from@posthog/core's root. Here, that would add the rest of the surveys module to core's root API, and it would only fix apps that upgrade posthog-react-native. Every published 4.47–4.78 release would stay broken. The stub fixes those through a core update, with no new root exports.Not covered
RN 0.70 additionally can't compile
@posthog/coresyntax (??=,||=, named regex groups) with its Babel preset and Hermes. With the stub, RN 0.71 bundles and Hermes compiles, so 0.71 stays the lowest version that works out of the box.Release info Sub-libraries affected
Libraries affected
@posthog/corefloor to the fixed version)Checklist
exportsand never read the stub; TypeScriptmoduleResolution: node10reads the stub'stypes, which is the samedist/surveys/index.d.ts)If releasing new changes
pnpm changesetto generate a changeset file🤖 Agent context
Autonomy: Human-driven (agent-assisted)
Written with Claude Code.
Verified:
react-native bundleplus that version's hermesc. Only 0.79 bundles without changes; 0.70–0.78 all fail on@posthog/core/surveys. With this branch's packed core, 0.71.19, 0.72.17, 0.76.9 and 0.78.3 bundle and compile with unchanged Metro configs, and 0.79.7 still works.@posthog/core. The same app fails to bundle with@posthog/core1.56.0 from npm. With this branch's core, it runs and its events reached a test PostHog project.@posthog/coreand posthog-react-native unit tests pass, along with lint andoxfmt.Not verified: an iOS run (the change is Metro module resolution, which is the same for both platforms), and RN versions not listed above.
🤖 Generated with Claude Code