Skip to content

Commit b4d9cbf

Browse files
Demo and Docs cleanup
1 parent 6afa299 commit b4d9cbf

File tree

10 files changed

+105
-68
lines changed

10 files changed

+105
-68
lines changed

Demo/GRDB Demo/GRDB Demo.xcodeproj/project.pbxproj

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,16 @@
4141
name = "Embed Frameworks";
4242
runOnlyForDeploymentPostprocessing = 0;
4343
};
44+
BEED7BE72E9007A5007C187A /* Embed Watch Content */ = {
45+
isa = PBXCopyFilesBuildPhase;
46+
buildActionMask = 2147483647;
47+
dstPath = "$(CONTENTS_FOLDER_PATH)/Watch";
48+
dstSubfolderSpec = 16;
49+
files = (
50+
);
51+
name = "Embed Watch Content";
52+
runOnlyForDeploymentPostprocessing = 0;
53+
};
4454
/* End PBXCopyFilesBuildPhase section */
4555

4656
/* Begin PBXFileReference section */
@@ -135,6 +145,7 @@
135145
BE1EABA22E7B075D00D0A0A7 /* Frameworks */,
136146
BE1EABA32E7B075D00D0A0A7 /* Resources */,
137147
BE1EABEE2E7C26DD00D0A0A7 /* Embed Frameworks */,
148+
BEED7BE72E9007A5007C187A /* Embed Watch Content */,
138149
);
139150
buildRules = (
140151
);

Demo/GRDB Demo/GRDB Demo/GRDB_DemoApp.swift

Lines changed: 17 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,6 @@ import PowerSync
44
import PowerSyncGRDB
55
import SwiftUI
66

7-
@Observable
87
class Databases {
98
let grdb: DatabasePool
109
let powerSync: PowerSyncDatabaseProtocol
@@ -37,23 +36,25 @@ func openDatabase()
3736
schema: schema
3837
)
3938

40-
guard let grdb = try? DatabasePool(
41-
path: dbUrl.path,
42-
configuration: config
43-
) else {
44-
fatalError("Could not open database")
45-
}
39+
do {
40+
let grdb = try DatabasePool(
41+
path: dbUrl.path,
42+
configuration: config
43+
)
4644

47-
let powerSync = openPowerSyncWithGRDB(
48-
pool: grdb,
49-
schema: schema,
50-
identifier: "test"
51-
)
45+
let powerSync = openPowerSyncWithGRDB(
46+
pool: grdb,
47+
schema: schema,
48+
identifier: "test.sqlite"
49+
)
5250

53-
return Databases(
54-
grdb: grdb,
55-
powerSync: powerSync
56-
)
51+
return Databases(
52+
grdb: grdb,
53+
powerSync: powerSync
54+
)
55+
} catch {
56+
fatalError("Could not open database: \(error)")
57+
}
5758
}
5859

5960
@main

Sources/PowerSync/Kotlin/KotlinPowerSyncDatabaseImpl.swift

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -67,7 +67,7 @@ final class KotlinPowerSyncDatabaseImpl: PowerSyncDatabaseProtocol,
6767
batch: base
6868
)
6969
}
70-
70+
7171
func getCrudTransactions() -> any CrudTransactions {
7272
return KotlinCrudTransactions(db: kotlinDatabase)
7373
}
@@ -388,7 +388,7 @@ final class KotlinPowerSyncDatabaseImpl: PowerSyncDatabaseProtocol,
388388
}
389389
}
390390

