Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
23 commits
Select commit Hold shift + click to select a range
7d42a37
Bundle native libraries with PowerSync.Common and use in demos
LucDeCaf Aug 20, 2026
135c524
Clean out Maui
LucDeCaf Aug 20, 2026
fcd4885
workflow updates
LucDeCaf Aug 20, 2026
ba789a9
more workflow updates
LucDeCaf Aug 20, 2026
0c960e1
Merge branch 'dotnet-10' into remove-maui
LucDeCaf Sep 9, 2026
a6ed36e
better native asset filtering
LucDeCaf Sep 14, 2026
811abf2
fix docs workflows still using net8.0
LucDeCaf Sep 14, 2026
12a0fd9
update docs config + more workflow changes + readme
LucDeCaf Sep 14, 2026
c418998
Fix Tools/Setup
LucDeCaf Sep 14, 2026
5cbc66f
net10.0 in docs
LucDeCaf Sep 14, 2026
f38bf6e
Convert PowerSync to PowerSync.Common in toc.yml
LucDeCaf Sep 14, 2026
8dd8b17
hack: up test timeouts
LucDeCaf Sep 14, 2026
5459835
enable nullable and implicitUsings in Setup.csproj
LucDeCaf Sep 15, 2026
dcdfac4
readd .env to root .gitignore
LucDeCaf Sep 15, 2026
736ca49
fix some race conditions causing tests to fail
LucDeCaf Sep 15, 2026
d4e7f53
Use long instead of string for more Ids
LucDeCaf Sep 16, 2026
d39e0db
throw on Setup exception to prevent CI builds from publishing without…
LucDeCaf Sep 16, 2026
b4c78b6
oops
LucDeCaf Sep 16, 2026
a8e4936
subscribe eagerly in way more events
LucDeCaf Sep 16, 2026
bce2cb1
fix demo failing on iOS and windows
LucDeCaf Sep 17, 2026
056b70f
Merge branch 'dotnet-10' into remove-maui
LucDeCaf Sep 18, 2026
c5f3fef
dev release
LucDeCaf Sep 21, 2026
b99a28c
add sign-file-list.txt to prevent unzipping xcframework
LucDeCaf Sep 21, 2026
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
3 changes: 1 addition & 2 deletions .github/workflows/build-docs.yml
Original file line number Diff line number Diff line change
Expand Up @@ -25,8 +25,7 @@ jobs:

- name: Restore Projects
run: |
dotnet restore PowerSync/PowerSync.Common/PowerSync.Common.csproj -p:TargetFrameworks=net8.0
dotnet restore PowerSync/PowerSync.Maui/PowerSync.Maui.csproj -p:TargetFrameworks=net8.0
dotnet restore PowerSync/PowerSync.Common/PowerSync.Common.csproj -p:TargetFrameworks=net10.0

- name: Generate API Metadata
working-directory: docs
Expand Down
3 changes: 1 addition & 2 deletions .github/workflows/deploy-docs.yml
Original file line number Diff line number Diff line change
Expand Up @@ -31,8 +31,7 @@ jobs:

- name: Restore Projects
run: |
dotnet restore PowerSync/PowerSync.Common/PowerSync.Common.csproj -p:TargetFrameworks=net8.0
dotnet restore PowerSync/PowerSync.Maui/PowerSync.Maui.csproj -p:TargetFrameworks=net8.0
dotnet restore PowerSync/PowerSync.Common/PowerSync.Common.csproj -p:TargetFrameworks=net10.0

- name: Generate API Metadata
working-directory: docs
Expand Down
35 changes: 9 additions & 26 deletions .github/workflows/dev-packages.yml
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ jobs:
with:
dotnet-version: "10.0.x"

- name: Install MAUI Workloads
- name: Install native workloads
run: dotnet workload restore

- name: Download PowerSync extension
Expand All @@ -33,9 +33,6 @@ jobs:
- name: Restore dependencies
run: dotnet restore

- name: Install Android SDK for net8.0-android
run: dotnet build PowerSync/PowerSync.Common -t:InstallAndroidDependencies -f net8.0-android -p:AndroidSdkDirectory="$ANDROID_HOME" -p:AcceptAndroidSdkLicenses=True

- name: Extract Common Package Version from CHANGELOG.md
shell: bash
run: |
Expand All @@ -50,20 +47,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 All @@ -81,6 +64,11 @@ jobs:
contents: read

steps:
- name: Checkout Repository
uses: actions/checkout@v4
with:
ref: ${{ github.ref }}

- name: Download build artifacts
uses: actions/download-artifact@v4
with:
Expand All @@ -90,7 +78,7 @@ jobs:
- name: Setup .NET
uses: actions/setup-dotnet@v4
with:
dotnet-version: "8.0.x"
dotnet-version: "10.0.x"

