Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
20 changes: 0 additions & 20 deletions .github/workflows/dev-packages.yml
Original file line number Diff line number Diff line change
Expand Up @@ -50,20 +50,6 @@ jobs:
- name: Run Pack For Common
run: dotnet pack PowerSync/PowerSync.Common -c Release -o ${{ github.workspace }}/output

- name: Extract MAUI Package Version from CHANGELOG.md
shell: bash
run: |
MAUI_VERSION=$(awk '/^## [0-9]+\.[0-9]+\.[0-9]+-dev(\.[0-9]+)?$/ {print $2; exit}' PowerSync/PowerSync.Maui/CHANGELOG.md)
if [[ -z "$MAUI_VERSION" ]]; then
echo "Error: Invalid dev version found in PowerSync.Maui/CHANGELOG.md. Expected format: x.x.x-dev.x"
exit 1
fi
echo "Detected Version: $MAUI_VERSION"
echo "VERSION=$MAUI_VERSION" >> $GITHUB_ENV

- name: Run Pack For MAUI
run: dotnet pack PowerSync/PowerSync.Maui -c Release -o ${{ github.workspace }}/output

- name: Upload Build Artifacts
uses: actions/upload-artifact@v4
with:
Expand Down Expand Up @@ -158,9 +144,3 @@ jobs:
dotnet nuget push "${{ github.workspace }}\SignedArtifacts\PowerSync.Common*.nupkg"
--api-key "${{ steps.login.outputs.NUGET_API_KEY }}"
--source https://api.nuget.org/v3/index.json

- name: Run Push For Maui
run: >
dotnet nuget push "${{ github.workspace }}\SignedArtifacts\PowerSync.Maui*.nupkg"
--api-key "${{ steps.login.outputs.NUGET_API_KEY }}"
--source https://api.nuget.org/v3/index.json
37 changes: 0 additions & 37 deletions .github/workflows/release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,6 @@ jobs:

outputs:
common_version: ${{ steps.extract_version.outputs.common_version }}
maui_version: ${{ steps.extract_maui_version.outputs.maui_version }}

steps:
- name: Checkout Repository
Expand Down Expand Up @@ -56,22 +55,6 @@ jobs:
- name: Run Pack For Common
run: dotnet pack PowerSync/PowerSync.Common -c Release -o ${{ github.workspace }}/output

- name: Extract MAUI Package Version from CHANGELOG.md
id: extract_maui_version
shell: bash
run: |
MAUI_VERSION=$(awk '/^## [0-9]+\.[0-9]+\.[0-9]+/ {print $2; exit}' PowerSync/PowerSync.Maui/CHANGELOG.md)
if [[ -z "$MAUI_VERSION" ]]; then
echo "Error: Invalid version found in PowerSync.Maui/CHANGELOG.md. Expected format: '## x.x.x'"
exit 1
fi
echo "Detected Version: $MAUI_VERSION"
echo "VERSION=$MAUI_VERSION" >> $GITHUB_ENV
echo "maui_version=$MAUI_VERSION" >> $GITHUB_OUTPUT

- name: Run Pack For MAUI
run: dotnet pack PowerSync/PowerSync.Maui -c Release -o ${{ github.workspace }}/output

- name: Upload Build Artifacts
uses: actions/upload-artifact@v4
with:
Expand Down Expand Up @@ -182,23 +165,3 @@ jobs:
--generate-notes \
SignedArtifacts/PowerSync.Common*.nupkg

- name: Run Push For Maui
run: >
dotnet nuget push "${{ github.workspace }}\SignedArtifacts\PowerSync.Maui*.nupkg"
--api-key "${{ steps.login.outputs.NUGET_API_KEY }}"
--source https://api.nuget.org/v3/index.json

- name: Create GitHub Release For Maui
continue-on-error: true
shell: bash
env:
GH_TOKEN: ${{ github.token }}
GH_REPO: ${{ github.repository }}
MAUI_VERSION: ${{ needs.build.outputs.maui_version }}
run: |
gh release create "PowerSync.Maui@${MAUI_VERSION}" \
--draft \
--title "PowerSync.Maui@${MAUI_VERSION}" \
--target main \
--generate-notes \
SignedArtifacts/PowerSync.Maui*.nupkg
6 changes: 6 additions & 0 deletions PowerSync/PowerSync.Common/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,11 @@
# PowerSync.Common Changelog

## Unreleased

