Skip to content

Commit ef78731

Browse files
author
DominicGBauer
committed
chore: add tests
1 parent f0d2f83 commit ef78731

23 files changed

+960
-159
lines changed

.github/workflows/build_and_test.yaml

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
name: Build and test
2+
3+
on:
4+
push
5+
6+
jobs:
7+
build:
8+
name: Swift ${{ matrix.swift }} on ${{ matrix.os }}
9+
strategy:
10+
matrix:
11+
os: [ubuntu-latest, macos-latest]
12+
swift: ["5.7", "6.0"]
13+
runs-on: ${{ matrix.os }}
14+
steps:
15+
- uses: swift-actions/setup-swift@v2
16+
with:
17+
swift-version: ${{ matrix.swift }}
18+
- uses: actions/checkout@v4
19+
- name: Build
20+
run: swift build
21+
- name: Run tests
22+
run: swift test

Demo/PowerSyncExample/Components/AddListView.swift

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,9 +13,9 @@ struct AddListView: View {
1313
Task.detached {
1414
do {
1515
try await powerSync.insertList(newList)
16-
completion(.success(true))
16+
await completion(.success(true))
1717
} catch {
18-
completion(.failure(error))
18+
await completion(.failure(error))
1919
throw error
2020
}
2121
}

Demo/PowerSyncExample/Components/AddTodoListView.swift

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,9 +15,9 @@ struct AddTodoListView: View {
1515
Task.detached {
1616
do {
1717
try await powerSync.insertTodo(newTodo, listId)
18-
completion(.success(true))
18+
await completion(.success(true))
1919
} catch {
20-
completion(.failure(error))
20+
await completion(.failure(error))
2121
throw error
2222
}
2323
}

Demo/PowerSyncExample/PowerSync/PowerSyncManager.swift

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -8,14 +8,14 @@ class PowerSyncManager {
88
let schema = AppSchema
99
var db: PowerSyncDatabaseProtocol!
1010

11+
// openDb must be called before connect
1112
func openDb() {
1213
db = PowerSyncDatabase(schema: schema, dbFilename: "powersync-swift.sqlite")
1314
}
14-
15-
// openDb must be called before connect
15+
1616
func connect() async {
1717
do {
18-
try await db.connect(connector: connector, crudThrottleMs: 1000, retryDelayMs:5000, params: [:])
18+
try await db.connect(connector: connector)
1919
} catch {
2020
print("Unexpected error: \(error.localizedDescription)") // Catches any other error
2121
}
@@ -30,12 +30,12 @@ class PowerSyncManager {
3030
}
3131

3232
func signOut() async throws -> Void {
33-
try await db.disconnectAndClear(clearLocal: true)
33+
try await db.disconnectAndClear()
3434
try await connector.client.auth.signOut()
3535
}
3636

3737
func watchLists(_ callback: @escaping (_ lists: [ListContent]) -> Void ) async {
38-
for await lists in self.db.watch(
38+
for await lists in self.db.watch<[ListContent]>(
3939
sql: "SELECT * FROM \(LISTS_TABLE)",
4040
parameters: [],
4141
mapper: { cursor in
Lines changed: 16 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import Foundation
2-
import PowerSync
2+
import PowerSyncSwift
33

44
let LISTS_TABLE = "lists"
55
let TODOS_TABLE = "todos"
@@ -8,40 +8,32 @@ let lists = Table(
88
name: LISTS_TABLE,
99
columns: [
1010
// ID column is automatically included
11-
Column(name: "name", type: ColumnType.text),
12-
Column(name: "created_at", type: ColumnType.text),
13-
Column(name: "owner_id", type: ColumnType.text)
14-
],
15-
indexes: [],
16-
localOnly: false,
17-
insertOnly: false,
18-
viewNameOverride: LISTS_TABLE
11+
.text("name"),
12+
.text("created_at"),
13+
.text("owner_id")
14+
]
1915
)
2016

2117
let todos = Table(
2218
name: TODOS_TABLE,
2319
// ID column is automatically included
2420
columns: [
25-
Column(name: "list_id", type: ColumnType.text),
26-
Column(name: "photo_id", type: ColumnType.text),
27-
Column(name: "description", type: ColumnType.text),
21+
Column.text("list_id"),
22+
Column.text("photo_id"),
23+
Column.text("description"),
2824
// 0 or 1 to represent false or true
29-
Column(name: "completed", type: ColumnType.integer),
30-
Column(name: "created_at", type: ColumnType.text),
31-
Column(name: "completed_at", type: ColumnType.text),
32-
Column(name: "created_by", type: ColumnType.text),
33-
Column(name: "completed_by", type: ColumnType.text)
34-
25+
Column.integer("completed"),
26+
Column.text("created_at"),
27+
Column.text("completed_at"),
28+
Column.text("created_by"),
29+
Column.text("completed_by")
3530
],
3631
indexes: [
3732
Index(
3833
name: "list_id",
39-
columns: [IndexedColumn(column: "list_id", ascending: true, columnDefinition: nil, type: nil)]
34+
columns: [IndexedColumn.ascending("list_id")]
4035
)
41-
],
42-
localOnly: false,
43-
insertOnly: false,
44-
viewNameOverride: TODOS_TABLE
36+
]
4537
)
4638

47-
let AppSchema = Schema(tables: [lists, todos])
39+
let AppSchema = Schema(lists, todos)

Demo/PowerSyncExample/PowerSync/SupabaseConnector.swift

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ class SupabaseConnector: PowerSyncBackendConnector {
2121
guard let self = self else { return }
2222

2323
for await (event, session) in self.client.auth.authStateChanges {
24-
guard [.initialSession, .signedIn, .signedOut].contains(event) else { throw AuthError.sessionNotFound }
24+
guard [.initialSession, .signedIn, .signedOut].contains(event) else { throw AuthError.sessionMissing }
2525

2626
self.session = session
2727
}
@@ -40,7 +40,7 @@ class SupabaseConnector: PowerSyncBackendConnector {
4040
session = try await client.auth.session
4141

4242
if (self.session == nil) {
43-
throw AuthError.sessionNotFound
43+
throw AuthError.sessionMissing
4444
}
4545

4646
let token = session!.accessToken
@@ -49,7 +49,7 @@ class SupabaseConnector: PowerSyncBackendConnector {
4949
return PowerSyncCredentials(endpoint: self.powerSyncEndpoint, token: token, userId: currentUserID)
5050
}
5151

52-
override func uploadData(database: any PowerSyncDatabase) async throws {
52+
override func uploadData(database: PowerSyncDatabase) async throws {
5353

5454
guard let transaction = try await database.getNextCrudTransaction() else { return }
5555

Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
import PowerSync
2+
3+
internal struct KotlinAdapter {
4+
struct Index {
5+
static func toKotlin(_ index: IndexProtocol) -> PowerSync.Index {
6+
PowerSync.Index(
7+
name: index.name,
8+
columns: index.columns.map { IndexedColumn.toKotlin($0) }
9+
)
10+
}
11+
}
12+
13+
struct IndexedColumn {
14+
static func toKotlin(_ column: IndexedColumnProtocol) -> PowerSync.IndexedColumn {
15+
return PowerSync.IndexedColumn(
16+
column: column.column,
17+
ascending: column.ascending,
18+
columnDefinition: nil,
19+
type: nil
20+
)
21+
}
22+
}
23+
24+
struct Table {
25+
static func toKotlin(_ table: TableProtocol) -> PowerSync.Table {
26+
PowerSync.Table(
27+
name: table.name,
28+
columns: table.columns.map {Column.toKotlin($0)},
29+
indexes: table.indexes.map { Index.toKotlin($0) },
30+
localOnly: table.localOnly,
31+
insertOnly: table.insertOnly,
32+
viewNameOverride: table.viewNameOverride
33+
)
34+
}
35+
}
36+
37+
struct Column {
38+
static func toKotlin(_ column: any ColumnProtocol) -> PowerSync.Column {
39+
PowerSync.Column(
40+
name: column.name,
41+
type: columnType(from: column.type)
42+
)
43+
}
44+
45+
private static func columnType(from swiftType: ColumnData) -> PowerSync.ColumnType {
46+
switch swiftType {
47+
case .text:
48+
return PowerSync.ColumnType.text
49+
case .integer:
50+
return PowerSync.ColumnType.integer
51+
case .real:
52+
return PowerSync.ColumnType.real
53+
}
54+
}
55+
}
56+
57+
struct Schema {
58+
static func toKotlin(_ schema: SchemaProtocol) -> PowerSync.Schema {
59+
PowerSync.Schema(
60+
tables: schema.tables.map { Table.toKotlin($0) }
61+
)
62+
}
63+
}
64+
}

Sources/PowerSyncSwift/PowerSyncDatabaseImpl.swift renamed to Sources/PowerSyncSwift/Kotlin/KotlinPowerSyncDatabaseImpl.swift

Lines changed: 3 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,7 @@
11
import Foundation
22
import PowerSync
33

4-
/// Implementation of PowerSyncDatabaseProtocol that initially wraps the KMP implementation
5-
/// and allows for gradual migration to pure Swift code
6-
final class PowerSyncDatabaseImpl: PowerSyncDatabaseProtocol {
4+
final class KotlinPowerSyncDatabaseImpl: PowerSyncDatabaseProtocol {
75
private let kmpDatabase: PowerSync.PowerSyncDatabase
86

97
var currentStatus: SyncStatus {
@@ -17,12 +15,11 @@ final class PowerSyncDatabaseImpl: PowerSyncDatabaseProtocol {
1715
let factory = PowerSync.DatabaseDriverFactory()
1816
self.kmpDatabase = PowerSyncDatabase(
1917
factory: factory,
20-
schema: schema,
18+
schema: KotlinAdapter.Schema.toKotlin(schema),
2119
dbFilename: dbFilename
2220
)
2321
}
2422

25-
2623
func waitForFirstSync() async throws {
2724
try await kmpDatabase.waitForFirstSync()
2825
}
@@ -33,7 +30,6 @@ final class PowerSyncDatabaseImpl: PowerSyncDatabaseProtocol {
3330
retryDelayMs: Int64 = 5000,
3431
params: [String: JsonParam?] = [:]
3532
) async throws {
36-
// Convert Swift types to KMP types
3733
try await kmpDatabase.connect(
3834
connector: connector,
3935
crudThrottleMs: crudThrottleMs,
@@ -63,7 +59,7 @@ final class PowerSyncDatabaseImpl: PowerSyncDatabaseProtocol {
6359
}
6460

6561
func execute(sql: String, parameters: [Any]?) async throws -> Int64 {
66-
Int64(try await kmpDatabase.execute(sql: sql, parameters: parameters))
62+
Int64(truncating: try await kmpDatabase.execute(sql: sql, parameters: parameters))
6763
}
6864

6965
func get<RowType>(

Sources/PowerSyncSwift/KotlinTypes.swift renamed to Sources/PowerSyncSwift/Kotlin/KotlinTypes.swift

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,5 @@
11
import PowerSync
22

3-
public typealias Schema = PowerSync.Schema
4-
typealias KmpPowerSyncDatabase = PowerSync.PowerSyncDatabase
53
public typealias PowerSyncBackendConnector = PowerSync.PowerSyncBackendConnector
64
public typealias CrudEntry = PowerSync.CrudEntry
75
public typealias CrudBatch = PowerSync.CrudBatch

Sources/PowerSyncSwift/PowerSyncDatabase.swift

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,13 +8,13 @@ public let DEFAULT_DB_FILENAME = "powersync.db"
88
/// - schema: The database schema
99
/// - dbFilename: The database filename. Defaults to "powersync.db"
1010
/// - Returns: A configured PowerSyncDatabase instance
11+
@MainActor
1112
public func PowerSyncDatabase(
1213
schema: Schema,
1314
dbFilename: String = DEFAULT_DB_FILENAME
1415
) -> PowerSyncDatabaseProtocol {
1516

16-
17-
return PowerSyncDatabaseImpl(
17+
return KotlinPowerSyncDatabaseImpl(
1818
schema: schema,
1919
dbFilename: dbFilename
2020
)

Sources/PowerSyncSwift/PowerSyncDatabaseProtocol.swift

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -91,3 +91,27 @@ public protocol PowerSyncDatabaseProtocol: Queries {
9191
/// - Parameter clearLocal: Set to false to preserve data in local-only tables.
9292
func disconnectAndClear(clearLocal: Bool) async throws
9393
}
94+
95+
public extension PowerSyncDatabaseProtocol {
96+
func connect(
97+
connector: PowerSyncBackendConnector,
98+
crudThrottleMs: Int64 = 1000,
99+
retryDelayMs: Int64 = 5000,
100+
params: [String: JsonParam?] = [:]
101+
) async throws {
102+
try await connect(
103+
connector: connector,
104+
crudThrottleMs: crudThrottleMs,
105+
retryDelayMs: retryDelayMs,
106+
params: params
107+
)
108+
}
109+
110+
func disconnectAndClear(clearLocal: Bool = true) async throws {
111+
try await disconnectAndClear(clearLocal: clearLocal)
112+
}
113+
114+
func getCrudBatch(limit: Int32 = 100) async throws -> CrudBatch? {
115+
try await getCrudBatch(limit: 100)
116+
}
117+
}

0 commit comments

Comments
 (0)