|
4 | 4 | import CustomDump |
5 | 5 | import OrderedCollections |
6 | 6 | import OSLog |
| 7 | + import StructuredQueriesCore |
| 8 | + import SwiftData |
7 | 9 |
|
8 | 10 | @available(iOS 17, macOS 14, tvOS 17, watchOS 10, *) |
9 | 11 | public final class SyncEngine: Sendable { |
|
24 | 26 |
|
25 | 27 | let dataManager = Dependency(\.dataManager) |
26 | 28 |
|
27 | | - public convenience init( |
28 | | - container: CKContainer, |
| 29 | + public convenience init<each T1: PrimaryKeyedTable, each T2: PrimaryKeyedTable>( |
| 30 | + for database: any DatabaseWriter, |
| 31 | + tables: repeat (each T1).Type, |
| 32 | + privateTables: repeat (each T2).Type, |
| 33 | + containerIdentifier: String? = nil, |
29 | 34 | defaultZone: CKRecordZone = CKRecordZone(zoneName: "co.pointfree.SQLiteData.defaultZone"), |
30 | | - database: any DatabaseWriter, |
31 | | - logger: Logger = Logger(subsystem: "SQLiteData", category: "CloudKit"), |
32 | | - tables: [any PrimaryKeyedTable.Type], |
33 | | - privateTables: [any PrimaryKeyedTable.Type] = [] |
34 | | - ) throws { |
| 35 | + logger: Logger = Logger(subsystem: "SQLiteData", category: "CloudKit") |
| 36 | + ) throws |
| 37 | + where |
| 38 | + repeat (each T1).PrimaryKey.QueryOutput: IdentifierStringConvertible, |
| 39 | + repeat (each T2).PrimaryKey.QueryOutput: IdentifierStringConvertible |
| 40 | + { |
| 41 | + let containerIdentifier = containerIdentifier |
| 42 | + ?? ModelConfiguration(groupContainer: .automatic).cloudKitContainerIdentifier |
| 43 | + |
| 44 | + guard let containerIdentifier else { |
| 45 | + throw SchemaError( |
| 46 | + reason: .noCloudKitContainer, |
| 47 | + debugDescription: """ |
| 48 | + No default CloudKit container found. Please add a container identifier to your app's \ |
| 49 | + entitlements. |
| 50 | + """ |
| 51 | + ) |
| 52 | + } |
| 53 | + |
| 54 | + let container = CKContainer(identifier: containerIdentifier) |
| 55 | + var allTables: [any PrimaryKeyedTable.Type] = [] |
| 56 | + var allPrivateTables: [any PrimaryKeyedTable.Type] = [] |
| 57 | + for table in repeat each tables { |
| 58 | + allTables.append(table) |
| 59 | + } |
| 60 | + for privateTable in repeat each privateTables { |
| 61 | + allPrivateTables.append(privateTable) |
| 62 | + } |
| 63 | + |
35 | 64 | let userDatabase = UserDatabase(database: database) |
36 | 65 | try self.init( |
37 | 66 | container: container, |
|
66 | 95 | }, |
67 | 96 | userDatabase: userDatabase, |
68 | 97 | logger: logger, |
69 | | - tables: tables, |
70 | | - privateTables: privateTables |
| 98 | + tables: allTables, |
| 99 | + privateTables: allPrivateTables |
71 | 100 | ) |
72 | 101 | _ = try setUpSyncEngine( |
73 | 102 | userDatabase: userDatabase, |
|
1493 | 1522 | /// |
1494 | 1523 | /// - Parameter containerIdentifier: The identifier of the CloudKit container used to synchronize |
1495 | 1524 | /// data. |
1496 | | - public func attachMetadatabase(containerIdentifier: String) throws { |
| 1525 | + public func attachMetadatabase(containerIdentifier: String? = nil) throws { |
| 1526 | + // TODO |
1497 | 1527 | let databasePath = try SQLQueryExpression( |
1498 | 1528 | """ |
1499 | 1529 | SELECT "file" FROM pragma_database_list() |
|
1539 | 1569 | case invalidForeignKeyAction(ForeignKey) |
1540 | 1570 | case invalidTableName(String) |
1541 | 1571 | case metadatabaseMismatch(attachedPath: String, syncEngineConfiguredPath: String) |
| 1572 | + case noCloudKitContainer |
1542 | 1573 | case nonNullColumnsWithoutDefault(tableName: String, columnNames: [String]) |
1543 | 1574 | case triggersWithoutSynchronizationCheck([String]) |
1544 | 1575 | case unknown |
|
0 commit comments