- **Breaking:** `PowerSync.Maui` has been folded into `PowerSync.Common` and is no longer published. Mobile and desktop targets are now served by a single package.
- Remove the `PowerSync.Maui` package reference; `PowerSync.Common` alone is sufficient on all platforms.
- Replace `MAUISQLiteDBOpenFactory` with `MDSQLiteDBOpenFactory` (from `PowerSync.Common.MDSQLite`) and drop the `using PowerSync.Maui.SQLite;` import. `MAUISQLiteAdapter` is likewise replaced by `MDSQLiteAdapter`, which now selects the correct native extension per platform.

## 0.1.4

- Update the PowerSync SQLite core extension to 0.5.2.
Expand Down
31 changes: 28 additions & 3 deletions PowerSync/PowerSync.Common/MDSQLite/MDSQLiteAdapter.cs
Original file line number Diff line number Diff line change
Expand Up @@ -153,16 +153,41 @@ protected virtual void LoadExtensions(SqliteConnection db)
}

/// <summary>
/// Loads the bundled PowerSync core SQLite extension. Override on
/// platform-specific adapters (e.g. MAUI iOS/Android) where the native library
/// lives outside the desktop runtime path.
/// Loads the bundled PowerSync core SQLite extension. The extension ships in a
/// different form per platform: an xcframework on iOS/MacCatalyst, a jniLib on
/// Android, and a plain native library under runtimes/ on desktop.
/// </summary>
protected virtual void LoadDefaultPowerSyncExtension(SqliteConnection db)
{
#if IOS || MACCATALYST
LoadAppleFrameworkExtension(db);
#elif ANDROID
db.LoadExtension("libpowersync");
#else
var path = PowerSyncPathResolver.GetNativeLibraryPath(AppContext.BaseDirectory);
db.LoadExtension(path, "sqlite3_powersync_init");
#endif
}

#if IOS || MACCATALYST
private static void LoadAppleFrameworkExtension(SqliteConnection db)
{
var bundlePath = Foundation.NSBundle.FromIdentifier("co.powersync.sqlitecore")?.BundlePath;
if (bundlePath == null)
{
throw new Exception("Could not find PowerSync SQLite extension bundle path");
}

var filePath = Path.Combine(bundlePath, "powersync-sqlite-core");

using var loadExtension = db.CreateCommand();
loadExtension.CommandText = "SELECT load_extension(@path, @entryPoint)";
loadExtension.Parameters.AddWithValue("@path", filePath);
loadExtension.Parameters.AddWithValue("@entryPoint", "sqlite3_powersync_init");
loadExtension.ExecuteNonQuery();
}
#endif