- name: Install Sign CLI tool
run: dotnet tool install --tool-path . --prerelease sign
Expand All @@ -108,6 +96,7 @@ jobs:
./sign code azure-key-vault
**/*.nupkg
--base-directory "${{ github.workspace }}/BuildArtifacts"
--file-list "${{ github.workspace }}/Tools/Setup/sign-file-list.txt"
--publisher-name "PowerSync"
--description "PowerSync .NET SDK"
--description-url "https://github.com/powersync-ja/powersync-dotnet"
Expand Down Expand Up @@ -142,7 +131,7 @@ jobs:
- name: Setup .NET
uses: actions/setup-dotnet@v4
with:
dotnet-version: "8.0.x"
dotnet-version: "10.0.x"

- name: Validate artifact signatures
run: dotnet nuget verify ${{ github.workspace }}/SignedArtifacts/**/*.nupkg
Expand All @@ -158,9 +147,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
53 changes: 9 additions & 44 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 All @@ -28,7 +27,7 @@ jobs:
with:
dotnet-version: "10.0.x"

- name: Install MAUI Workloads
- name: Install native workloads
run: dotnet workload restore

- name: Download PowerSync extension
Expand All @@ -37,9 +36,6 @@ jobs:
- name: Restore dependencies
run: dotnet restore

- name: Install Android SDK for net8.0-android
run: dotnet build PowerSync/PowerSync.Common -t:InstallAndroidDependencies -f net8.0-android -p:AndroidSdkDirectory="$ANDROID_HOME" -p:AcceptAndroidSdkLicenses=True

- name: Extract Common Package Version from CHANGELOG.md
id: extract_version
shell: bash
Expand All @@ -56,22 +52,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 All @@ -89,6 +69,11 @@ jobs:
contents: read

steps:
- name: Checkout Repository
uses: actions/checkout@v4
with:
ref: ${{ github.ref }}

- name: Download build artifacts
uses: actions/download-artifact@v4
with:
Expand All @@ -98,7 +83,7 @@ jobs:
- name: Setup .NET
uses: actions/setup-dotnet@v4
with:
dotnet-version: "8.0.x"
dotnet-version: "10.0.x"

- name: Install Sign CLI tool
run: dotnet tool install --tool-path . --prerelease sign
Expand All @@ -116,6 +101,7 @@ jobs:
./sign code azure-key-vault
**/*.nupkg
--base-directory "${{ github.workspace }}/BuildArtifacts"
--file-list "${{ github.workspace }}/Tools/Setup/sign-file-list.txt"
--publisher-name "PowerSync"
--description "PowerSync .NET SDK"
--description-url "https://github.com/powersync-ja/powersync-dotnet"
Expand Down Expand Up @@ -150,7 +136,7 @@ jobs:
- name: Setup .NET
uses: actions/setup-dotnet@v4
with:
dotnet-version: "8.0.x"
dotnet-version: "10.0.x"

- name: Validate artifact signatures
run: dotnet nuget verify ${{ github.workspace }}/SignedArtifacts/**/*.nupkg
Expand Down Expand Up @@ -181,24 +167,3 @@ jobs:
--target main \
--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
12 changes: 6 additions & 6 deletions .github/workflows/test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ on:
jobs:
build:
strategy:
matrix:
matrix:
runner: [windows-latest, windows-11-arm]
name: Test Packages ${{ matrix.runner }}
runs-on: ${{ matrix.runner }}
Expand All @@ -18,16 +18,16 @@ jobs:
- name: Setup .NET SDK
uses: actions/setup-dotnet@v5
with:
dotnet-version: '10.0'
dotnet-version: "10.0"

- name: Install MAUI Workloads
- name: Install native workloads
run: dotnet workload restore

- name: Download PowerSync extension
run: dotnet run --project Tools/Setup
run: dotnet run --project Tools/Setup

- name: Restore dependencies
run: dotnet restore

- name: Run tests
run: dotnet test -v n --framework net10.0
10 changes: 3 additions & 7 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -53,18 +53,14 @@ TestResults/
*.VSIXProjectLaunch
.project
.vsconfig
.env

*.db
*.db-shm
*.db-wal

#Core binaries - add rules after ps extension downloading is supported
*.dylib
*.dll
*.so
*.xcframework
.env
*NativeLibs
# PowerSync runtimes installed by Tools/Setup
**/runtimes/

# Ignore user id file
user_id.txt
Expand Down
5 changes: 3 additions & 2 deletions PowerSync/PowerSync.Common/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,10 +1,11 @@
# PowerSync.Common Changelog

## 1.0.1 (unreleased)
## 1.0.1-dev.2

