Skip to content

discussion/fix: powersync/common dependencies#847

Draft
stevensJourney wants to merge 3 commits intomainfrom
package-peers
Draft

discussion/fix: powersync/common dependencies#847
stevensJourney wants to merge 3 commits intomainfrom
package-peers

Conversation

@stevensJourney
Copy link
Collaborator

Overview

We've seen a few reports of mismatched @powersync/common packages in users' applications:

This causes cryptic TypeScript build errors of the form

// Your app re-exports or uses types from both packages.
import { PowerSyncDatabase, Schema as SchemaFromWeb } from '@powersync/web';
import { PowerSyncProvider } from '@powersync/react'; // internally uses Schema from its own @powersync/common@1.45.0

const schemaFromWeb: SchemaFromWeb = new SchemaFromWeb({ tables: [...] });
const db = new PowerSyncDatabase({ schema: schemaFromWeb }); // ✅ same package, same Schema class

// Later you pass the same db (or its schema) into React context.
<PowerSyncProvider db={db}> {/* ❌ TypeScript error: PowerSyncProvider expects db from "its" common. Even though both Schema classes have the same shape, they are different declarations (1.46.0 vs 1.45.0), so the types are not assignable. */}
</PowerSyncProvider>

While there are multiple factors which can contribute to these package mismatches - one of the primary factors is the upgrade/bumping of @powersync/* NPM packages in an application. The method in which the package manager facilitates these upgrades, currently can easily result in multiple versions of @powersync/common being present in a project.

One path which results in issues is:

  • Project depends on version @powersync/web@1.0.1 (which depends on @powersync/common@1.0.1). Project also depends on @powersync/react@1.1.1 which has a peerDependency range for @powersync/common@^1.0.1)
  • Project upgrades to @powersync/web@1.5.0 which depends on @powersync/common@1.5.0. The upgrade path does not bump the common dependency for @powersync/react which causes both @powersync/common@1.5.0 and @powersync/common@1.0.1 to be present in the project.
  • Type differences in the @powersync/common package cause TypeScript build errors

The general desired behaviour is for @powersync/web to "provide" @powersync/common, where packages such as @powersync/react should use the version provided by @powersync/web.

The crux of the issue above is that: upgrading @powersync/web does not bump the @powersync/common version used by @powersync/react.

After some investigation, this erroneous behaviour seems to be caused by the current relationship of @powersync/web and @powersync/common. In #179, @powersync/common was declared as a peerDependency of @powersync/web. I believe the reasoning was to allow for warning if the actual resolved version of @powersync/common was incompatible with the SDK... The peerDependency should provide warnings, while the direct dependency should actually dictate which version of @powersync/common was required.

However, declaring the peerDependency for @powersync/common seems to be root cause of the issues described above, where the peerDependency seems to cause bumps in @powersync/web not to bump @powersync/common - at least with PNPM 10.28.2.

A video which demonstrates this behaviour is below

2026-02-11_powersync_js_peerDependencies.mp4

When testing with local publishing, removing the peerDependency declarations for @powersync/common seems to fix the core issues.

The benefit of having @powersync/common as a peerDependency (in addition to a dependency) seems to be small - if not non-existent. The fact that @powersync/web has a direct dependency for @powersync/common should result in that peerDependency range always being specified, even if there are mulitiple packages which have direct dependencies for @powersync/common

Additional tests were performed to test various future scenarios:

If a user had an older version of @powersync/react-native (which still had peerDependency declarations) and only upgraded @powersync/web (which will no longer contain peerDependency declarations). The @powersync/web declaration will drive the version of @powersync/common

# Web has no peer, old RN has peer
❯ pnpm why @powersync/common
Legend: production dependency, optional only, dev only

versions@1.0.0 /private/tmp/versions

dependencies:
@powersync/drizzle-driver 0.7.2
└── @powersync/common 1.47.0 peer
@powersync/react-native 1.17.0
├── @powersync/common 1.47.0 peer
└─┬ @powersync/react 1.5.1
  └── @powersync/common 1.47.0 peer
@powersync/web 1.33.2
└── @powersync/common 1.47.0

If we (only) removed the peerDependency requirement for both @powersync/react-native and @powersync/web. Each package would have a fixed dependency range for @powersync/common which could result in multiple versions of @powersync/common being present.

# Both have no peer, RN relies on older version
❯ pnpm why @powersync/common
Legend: production dependency, optional only, dev only

versions@1.0.0 /private/tmp/versions

dependencies:
@powersync/drizzle-driver 0.7.2
└── @powersync/common 1.47.0 peer
@powersync/react-native 1.30.0
├── @powersync/common 1.46.0
└─┬ @powersync/react 1.8.2
  └── @powersync/common 1.46.0 peer
@powersync/web 1.33.3
└── @powersync/common 1.47.0

If we update the direct dependencies from

-     "@powersync/common": "workspace:*",
+    "@powersync/common": "workspace:^",

Then, updating only @powersync/web does not automatically bump @powersync/common for @powersync/react-native

❯ pnpm why @powersync/common
Legend: production dependency, optional only, dev only

versions@1.0.0 /private/tmp/versions

dependencies:
@powersync/drizzle-driver 0.7.2
└── @powersync/common 1.51.0 peer
@powersync/react-native 1.50.0
├── @powersync/common 1.47.0
└─┬ @powersync/react 1.8.2
  └── @powersync/common 1.47.0 peer
@powersync/web 1.51.0
└── @powersync/common 1.51.0

But, running pnpm upgrade will resolve both to a single version of @powersync/common

❯ pnpm why @powersync/common
Legend: production dependency, optional only, dev only

versions@1.0.0 /private/tmp/versions

dependencies:
@powersync/drizzle-driver 0.7.2
└── @powersync/common 1.51.0 peer
@powersync/react-native 1.50.0
├── @powersync/common 1.51.0
└─┬ @powersync/react 1.8.2
  └── @powersync/common 1.51.0 peer
@powersync/web 1.51.0
└── @powersync/common 1.51.0

@changeset-bot
Copy link

changeset-bot bot commented Feb 11, 2026

🦋 Changeset detected

Latest commit: 632ed5c

The changes in this PR will be included in the next version bump.

This PR includes changesets to release 4 packages
Name Type
@powersync/react-native Minor
@powersync/node Minor
@powersync/web Minor
@powersync/diagnostics-app Patch

Not sure what this means? Click here to learn what changesets are.

Click here if you're a maintainer who wants to add another changeset to this PR

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant

Comments