public async Task Close()
{
tablesUpdatedCts?.Cancel();
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
namespace PowerSync.Maui.build
namespace PowerSync.Common.Platforms
{
// Empty API definition - allows xcframework to be included without managed bindings
}
44 changes: 36 additions & 8 deletions PowerSync/PowerSync.Common/PowerSync.Common.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,10 @@
<NoWarn>NU5100</NoWarn>
<PackageReadmeFile>README.md</PackageReadmeFile>
<DefaultItemExcludes>$(DefaultItemExcludes);runtimes/**/*.*;</DefaultItemExcludes>
<!-- Apple TFMs carry the powersync-sqlite-core xcframework as a NativeReference,
which requires binding-project semantics so the framework travels in the NuGet package. -->
<IsBindingProject Condition="$(TargetFramework.Contains('-ios')) OR $(TargetFramework.Contains('-maccatalyst'))">true</IsBindingProject>
<IncludeBuildOutput>true</IncludeBuildOutput>
</PropertyGroup>

<ItemGroup>
Expand All @@ -42,21 +46,45 @@
<None Include="PowerSync.Common.targets" Pack="true" PackagePath="buildTransitive\" />
</ItemGroup>

<!-- Check allows us to skip for all MAUI targets-->
<!-- For monorepo-->
<!-- The desktop native libraries. CopyToOutputDirectory serves projects that reference
this one directly (the demos in this repo); PackagePath ships them to NuGet consumers
under runtimes/, from where PowerSync.Common.targets copies them into the consuming
project's output.

PackagePath is what keeps these out of contentFiles. Without it, NuGet gathers content
during the cross-targeting outer build, where $(TargetFramework) is empty, so the
condition below cannot distinguish target frameworks and every one of them — iOS,
Android and MacCatalyst included — receives a copy of every desktop binary. -->
<ItemGroup Condition="!$(TargetFramework.EndsWith('-android')) AND !$(TargetFramework.EndsWith('-ios')) AND !$(TargetFramework.EndsWith('-maccatalyst'))">
<Content Include="runtimes\**\*.*">
<Content Include="runtimes\**\*.*" Pack="true" PackagePath="runtimes\">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
</ItemGroup>

<!-- For releasing runtimes -->
<ItemGroup Condition="!$(TargetFramework.EndsWith('-android')) AND !$(TargetFramework.EndsWith('-ios')) AND !$(TargetFramework.EndsWith('-maccatalyst'))">
<None Include="runtimes\**\*.*" Pack="true" PackagePath="runtimes\" />
</ItemGroup>

<ItemGroup>
<None Include="..\..\icon.png" Pack="true" PackagePath="" />
<None Include="README.md" Pack="true" PackagePath="" />
</ItemGroup>

<!-- Bundled PowerSync core extension for Apple targets. The xcframework is
self-describing, so the same one serves both iOS and MacCatalyst. -->
<ItemGroup Condition="$(TargetFramework.Contains('-ios')) OR $(TargetFramework.Contains('-maccatalyst'))">
<ObjcBindingApiDefinition Include="Platforms\ApiDefinition.cs" />

<NativeReference Include="Platforms\Apple\NativeLibs\powersync-sqlite-core.xcframework">
<Kind>Framework</Kind>
<SmartLink>False</SmartLink>
</NativeReference>
</ItemGroup>

<!-- Prevent e_sqlite3.a from being frozen into the binding manifest. It is provided by
SQLitePCLRaw.lib.e_sqlite3.ios with separate device/simulator variants, selected at
consuming-project build time via buildTransitive targets. Capturing it here would bake
in the device-only variant and break simulator builds in consuming projects. -->
<Target Name="_RemoveE_Sqlite3FromBindingManifest" BeforeTargets="_SanitizeNativeReferences" Condition="'$(IsBindingProject)' == 'true'">
<ItemGroup>
<NativeReference Remove="@(NativeReference)" Condition="'%(Filename)' == 'e_sqlite3'" />
</ItemGroup>
</Target>

</Project>
17 changes: 16 additions & 1 deletion PowerSync/PowerSync.Common/PowerSync.Common.targets
Original file line number Diff line number Diff line change
@@ -1,7 +1,22 @@
<Project>
<!-- Copies the desktop native libraries out of the package and into the consuming
project's output, where PowerSyncPathResolver looks for them at runtime.

This replaces packing them as contentFiles. NuGet gathers content during the
cross-targeting outer build, where $(TargetFramework) is empty, so it cannot tell the
target frameworks apart and fans the same files out to every one of them — including
iOS, Android and MacCatalyst, which bundle their own native extension and can never
use these. Here $(TargetFramework) is the consumer's, so the check works. -->
<ItemGroup Condition="!$(TargetFramework.Contains('-android')) AND !$(TargetFramework.Contains('-ios')) AND !$(TargetFramework.Contains('-maccatalyst'))">
<None Include="$(MSBuildThisFileDirectory)../runtimes/**/*.*"
Link="runtimes/%(RecursiveDir)%(Filename)%(Extension)"
CopyToOutputDirectory="PreserveNewest"
Visible="false" />
</ItemGroup>

<Target Name="RemovePowerSyncNativeForAndroid" AfterTargets="ResolvePackageAssets" Condition="$(TargetFramework.Contains('android'))">
<ItemGroup>
<NativeCopyLocalItems Remove="@(NativeCopyLocalItems)" Condition="'%(NuGetPackageId)' == 'PowerSync.Common'" />
</ItemGroup>
</Target>
</Project>
</Project>
22 changes: 22 additions & 0 deletions PowerSync/PowerSync.Common/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@

This package contains a .NET implementation of a PowerSync database connector and streaming sync bucket implementation.

It bundles the native PowerSync SQLite extension for every supported target and loads the right one automatically, so no additional package is required on mobile.

## ⚠️ Project Status & Release Note

This package is in beta and is considered ready for production use for tested use cases. See our feature status definitions [here](https://docs.powersync.com/resources/feature-status).
Expand Down Expand Up @@ -36,6 +38,26 @@ static async Task Main() {

```

### MAUI / mobile

Initialization is the same on mobile, except that the database file must be placed in a
platform-appropriate location. Supply an `MDSQLiteDBOpenFactory` built from that path:

```csharp
var dbPath = Path.Combine(FileSystem.AppDataDirectory, "maui-example.db");
var factory = new MDSQLiteDBOpenFactory(new MDSQLiteOpenFactoryOptions
{
DbFilename = dbPath
});

var db = new PowerSyncDatabase(new PowerSyncDatabaseOptions
{
Database = factory,
Schema = AppSchema.PowerSyncSchema,
});
await db.Init();
```

### Watched queries

Watched queries will automatically update when a dependant table is updated.
Expand Down
67 changes: 0 additions & 67 deletions PowerSync/PowerSync.Maui/CHANGELOG.md

This file was deleted.

Loading