From 98cb1d6145bc12a3fbb3b7cd284c45b6a471a087 Mon Sep 17 00:00:00 2001 From: stevensJourney Date: Thu, 31 Jul 2025 16:47:40 +0200 Subject: [PATCH 1/5] demo improvements --- .gitignore | 3 ++ Demo/PowerSyncExample/Navigation.swift | 5 --- .../PowerSync/SupabaseConnector.swift | 6 ++- Demo/PowerSyncExample/RootView.swift | 6 +-- .../PowerSyncExample/Screens/HomeScreen.swift | 2 - .../Screens/SignInScreen.swift | 2 - .../Screens/SignUpScreen.swift | 2 - Demo/PowerSyncExample/_Secrets.swift | 40 +++++++++++++++---- Demo/README.md | 7 +++- 9 files changed, 47 insertions(+), 26 deletions(-) diff --git a/.gitignore b/.gitignore index 1a06cf8..fb8464f 100644 --- a/.gitignore +++ b/.gitignore @@ -69,3 +69,6 @@ DerivedData/ .swiftpm/configuration/registries.json .swiftpm/xcode/package.xcworkspace/contents.xcworkspacedata .netrc + + +Secrets.swift \ No newline at end of file diff --git a/Demo/PowerSyncExample/Navigation.swift b/Demo/PowerSyncExample/Navigation.swift index a8e0802..202809f 100644 --- a/Demo/PowerSyncExample/Navigation.swift +++ b/Demo/PowerSyncExample/Navigation.swift @@ -6,11 +6,6 @@ enum Route: Hashable { case signUp } -@Observable -class AuthModel { - var isAuthenticated = false -} - @Observable class NavigationModel { var path = NavigationPath() diff --git a/Demo/PowerSyncExample/PowerSync/SupabaseConnector.swift b/Demo/PowerSyncExample/PowerSync/SupabaseConnector.swift index bb27290..6024923 100644 --- a/Demo/PowerSyncExample/PowerSync/SupabaseConnector.swift +++ b/Demo/PowerSyncExample/PowerSync/SupabaseConnector.swift @@ -40,7 +40,10 @@ private enum PostgresFatalCodes { @Observable class SupabaseConnector: PowerSyncBackendConnector { let powerSyncEndpoint: String = Secrets.powerSyncEndpoint - let client: SupabaseClient = .init(supabaseURL: Secrets.supabaseURL, supabaseKey: Secrets.supabaseAnonKey) + let client: SupabaseClient = .init( + supabaseURL: Secrets.supabaseURL, + supabaseKey: Secrets.supabaseAnonKey, + ) var session: Session? private var errorCode: String? @@ -49,6 +52,7 @@ class SupabaseConnector: PowerSyncBackendConnector { override init() { super.init() + session = client.auth.currentSession observeAuthStateChangesTask = Task { [weak self] in guard let self = self else { return } diff --git a/Demo/PowerSyncExample/RootView.swift b/Demo/PowerSyncExample/RootView.swift index e4a03e1..baed264 100644 --- a/Demo/PowerSyncExample/RootView.swift +++ b/Demo/PowerSyncExample/RootView.swift @@ -3,14 +3,13 @@ import SwiftUI struct RootView: View { @Environment(SystemManager.self) var system - - @State private var authModel = AuthModel() + @State private var navigationModel = NavigationModel() var body: some View { NavigationStack(path: $navigationModel.path) { Group { - if authModel.isAuthenticated { + if system.connector.session != nil { HomeScreen() } else { SignInScreen() @@ -27,7 +26,6 @@ struct RootView: View { } } } - .environment(authModel) .environment(navigationModel) } } diff --git a/Demo/PowerSyncExample/Screens/HomeScreen.swift b/Demo/PowerSyncExample/Screens/HomeScreen.swift index 6a4da2f..8ad4437 100644 --- a/Demo/PowerSyncExample/Screens/HomeScreen.swift +++ b/Demo/PowerSyncExample/Screens/HomeScreen.swift @@ -4,7 +4,6 @@ import SwiftUI struct HomeScreen: View { @Environment(SystemManager.self) private var system - @Environment(AuthModel.self) private var authModel @Environment(NavigationModel.self) private var navigationModel @@ -16,7 +15,6 @@ struct HomeScreen: View { Button("Sign out") { Task { try await system.signOut() - authModel.isAuthenticated = false navigationModel.path = NavigationPath() } } diff --git a/Demo/PowerSyncExample/Screens/SignInScreen.swift b/Demo/PowerSyncExample/Screens/SignInScreen.swift index ce9d67e..4102f2e 100644 --- a/Demo/PowerSyncExample/Screens/SignInScreen.swift +++ b/Demo/PowerSyncExample/Screens/SignInScreen.swift @@ -8,7 +8,6 @@ private enum ActionState { struct SignInScreen: View { @Environment(SystemManager.self) private var system - @Environment(AuthModel.self) private var authModel @Environment(NavigationModel.self) private var navigationModel @State private var email = "" @@ -66,7 +65,6 @@ struct SignInScreen: View { actionState = .inFlight try await system.connector.client.auth.signIn(email: email, password: password) actionState = .result(.success(())) - authModel.isAuthenticated = true navigationModel.path = NavigationPath() } catch { withAnimation { diff --git a/Demo/PowerSyncExample/Screens/SignUpScreen.swift b/Demo/PowerSyncExample/Screens/SignUpScreen.swift index 0d2693a..4d039f1 100644 --- a/Demo/PowerSyncExample/Screens/SignUpScreen.swift +++ b/Demo/PowerSyncExample/Screens/SignUpScreen.swift @@ -8,7 +8,6 @@ private enum ActionState { struct SignUpScreen: View { @Environment(SystemManager.self) private var system - @Environment(AuthModel.self) private var authModel @Environment(NavigationModel.self) private var navigationModel @State private var email = "" @@ -66,7 +65,6 @@ struct SignUpScreen: View { redirectTo: Constants.redirectToURL ) actionState = .result(.success(())) - authModel.isAuthenticated = true navigationModel.path = NavigationPath() } catch { withAnimation { diff --git a/Demo/PowerSyncExample/_Secrets.swift b/Demo/PowerSyncExample/_Secrets.swift index 5959dc8..ce675bd 100644 --- a/Demo/PowerSyncExample/_Secrets.swift +++ b/Demo/PowerSyncExample/_Secrets.swift @@ -1,10 +1,34 @@ import Foundation -// Enter your Supabase and PowerSync project details. -enum Secrets { - static let powerSyncEndpoint = "https://your-id.powersync.journeyapps.com" - static let supabaseURL = URL(string: "https://your-id.supabase.co")! - static let supabaseAnonKey = "anon-key" - // Optional storage bucket name. Set to nil if you don't want to use storage. - static let supabaseStorageBucket: String? = nil -} \ No newline at end of file +/// A protocol which specified the base structure for secrets +protocol SecretsProvider { + static var powerSyncEndpoint: String { get } + static var supabaseURL: URL { get } + static var supabaseAnonKey: String { get } + static var supabaseStorageBucket: String? { get } +} + +/// A default implementation of [SecretsProvider]. +/// This implementation ensures the app will compile even if no actual secrets are provided. +/// Devs should specify the actual secrets in a Git ignored file. +extension SecretsProvider { + static var powerSyncEndpoint: String { + return "TODO" + } + + static var supabaseURL: URL { + return URL(string: "TODO")! + } + + static var supabaseAnonKey: String { + return "TODO" + } + + static var supabaseStorageBucket: String? { + return nil + } +} + + +// Default conforming type +enum Secrets: SecretsProvider {} diff --git a/Demo/README.md b/Demo/README.md index e3369d1..a92efed 100644 --- a/Demo/README.md +++ b/Demo/README.md @@ -16,7 +16,11 @@ Follow this guide to: 1. Open this directory in XCode. -2. Open the “_Secrets” file and insert the credentials of your Supabase and PowerSync projects (more info can be found [here](https://docs.powersync.com/integration-guides/supabase-+-powersync#test-everything-using-our-demo-app)). +2. Copy the `Secrets.template` file to a new Swift file and insert the credentials of your Supabase and PowerSync projects (more info can be found [here](https://docs.powersync.com/integration-guides/supabase-+-powersync#test-everything-using-our-demo-app)). + +```bash +cp Secrets.template Secrets.swift +``` 3. You will need to enable `CasePathMacros` for SwiftUI Navigation. You can do this in settings, or just build the app and a dialog will be shown to enable `CasePathMacros`. @@ -36,7 +40,6 @@ rm -rf ~/Library/org.swift.swiftpm - Reset Packages: File -> Packages -> Reset Package Caches - Clean Build: Product -> Clean Build Folder. - ## Run project Build the project, launch the app and sign in or register a new user. From 8dbe38df366c8ea7cf9cab10477a4055fecd7b89 Mon Sep 17 00:00:00 2001 From: stevensJourney Date: Thu, 31 Jul 2025 16:58:26 +0200 Subject: [PATCH 2/5] update readme --- .../project.pbxproj | 4 ++++ Demo/PowerSyncExample/Secrets.template | 19 +++++++++++++++++++ Demo/PowerSyncExample/_Secrets.swift | 4 ++-- Demo/README.md | 2 ++ 4 files changed, 27 insertions(+), 2 deletions(-) create mode 100644 Demo/PowerSyncExample/Secrets.template diff --git a/Demo/PowerSyncExample.xcodeproj/project.pbxproj b/Demo/PowerSyncExample.xcodeproj/project.pbxproj index 4f881e4..76e7d01 100644 --- a/Demo/PowerSyncExample.xcodeproj/project.pbxproj +++ b/Demo/PowerSyncExample.xcodeproj/project.pbxproj @@ -41,6 +41,7 @@ B6B3698A2C64F4B30033C307 /* Navigation.swift in Sources */ = {isa = PBXBuildFile; fileRef = B6B369892C64F4B30033C307 /* Navigation.swift */; }; B6FFD5322D06DA8000EEE60F /* PowerSync in Frameworks */ = {isa = PBXBuildFile; productRef = B6FFD5312D06DA8000EEE60F /* PowerSync */; }; BE2F26EC2DA54B2F0080F1AE /* SupabaseRemoteStorage.swift in Sources */ = {isa = PBXBuildFile; fileRef = BE2F26EB2DA54B2A0080F1AE /* SupabaseRemoteStorage.swift */; }; + BEE4708B2E3BBB2500140D11 /* Secrets.swift in Sources */ = {isa = PBXBuildFile; fileRef = BEE4708A2E3BBB2500140D11 /* Secrets.swift */; }; /* End PBXBuildFile section */ /* Begin PBXCopyFilesBuildPhase section */ @@ -108,6 +109,7 @@ B6F4213D2BC42F5B0005D0D0 /* sqlite3.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; name = sqlite3.c; path = "../powersync-kotlin/core/build/interop/sqlite/sqlite3.c"; sourceTree = ""; }; B6F421402BC430B60005D0D0 /* sqlite3.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = sqlite3.h; path = "../powersync-kotlin/core/build/interop/sqlite/sqlite3.h"; sourceTree = ""; }; BE2F26EB2DA54B2A0080F1AE /* SupabaseRemoteStorage.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SupabaseRemoteStorage.swift; sourceTree = ""; }; + BEE4708A2E3BBB2500140D11 /* Secrets.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Secrets.swift; sourceTree = ""; }; /* End PBXFileReference section */ /* Begin PBXFrameworksBuildPhase section */ @@ -151,6 +153,7 @@ 6A7315862B9854220004CB17 /* PowerSyncExample */ = { isa = PBXGroup; children = ( + BEE4708A2E3BBB2500140D11 /* Secrets.swift */, B65C4D6F2C60D58500176007 /* PowerSync */, B65C4D6E2C60D52E00176007 /* Components */, B65C4D6B2C60D36700176007 /* Screens */, @@ -564,6 +567,7 @@ 6ABD78672B9F2B4800558A41 /* RootView.swift in Sources */, B66658612C62179E00159A81 /* ListView.swift in Sources */, 6ABD78782B9F2D2800558A41 /* Schema.swift in Sources */, + BEE4708B2E3BBB2500140D11 /* Secrets.swift in Sources */, B65C4D6D2C60D38B00176007 /* HomeScreen.swift in Sources */, 6A7315882B9854220004CB17 /* PowerSyncExampleApp.swift in Sources */, B666585F2C62115300159A81 /* ListRow.swift in Sources */, diff --git a/Demo/PowerSyncExample/Secrets.template b/Demo/PowerSyncExample/Secrets.template new file mode 100644 index 0000000..49dd8ae --- /dev/null +++ b/Demo/PowerSyncExample/Secrets.template @@ -0,0 +1,19 @@ +import Foundation + +extension Secrets { + static var powerSyncEndpoint: String { + return "https://todo.powersync.com" + } + + static var supabaseURL: URL { + return URL(string: "https://todo.supabase.co")! + } + + static var supabaseAnonKey: String { + return "TODO" + } + + static var supabaseStorageBucket: String? { + return nil + } +} \ No newline at end of file diff --git a/Demo/PowerSyncExample/_Secrets.swift b/Demo/PowerSyncExample/_Secrets.swift index ce675bd..d956630 100644 --- a/Demo/PowerSyncExample/_Secrets.swift +++ b/Demo/PowerSyncExample/_Secrets.swift @@ -13,11 +13,11 @@ protocol SecretsProvider { /// Devs should specify the actual secrets in a Git ignored file. extension SecretsProvider { static var powerSyncEndpoint: String { - return "TODO" + return "https://todo.powersync.com" } static var supabaseURL: URL { - return URL(string: "TODO")! + return URL(string: "https://todo.supabase.co")! } static var supabaseAnonKey: String { diff --git a/Demo/README.md b/Demo/README.md index a92efed..5dee264 100644 --- a/Demo/README.md +++ b/Demo/README.md @@ -22,6 +22,8 @@ Follow this guide to: cp Secrets.template Secrets.swift ``` +Add the `Secrets.swift` file to the project in XCode. Right click on the `PowerSyncExample` tree item then select `Add files to PowerSyncExample`. + 3. You will need to enable `CasePathMacros` for SwiftUI Navigation. You can do this in settings, or just build the app and a dialog will be shown to enable `CasePathMacros`. ### Troubleshooting From 555ec9981053bbc7e8ca4d0da9d8de70a2315aad Mon Sep 17 00:00:00 2001 From: stevensJourney Date: Thu, 31 Jul 2025 17:12:54 +0200 Subject: [PATCH 3/5] cleanup secrets. Remove duplication. --- Demo/PowerSyncExample/_Secrets.swift | 22 ---------------------- Demo/README.md | 2 -- 2 files changed, 24 deletions(-) diff --git a/Demo/PowerSyncExample/_Secrets.swift b/Demo/PowerSyncExample/_Secrets.swift index d956630..871ddf2 100644 --- a/Demo/PowerSyncExample/_Secrets.swift +++ b/Demo/PowerSyncExample/_Secrets.swift @@ -8,27 +8,5 @@ protocol SecretsProvider { static var supabaseStorageBucket: String? { get } } -/// A default implementation of [SecretsProvider]. -/// This implementation ensures the app will compile even if no actual secrets are provided. -/// Devs should specify the actual secrets in a Git ignored file. -extension SecretsProvider { - static var powerSyncEndpoint: String { - return "https://todo.powersync.com" - } - - static var supabaseURL: URL { - return URL(string: "https://todo.supabase.co")! - } - - static var supabaseAnonKey: String { - return "TODO" - } - - static var supabaseStorageBucket: String? { - return nil - } -} - - // Default conforming type enum Secrets: SecretsProvider {} diff --git a/Demo/README.md b/Demo/README.md index 5dee264..a92efed 100644 --- a/Demo/README.md +++ b/Demo/README.md @@ -22,8 +22,6 @@ Follow this guide to: cp Secrets.template Secrets.swift ``` -Add the `Secrets.swift` file to the project in XCode. Right click on the `PowerSyncExample` tree item then select `Add files to PowerSyncExample`. - 3. You will need to enable `CasePathMacros` for SwiftUI Navigation. You can do this in settings, or just build the app and a dialog will be shown to enable `CasePathMacros`. ### Troubleshooting From 06b979d96e8285bd68659806860a40e5c277a403 Mon Sep 17 00:00:00 2001 From: stevensJourney Date: Thu, 31 Jul 2025 17:16:35 +0200 Subject: [PATCH 4/5] more cleanup --- .../{Secrets.template => Secrets.template.swift} | 0 Demo/README.md | 4 ++-- 2 files changed, 2 insertions(+), 2 deletions(-) rename Demo/PowerSyncExample/{Secrets.template => Secrets.template.swift} (100%) diff --git a/Demo/PowerSyncExample/Secrets.template b/Demo/PowerSyncExample/Secrets.template.swift similarity index 100% rename from Demo/PowerSyncExample/Secrets.template rename to Demo/PowerSyncExample/Secrets.template.swift diff --git a/Demo/README.md b/Demo/README.md index a92efed..6616639 100644 --- a/Demo/README.md +++ b/Demo/README.md @@ -16,10 +16,10 @@ Follow this guide to: 1. Open this directory in XCode. -2. Copy the `Secrets.template` file to a new Swift file and insert the credentials of your Supabase and PowerSync projects (more info can be found [here](https://docs.powersync.com/integration-guides/supabase-+-powersync#test-everything-using-our-demo-app)). +2. Copy the `Secrets.template.swift` file to a new `Secrets.swift` file and insert the credentials of your Supabase and PowerSync projects (more info can be found [here](https://docs.powersync.com/integration-guides/supabase-+-powersync#test-everything-using-our-demo-app)). ```bash -cp Secrets.template Secrets.swift +cp Secrets.template.swift Secrets.swift ``` 3. You will need to enable `CasePathMacros` for SwiftUI Navigation. You can do this in settings, or just build the app and a dialog will be shown to enable `CasePathMacros`. From 6d2cccfe1f76615f3298469fc30b5bd755d261db Mon Sep 17 00:00:00 2001 From: stevensJourney Date: Thu, 31 Jul 2025 17:17:38 +0200 Subject: [PATCH 5/5] restore comment --- Demo/PowerSyncExample/Secrets.template.swift | 1 + 1 file changed, 1 insertion(+) diff --git a/Demo/PowerSyncExample/Secrets.template.swift b/Demo/PowerSyncExample/Secrets.template.swift index 49dd8ae..d7b3677 100644 --- a/Demo/PowerSyncExample/Secrets.template.swift +++ b/Demo/PowerSyncExample/Secrets.template.swift @@ -13,6 +13,7 @@ extension Secrets { return "TODO" } + // Optional storage bucket name. Set to nil if you don't want to use storage. static var supabaseStorageBucket: String? { return nil }