- Full release.
- `PowerSyncDatabase.OnChange` now returns the underlying raw table name instead of the view name to mirror PowerSync JS.
- Use `long` for op IDs instead of `string`. This affects the types returned by some methods used in `PowerSyncBackendConnector.UploadData`, namely `PowerSyncDatabase.GetNextCrudTransaction()` and `PowerSyncDatabase.GetCrudBatch()`.
- Use `long` for op IDs instead of `string`. This affects the types returned by some methods used in `PowerSyncBackendConnector.UploadData`, namely `PowerSyncDatabase.GetNextCrudTransaction()` and `PowerSyncDatabase.GetCrudBatch()`, as well as `ICustomCheckpointRequestConnector.PostCheckpointRequest`.
- Bundle and load native libraries on Android, iOS, and MacCatalyst. This allows `PowerSync.Common` to fully replace `PowerSync.Maui`.

## 1.0.0 (unlisted)

Expand Down
52 changes: 34 additions & 18 deletions PowerSync/PowerSync.Common/Client/PowerSyncDatabase.cs
Original file line number Diff line number Diff line change
Expand Up @@ -154,6 +154,10 @@ public class PowerSyncDatabase : IPowerSyncDatabase

protected IBucketStorageAdapter BucketStorageAdapter;

private readonly object currentStatusLock = new();
/// <summary>
/// The latest published sync status.
/// </summary>
public SyncStatus CurrentStatus { get; protected set; }

protected CancellationTokenSource masterCts = new();
Expand All @@ -163,6 +167,7 @@ public class PowerSyncDatabase : IPowerSyncDatabase
public ILogger Logger { get; protected set; }

private readonly AsyncLock runExclusive = new();

private readonly Func<IPowerSyncBackendConnector, Remote> remoteFactory;

public StreamingSyncImplementation? SyncStreamImplementation => ConnectionManager.SyncStreamImplementation;
Expand Down Expand Up @@ -225,6 +230,8 @@ public PowerSyncDatabase(PowerSyncDatabaseOptions options)
await WaitForReady();
using (await runExclusive.LockAsync())
{
var syncStreamStatusCts = CancellationTokenSource.CreateLinkedTokenSource(masterCts.Token);

syncStreamImplementation = new StreamingSyncImplementation(new StreamingSyncImplementationOptions
{
Adapter = BucketStorageAdapter,
Expand All @@ -245,20 +252,22 @@ public PowerSyncDatabase(PowerSyncDatabaseOptions options)
Subscriptions = options.Subscriptions,
CrudUploadThrottleMs = options.CrudUploadThrottleMs,
TimeProvider = timeProvider,
Logger = Logger
});

var syncStreamStatusCts = CancellationTokenSource.CreateLinkedTokenSource(masterCts.Token);
var syncStreamStatusListener = syncStreamImplementation.Events.OnStatusChanged.ListenAsync(syncStreamStatusCts.Token);
var _ = Task.Run(async () =>
{
await foreach (var update in syncStreamStatusListener)
Logger = Logger,
OnStatusChanged = status =>
{
CurrentStatus = new SyncStatus(new SyncStatusOptions(update.Status.Options)
if (syncStreamStatusCts.IsCancellationRequested)
{
HasSynced = CurrentStatus?.HasSynced == true || update.Status.LastSyncedAt != null,
});
Events.Emit(new PowerSyncDBEvents.StatusChangedEvent(CurrentStatus));
return;
}

lock (currentStatusLock)
{
CurrentStatus = new SyncStatus(new SyncStatusOptions(status.Options)
{
HasSynced = CurrentStatus?.HasSynced == true || status.LastSyncedAt != null,
});
Events.Emit(new PowerSyncDBEvents.StatusChangedEvent(CurrentStatus));
}
}
});

Expand Down Expand Up @@ -431,12 +440,16 @@ protected async Task ResolveOfflineSyncStatus()
var parsed = JsonConvert.DeserializeObject<CoreSyncStatus>(result.r);

var parsedSyncStatus = CoreInstructionHelpers.CoreStatusToSyncStatus(parsed!);
var updatedStatus = CurrentStatus.CreateUpdatedStatus(parsedSyncStatus);

if (!updatedStatus.IsEqual(CurrentStatus))
lock (currentStatusLock)
{
CurrentStatus = updatedStatus;
Events.Emit(new PowerSyncDBEvents.StatusChangedEvent(CurrentStatus));
var updatedStatus = CurrentStatus.CreateUpdatedStatus(parsedSyncStatus);

if (!updatedStatus.IsEqual(CurrentStatus))
{
CurrentStatus = updatedStatus;
Events.Emit(new PowerSyncDBEvents.StatusChangedEvent(CurrentStatus));
}
}
}

Expand Down Expand Up @@ -531,8 +544,11 @@ await Database.WriteTransaction(async tx =>
});

// The data has been deleted - reset the sync status
CurrentStatus = new SyncStatus(new SyncStatusOptions());
Events.Emit(new PowerSyncDBEvents.StatusChangedEvent(CurrentStatus));
lock (currentStatusLock)
{
CurrentStatus = new SyncStatus(new SyncStatusOptions());
Events.Emit(new PowerSyncDBEvents.StatusChangedEvent(CurrentStatus));
}
}

/// <summary>
Expand Down
Loading
Loading