391-
func openKotlinDBWithFactory(
391+
func openKotlinDBDefault(
392392
schema: Schema,
393393
dbFilename: String,
394394
logger: DatabaseLogger

Sources/PowerSync/PowerSyncDatabase.swift

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,13 +14,28 @@ public func PowerSyncDatabase(
1414
dbFilename: String = DEFAULT_DB_FILENAME,
1515
logger: (any LoggerProtocol) = DefaultLogger()
1616
) -> PowerSyncDatabaseProtocol {
17-
return openKotlinDBWithFactory(
17+
return openKotlinDBDefault(
1818
schema: schema,
1919
dbFilename: dbFilename,
2020
logger: DatabaseLogger(logger)
2121
)
2222
}
2323

24+
/// Opens a PowerSync database using an existing SQLite connection pool.
25+
///
26+
/// - Parameters:
27+
/// - schema: The database schema describing the tables, indexes and other
28+
/// structure required by PowerSync.
29+
/// - pool: An active `SQLiteConnectionPoolProtocol` that provides connections
30+
/// to the underlying SQLite database. The pool must remain valid for the
31+
/// lifetime of the returned database instance.
32+
/// - identifier: A unique identifier for this database instance. This is
33+
/// typically used to isolate multiple database
34+
/// instances in the same process.
35+
/// - logger: Optional logging implementation. Defaults to `DefaultLogger()`.
36+
///
37+
/// - Returns: A `PowerSyncDatabaseProtocol` that wraps the opened database and
38+
/// exposes PowerSync functionality backed by the provided connection pool.
2439
public func OpenedPowerSyncDatabase(
2540
schema: Schema,
2641
pool: any SQLiteConnectionPoolProtocol,

Sources/PowerSync/Utils/withSession.swift

Lines changed: 31 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -5,40 +5,50 @@ public struct WithSessionResult<ResultType: Sendable>: Sendable {
55
public let affectedTables: Set<String>
66
}
77

8-
/// Executes an action within a SQLite database connection session and handles its result.
8+
/// Executes an action within a SQLite database connection session and
9+
/// returns a `WithSessionResult` containing the action result and the set of
10+
/// tables that were affected during the session.
911
///
10-
/// The Raw SQLite connection is only available in some niche scenarios.
12+
/// The raw SQLite connection is only available in some niche scenarios. This helper is
13+
/// intended for internal use.
1114
///
12-
/// - Executes the provided action in a SQLite session
13-
/// - Handles success/failure results
14-
/// - Tracks table updates during execution
15-
/// - Provides type-safe result handling
15+
/// - The provided `action` is executed inside a database session.
16+
/// - Any success or failure from the `action` is captured in
17+
/// `WithSessionResult.blockResult`.
18+
/// - The set of updated table names is returned in
19+
/// `WithSessionResult.affectedTables`.
1620
///
1721
/// Example usage:
1822
/// ```swift
19-
/// try withSession(db: database) {
20-
/// return try someOperation()
21-
/// } onComplete: { result, updates in
22-
/// switch result {
23-
/// case .success(let value):
24-
/// print("Operation succeeded with: \(value)")
25-
/// case .failure(let error):
26-
/// print("Operation failed: \(error)")
27-
/// }
23+
/// let result = try withSession(db: database) {
24+
/// // perform database work and return a value
25+
/// try someOperation()
2826
/// }
27+
///
28+
/// switch result.blockResult {
29+
/// case .success(let value):
30+
/// print("Operation succeeded with: \(value)")
31+
/// case .failure(let error):
32+
/// print("Operation failed: \(error)")
33+
/// }
34+
///
35+
/// print("Updated tables: \(result.affectedTables)")
2936
/// ```
3037
///
3138
/// - Parameters:
32-
/// - db: The database connection pointer
33-
/// - action: The operation to execute within the session
34-
/// - onComplete: Callback that receives the operation result and set of updated tables
35-
/// - Throws: Errors from session initialization or execution
39+
/// - db: The raw SQLite connection pointer used to open the session.
40+
/// - action: The operation to execute within the session. Its return value is
41+
/// propagated into `WithSessionResult.blockResult` on success.
42+
/// - Returns: A `WithSessionResult` containing the action's result and the set
43+
/// of affected table names.
44+
/// - Throws: Any error thrown while establishing the session or executing the
45+
/// provided `action`.
3646
public func withSession<ReturnType>(
3747
db: OpaquePointer,
38-
action: @escaping () throws -> ReturnType,
48+
action: @escaping () throws -> ReturnType
3949
) throws -> WithSessionResult<ReturnType> {
4050
return try kotlinWithSession(
4151
db: db,
42-
action: action,
52+
action: action
4353
)
4454
}

Sources/PowerSyncGRDB/Connections/GRDBConnectionPool.swift

Lines changed: 11 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -37,16 +37,6 @@ actor GRDBConnectionPool: SQLiteConnectionPoolProtocol {
3737
tableUpdatesContinuation = tempContinuation
3838
}
3939

40-
func processPowerSyncUpdates(_ updates: Set<String>) async throws {
41-
try await pool.write { database in
42-
for table in updates {
43-
try database.notifyChanges(in: Table(table))
44-
}
45-
}
46-
// Pass the updates to the output stream
47-
tableUpdatesContinuation?.yield(updates)
48-
}
49-
5040
func read(
5141
onConnection: @Sendable @escaping (SQLiteConnectionLease) throws -> Void
5242
) async throws {
@@ -66,15 +56,25 @@ actor GRDBConnectionPool: SQLiteConnectionPoolProtocol {
6656
throw PowerSyncGRDBError.connectionUnavailable
6757
}
6858

69-
return try withSession(
59+
let sessionResult = try withSession(
7060
db: pointer,
7161
) {
7262
try onConnection(
7363
GRDBConnectionLease(database: database)
7464
)
7565
}
66+
67+
return sessionResult
7668
}
69+
// Notify PowerSync of these changes
7770
tableUpdatesContinuation?.yield(result.affectedTables)
71+
// Notify GRDB, this needs to be a write (transaction)
72+
try await pool.write { database in
73+
// Notify GRDB about these changes
74+
for table in result.affectedTables {
75+
try database.notifyChanges(in: Table(table))
76+
}
77+
}
7878
}
7979

8080
func withAllConnections(

Tests/PowerSyncTests/ConnectTests.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ final class ConnectTests: XCTestCase {
1818
),
1919
])
2020

21-
database = openKotlinDBWithFactory(
21+
database = openKotlinDBDefault(
2222
schema: schema,
2323
dbFilename: ":memory:",
2424
logger: DatabaseLogger(DefaultLogger())

Tests/PowerSyncTests/CrudTests.swift

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ final class CrudTests: XCTestCase {
1919
),
2020
])
2121

22-
database = openKotlinDBWithFactory(
22+
database = openKotlinDBDefault(
2323
schema: schema,
2424
dbFilename: ":memory:",
2525
logger: DatabaseLogger(DefaultLogger())
@@ -199,7 +199,7 @@ final class CrudTests: XCTestCase {
199199
let finalValidationBatch = try await database.getCrudBatch(limit: 100)
200200
XCTAssertNil(finalValidationBatch)
201201
}
202-
202+
203203
func testCrudTransactions() async throws {
204204
func insertInTransaction(size: Int) async throws {
205205
try await database.writeTransaction { tx in
@@ -211,30 +211,30 @@ final class CrudTests: XCTestCase {
211211
}
212212
}
213213
}
214-
214+
215215
// Before inserting any data, the iterator should be empty.
216216
for try await _ in database.getCrudTransactions() {
217217
XCTFail("Unexpected transaction")
218218
}
219-
219+
220220
try await insertInTransaction(size: 5)
221221
try await insertInTransaction(size: 10)
222222
try await insertInTransaction(size: 15)
223-
223+
224224
var batch = [CrudEntry]()
225225
var lastTx: CrudTransaction? = nil
226226
for try await tx in database.getCrudTransactions() {
227227
batch.append(contentsOf: tx.crud)
228228
lastTx = tx
229-
230-
if (batch.count >= 10) {
229+
230+
if batch.count >= 10 {
231231
break
232232
}
233233
}
234-
234+
235235
XCTAssertEqual(batch.count, 15)
236236
try await lastTx!.complete()
237-
237+
238238
let finalTx = try await database.getNextCrudTransaction()
239239
XCTAssertEqual(finalTx!.crud.count, 15)
240240
}

Tests/PowerSyncTests/Kotlin/KotlinPowerSyncDatabaseImplTests.swift

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -71,7 +71,7 @@ final class KotlinPowerSyncDatabaseImplTests: XCTestCase {
7171

7272
func testGetError() async throws {
7373
do {
74-
let _ = try await database.get(
74+
_ = try await database.get(
7575
sql: "SELECT id, name, email FROM usersfail WHERE id = ?",
7676
parameters: ["1"]
7777
) { cursor in
@@ -116,7 +116,7 @@ final class KotlinPowerSyncDatabaseImplTests: XCTestCase {
116116

117117
func testGetOptionalError() async throws {
118118
do {
119-
let _ = try await database.getOptional(
119+
_ = try await database.getOptional(
120120
sql: "SELECT id, name, email FROM usersfail WHERE id = ?",
121121
parameters: ["1"]
122122
) { cursor in
@@ -140,7 +140,7 @@ final class KotlinPowerSyncDatabaseImplTests: XCTestCase {
140140
parameters: ["1", "Test User", "[email protected]"]
141141
)
142142
do {
143-
let _ = try await database.getOptional(
143+
_ = try await database.getOptional(
144144
sql: "SELECT id, name, email FROM users WHERE id = ?",
145145
parameters: ["1"]
146146
) { _ throws in
@@ -181,7 +181,7 @@ final class KotlinPowerSyncDatabaseImplTests: XCTestCase {
181181

182182
func testGetAllError() async throws {
183183
do {
184-
let _ = try await database.getAll(
184+
_ = try await database.getAll(
185185
sql: "SELECT id, name, email FROM usersfail WHERE id = ?",
186186
parameters: ["1"]
187187
) { cursor in
@@ -505,7 +505,7 @@ final class KotlinPowerSyncDatabaseImplTests: XCTestCase {
505505
let testWriter = TestLogWriterAdapter()
506506
let logger = DefaultLogger(minSeverity: LogSeverity.debug, writers: [testWriter])
507507

508-
let db2 = openKotlinDBWithFactory(
508+
let db2 = openKotlinDBDefault(
509509
schema: schema,
510510
dbFilename: ":memory:",
511511
logger: DatabaseLogger(logger)
@@ -526,7 +526,7 @@ final class KotlinPowerSyncDatabaseImplTests: XCTestCase {
526526
let testWriter = TestLogWriterAdapter()
527527
let logger = DefaultLogger(minSeverity: LogSeverity.error, writers: [testWriter])
528528

529-
let db2 = openKotlinDBWithFactory(
529+
let db2 = openKotlinDBDefault(
530530
schema: schema,
531531
dbFilename: ":memory:",
532532
logger: DatabaseLogger(logger)

Tests/PowerSyncTests/Kotlin/SqlCursorTests.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -65,7 +65,7 @@ final class SqlCursorTests: XCTestCase {
6565
])
6666
])
6767

68-
database = openKotlinDBWithFactory(
68+
database = openKotlinDBDefault(
6969
schema: schema,
7070
dbFilename: ":memory:",
7171
logger: DatabaseLogger(DefaultLogger())

0 commit comments

Comments
 (0)