From b66bf47e0fe65d3705b990fd524a6bcf2d0dbd00 Mon Sep 17 00:00:00 2001 From: Anna Garcia Date: Mon, 5 Oct 2026 16:18:57 -0400 Subject: [PATCH 1/2] fix(core): resolve @posthog/core/surveys on Metro without package exports 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. --- .changeset/core-surveys-subpath-old-metro.md | 5 ++++ packages/core/package.json | 1 + .../core/src/__tests__/subpath-stubs.spec.ts | 22 +++++++++++++++ packages/core/surveys/package.json | 6 ++++ .../test/core-subpath-stubs.spec.ts | 28 +++++++++++++++++++ 5 files changed, 62 insertions(+) create mode 100644 .changeset/core-surveys-subpath-old-metro.md create mode 100644 packages/core/src/__tests__/subpath-stubs.spec.ts create mode 100644 packages/core/surveys/package.json create mode 100644 packages/react-native/test/core-subpath-stubs.spec.ts diff --git a/.changeset/core-surveys-subpath-old-metro.md b/.changeset/core-surveys-subpath-old-metro.md new file mode 100644 index 0000000000..160e653ccc --- /dev/null +++ b/.changeset/core-surveys-subpath-old-metro.md @@ -0,0 +1,5 @@ +--- +'@posthog/core': patch +--- + +Fix `Unable to resolve module @posthog/core/surveys` when bundling posthog-react-native 4.44.0 or later on React Native 0.71–0.78 without Metro package exports diff --git a/packages/core/package.json b/packages/core/package.json index 7c2a00929f..23aa1bb331 100644 --- a/packages/core/package.json +++ b/packages/core/package.json @@ -34,6 +34,7 @@ }, "files": [ "dist", + "surveys", "src", "!src/__tests__" ], diff --git a/packages/core/src/__tests__/subpath-stubs.spec.ts b/packages/core/src/__tests__/subpath-stubs.spec.ts new file mode 100644 index 0000000000..c444e6146e --- /dev/null +++ b/packages/core/src/__tests__/subpath-stubs.spec.ts @@ -0,0 +1,22 @@ +import { readFileSync } from 'node:fs' +import { join } from 'node:path' + +const packageRoot = join(__dirname, '..', '..') +const readJson = (path: string): any => JSON.parse(readFileSync(join(packageRoot, path), 'utf8')) + +// Metro without package exports (React Native < 0.79 by default) resolves `@posthog/core/surveys` +// as a folder, so the stub must point at the same files as the `./surveys` export. +describe('subpath stubs', () => { + it('surveys/package.json matches the ./surveys export', () => { + const exported = readJson('package.json').exports['./surveys'] + const stub = readJson('surveys/package.json') + + expect(join('surveys', stub.main)).toBe(join(exported.require)) + expect(join('surveys', stub.module)).toBe(join(exported.import)) + expect(join('surveys', stub.types)).toBe(join(exported.types)) + }) + + it('ships the surveys stub', () => { + expect(readJson('package.json').files).toContain('surveys') + }) +}) diff --git a/packages/core/surveys/package.json b/packages/core/surveys/package.json new file mode 100644 index 0000000000..c354e5fcd6 --- /dev/null +++ b/packages/core/surveys/package.json @@ -0,0 +1,6 @@ +{ + "private": true, + "main": "../dist/surveys/index.js", + "module": "../dist/surveys/index.mjs", + "types": "../dist/surveys/index.d.ts" +} diff --git a/packages/react-native/test/core-subpath-stubs.spec.ts b/packages/react-native/test/core-subpath-stubs.spec.ts new file mode 100644 index 0000000000..9bfe173831 --- /dev/null +++ b/packages/react-native/test/core-subpath-stubs.spec.ts @@ -0,0 +1,28 @@ +import { existsSync, readdirSync, readFileSync, statSync } from 'node:fs' +import { join } from 'node:path' + +const srcDir = join(__dirname, '..', 'src') +const coreDir = join(__dirname, '..', '..', 'core') + +const sourceFiles = (dir: string): string[] => + readdirSync(dir).flatMap((name) => { + const path = join(dir, name) + return statSync(path).isDirectory() ? sourceFiles(path) : /\.(ts|tsx)$/.test(name) ? [path] : [] + }) + +// Metro without package exports (React Native < 0.79 by default) can only resolve +// `@posthog/core/` through a real `/package.json` in @posthog/core. +describe('@posthog/core subpath imports', () => { + 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]) + ) + ) + + expect(subpaths.size).toBeGreaterThan(0) + for (const subpath of subpaths) { + expect(existsSync(join(coreDir, subpath, 'package.json')), `@posthog/core/${subpath}`).toBe(true) + } + }) +}) From e216e2935eb573f20764eeececced85effd98bcb Mon Sep 17 00:00:00 2001 From: Anna Garcia Date: Mon, 5 Oct 2026 16:30:48 -0400 Subject: [PATCH 2/2] chore: release posthog-react-native with the fix and guard nested core subpaths --- .changeset/core-surveys-subpath-old-metro.md | 3 ++- packages/react-native/test/core-subpath-stubs.spec.ts | 2 +- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/.changeset/core-surveys-subpath-old-metro.md b/.changeset/core-surveys-subpath-old-metro.md index 160e653ccc..8ae41f579a 100644 --- a/.changeset/core-surveys-subpath-old-metro.md +++ b/.changeset/core-surveys-subpath-old-metro.md @@ -1,5 +1,6 @@ --- '@posthog/core': patch +'posthog-react-native': patch --- -Fix `Unable to resolve module @posthog/core/surveys` when bundling posthog-react-native 4.44.0 or later on React Native 0.71–0.78 without Metro package exports +Fix `Unable to resolve module @posthog/core/surveys` when bundling posthog-react-native on React Native 0.71–0.78 without Metro package exports. posthog-react-native 4.47.0 and later also pick up the fix by updating `@posthog/core`. diff --git a/packages/react-native/test/core-subpath-stubs.spec.ts b/packages/react-native/test/core-subpath-stubs.spec.ts index 9bfe173831..1cf52d9016 100644 --- a/packages/react-native/test/core-subpath-stubs.spec.ts +++ b/packages/react-native/test/core-subpath-stubs.spec.ts @@ -16,7 +16,7 @@ describe('@posthog/core subpath imports', () => { 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]) + [...readFileSync(file, 'utf8').matchAll(/['"]@posthog\/core\/([\w/-]+)['"]/g)].map((match) => match[1]) ) )