From 6308a4897d5aab1ccc4c79d9c56b4bf596680cb7 Mon Sep 17 00:00:00 2001 From: Stijn Willems Date: Sat, 13 Dec 2025 20:43:50 +0100 Subject: [PATCH 1/9] "Claude PR Assistant workflow" (#6) "Claude PR Assistant workflow" "Claude Code Review workflow" --- .github/workflows/claude-code-review.yml | 57 ++++++++++++++++++++++++ .github/workflows/claude.yml | 50 +++++++++++++++++++++ 2 files changed, 107 insertions(+) create mode 100644 .github/workflows/claude-code-review.yml create mode 100644 .github/workflows/claude.yml diff --git a/.github/workflows/claude-code-review.yml b/.github/workflows/claude-code-review.yml new file mode 100644 index 00000000..8452b0f2 --- /dev/null +++ b/.github/workflows/claude-code-review.yml @@ -0,0 +1,57 @@ +name: Claude Code Review + +on: + pull_request: + types: [opened, synchronize] + # Optional: Only run on specific file changes + # paths: + # - "src/**/*.ts" + # - "src/**/*.tsx" + # - "src/**/*.js" + # - "src/**/*.jsx" + +jobs: + claude-review: + # Optional: Filter by PR author + # if: | + # github.event.pull_request.user.login == 'external-contributor' || + # github.event.pull_request.user.login == 'new-developer' || + # github.event.pull_request.author_association == 'FIRST_TIME_CONTRIBUTOR' + + runs-on: ubuntu-latest + permissions: + contents: read + pull-requests: read + issues: read + id-token: write + + steps: + - name: Checkout repository + uses: actions/checkout@v4 + with: + fetch-depth: 1 + + - name: Run Claude Code Review + id: claude-review + uses: anthropics/claude-code-action@v1 + with: + claude_code_oauth_token: ${{ secrets.CLAUDE_CODE_OAUTH_TOKEN }} + prompt: | + REPO: ${{ github.repository }} + PR NUMBER: ${{ github.event.pull_request.number }} + + Please review this pull request and provide feedback on: + - Code quality and best practices + - Potential bugs or issues + - Performance considerations + - Security concerns + - Test coverage + + Use the repository's CLAUDE.md for guidance on style and conventions. Be constructive and helpful in your feedback. + + Use `gh pr comment` with your Bash tool to leave your review as a comment on the PR. + + # See https://github.com/anthropics/claude-code-action/blob/main/docs/usage.md + # or https://code.claude.com/docs/en/cli-reference for available options + claude_args: '--allowed-tools "Bash(gh issue view:*),Bash(gh search:*),Bash(gh issue list:*),Bash(gh pr comment:*),Bash(gh pr diff:*),Bash(gh pr view:*),Bash(gh pr list:*)"' + diff --git a/.github/workflows/claude.yml b/.github/workflows/claude.yml new file mode 100644 index 00000000..d300267f --- /dev/null +++ b/.github/workflows/claude.yml @@ -0,0 +1,50 @@ +name: Claude Code + +on: + issue_comment: + types: [created] + pull_request_review_comment: + types: [created] + issues: + types: [opened, assigned] + pull_request_review: + types: [submitted] + +jobs: + claude: + if: | + (github.event_name == 'issue_comment' && contains(github.event.comment.body, '@claude')) || + (github.event_name == 'pull_request_review_comment' && contains(github.event.comment.body, '@claude')) || + (github.event_name == 'pull_request_review' && contains(github.event.review.body, '@claude')) || + (github.event_name == 'issues' && (contains(github.event.issue.body, '@claude') || contains(github.event.issue.title, '@claude'))) + runs-on: ubuntu-latest + permissions: + contents: read + pull-requests: read + issues: read + id-token: write + actions: read # Required for Claude to read CI results on PRs + steps: + - name: Checkout repository + uses: actions/checkout@v4 + with: + fetch-depth: 1 + + - name: Run Claude Code + id: claude + uses: anthropics/claude-code-action@v1 + with: + claude_code_oauth_token: ${{ secrets.CLAUDE_CODE_OAUTH_TOKEN }} + + # This is an optional setting that allows Claude to read CI results on PRs + additional_permissions: | + actions: read + + # Optional: Give a custom prompt to Claude. If this is not specified, Claude will perform the instructions specified in the comment that tagged it. + # prompt: 'Update the pull request description to include a summary of changes.' + + # Optional: Add claude_args to customize behavior and configuration + # See https://github.com/anthropics/claude-code-action/blob/main/docs/usage.md + # or https://code.claude.com/docs/en/cli-reference for available options + # claude_args: '--allowed-tools Bash(gh pr:*)' + From 341b624324db4c899b71d7e4b0f2669663343e92 Mon Sep 17 00:00:00 2001 From: Stijn Willems Date: Sat, 13 Dec 2025 21:03:13 +0100 Subject: [PATCH 2/9] refactor: Remove unused swift-perception dependency, target macOS 15+ only (#1) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Remove `import Perception` from FetchSubscription.swift (was unused) - Add explicit `import ConcurrencyExtras` for LockIsolated - Remove swift-perception package dependency from Package.swift - Update platforms to macOS 15+ only (drop iOS/tvOS/watchOS) - Update Package@swift-6.0.swift similarly The Perception import was never actually used - the file only uses LockIsolated (from ConcurrencyExtras) and SharedReader (from Sharing). 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude --- Package.swift | 5 +-- Package@swift-6.0.swift | 5 +-- Sources/SQLiteData/FetchSubscription.swift | 46 ++++++++++++++++++++++ 3 files changed, 48 insertions(+), 8 deletions(-) create mode 100644 Sources/SQLiteData/FetchSubscription.swift diff --git a/Package.swift b/Package.swift index 0d607e9d..e526eff8 100644 --- a/Package.swift +++ b/Package.swift @@ -5,10 +5,7 @@ import PackageDescription let package = Package( name: "sqlite-data", platforms: [ - .iOS(.v13), - .macOS(.v10_15), - .tvOS(.v13), - .watchOS(.v7), + .macOS(.v15), ], products: [ .library( diff --git a/Package@swift-6.0.swift b/Package@swift-6.0.swift index fc886e60..76704aab 100644 --- a/Package@swift-6.0.swift +++ b/Package@swift-6.0.swift @@ -5,10 +5,7 @@ import PackageDescription let package = Package( name: "sqlite-data", platforms: [ - .iOS(.v13), - .macOS(.v10_15), - .tvOS(.v13), - .watchOS(.v7), + .macOS(.v15), ], products: [ .library( diff --git a/Sources/SQLiteData/FetchSubscription.swift b/Sources/SQLiteData/FetchSubscription.swift new file mode 100644 index 00000000..9ce8f893 --- /dev/null +++ b/Sources/SQLiteData/FetchSubscription.swift @@ -0,0 +1,46 @@ +import ConcurrencyExtras +import Sharing + +/// A subscription associated with `@FetchAll`, `@FetchOne`, and `@Fetch` observation. +/// +/// This value can be useful in associating the lifetime of observing a query to the lifetime of a +/// SwiftUI view _via_ the `task` view modifier. For example, loading a query in a view's `task` +/// will automatically cancel the observation when drilling down into a child view, and restart +/// observation when popping back to the view: +/// +/// ```swift +/// .task { +/// try? await $reminders.load(Reminder.all).task +/// } +/// ``` +public struct FetchSubscription: Sendable { + let cancellable = LockIsolated?>(nil) + let onCancel: @Sendable () -> Void + + init(sharedReader: SharedReader) { + onCancel = { sharedReader.projectedValue = SharedReader(value: sharedReader.wrappedValue) } + } + + /// An async handle to the given fetch observation. + /// + /// This handle will suspend until the current task is cancelled, at which point it will terminate + /// the observation of the associated ``FetchAll``, ``FetchOne``, or ``Fetch``. + public var task: Void { + get async throws { + let task = Task { + try await withTaskCancellationHandler { + try await Task.never() + } onCancel: { + onCancel() + } + } + cancellable.withValue { $0 = task } + try await task.cancellableValue + } + } + + /// Cancels the database observation of the associated ``FetchAll``, ``FetchOne``, or ``Fetch``. + public func cancel() { + cancellable.value?.cancel() + } +} From 1bb1ac1571e2a95e34a2d071f260e7a887ab9043 Mon Sep 17 00:00:00 2001 From: Stijn Willems Date: Sat, 13 Dec 2025 21:06:36 +0100 Subject: [PATCH 3/9] wip local dependencies for structured queries (#3) --- .claude/settings.local.json | 9 + Package.resolved | 28 +-- Package.swift | 185 +++++++++--------- Package@swift-6.0.swift | 89 --------- .../CloudKit/CloudKit+StructuredQueries.swift | 2 +- .../CloudKit/PrimaryKeyMigration.swift | 57 ++++-- 6 files changed, 146 insertions(+), 224 deletions(-) create mode 100644 .claude/settings.local.json delete mode 100644 Package@swift-6.0.swift diff --git a/.claude/settings.local.json b/.claude/settings.local.json new file mode 100644 index 00000000..04f178c7 --- /dev/null +++ b/.claude/settings.local.json @@ -0,0 +1,9 @@ +{ + "permissions": { + "allow": [ + "Bash(swift --version:*)", + "Bash(~/.swiftly/bin/swiftly list:*)", + "Bash(~/.swiftly/bin/swiftly use:*)" + ] + } +} diff --git a/Package.resolved b/Package.resolved index 419fc30f..41a5cdb7 100644 --- a/Package.resolved +++ b/Package.resolved @@ -1,22 +1,13 @@ { - "originHash" : "41f93013537f670f4fe1a235c318bee33b54528c76e4b1dd2a7675bea6c0bcde", + "originHash" : "a18b1644857cf7bbf788548464ff5983bac7f7a8faa125c59045f5d830aa5f28", "pins" : [ { "identity" : "combine-schedulers", "kind" : "remoteSourceControl", "location" : "https://github.com/pointfreeco/combine-schedulers", "state" : { - "revision" : "5928286acce13def418ec36d05a001a9641086f2", - "version" : "1.0.3" - } - }, - { - "identity" : "grdb.swift", - "kind" : "remoteSourceControl", - "location" : "https://github.com/groue/GRDB.swift", - "state" : { - "revision" : "18497b68fdbb3a09528d260a0a0e1e7e61c8c53d", - "version" : "7.8.0" + "revision" : "fd16d76fd8b9a976d88bfb6cacc05ca8d19c91b6", + "version" : "1.1.0" } }, { @@ -118,15 +109,6 @@ "version" : "1.18.7" } }, - { - "identity" : "swift-structured-queries", - "kind" : "remoteSourceControl", - "location" : "https://github.com/pointfreeco/swift-structured-queries", - "state" : { - "revision" : "3a95b70a81b7027b8a5117e7dd08188837e5f54e", - "version" : "0.24.0" - } - }, { "identity" : "swift-syntax", "kind" : "remoteSourceControl", @@ -141,8 +123,8 @@ "kind" : "remoteSourceControl", "location" : "https://github.com/pointfreeco/xctest-dynamic-overlay", "state" : { - "revision" : "4c27acf5394b645b70d8ba19dc249c0472d5f618", - "version" : "1.7.0" + "revision" : "31073495cae9caf243c440eac94b3ab067e3d7bc", + "version" : "1.8.0" } } ], diff --git a/Package.swift b/Package.swift index e526eff8..fa9fcc85 100644 --- a/Package.swift +++ b/Package.swift @@ -1,107 +1,108 @@ -// swift-tools-version: 6.1 +// swift-tools-version: 6.2.1 import PackageDescription let package = Package( - name: "sqlite-data", - platforms: [ - .macOS(.v15), - ], - products: [ - .library( - name: "SQLiteData", - targets: ["SQLiteData"] - ), - .library( - name: "SQLiteDataTestSupport", - targets: ["SQLiteDataTestSupport"] - ), - ], - traits: [ - .trait( - name: "SQLiteDataTagged", - description: "Introduce SQLiteData conformances to the swift-tagged package." - ) - ], - dependencies: [ - .package(url: "https://github.com/apple/swift-collections", from: "1.0.0"), - .package(url: "https://github.com/groue/GRDB.swift", from: "7.6.0"), - .package(url: "https://github.com/pointfreeco/swift-concurrency-extras", from: "1.0.0"), - .package(url: "https://github.com/pointfreeco/swift-custom-dump", from: "1.3.3"), - .package(url: "https://github.com/pointfreeco/swift-dependencies", from: "1.9.0"), - .package(url: "https://github.com/pointfreeco/swift-sharing", from: "2.3.0"), - .package(url: "https://github.com/pointfreeco/swift-snapshot-testing", from: "1.18.4"), - .package( - url: "https://github.com/pointfreeco/swift-structured-queries", - from: "0.24.0", - traits: [ - .trait(name: "StructuredQueriesTagged", condition: .when(traits: ["SQLiteDataTagged"])) - ] - ), - .package(url: "https://github.com/pointfreeco/swift-tagged", from: "0.10.0"), - .package(url: "https://github.com/pointfreeco/xctest-dynamic-overlay", from: "1.5.0"), - ], - targets: [ - .target( - name: "SQLiteData", - dependencies: [ - .product(name: "ConcurrencyExtras", package: "swift-concurrency-extras"), - .product(name: "Dependencies", package: "swift-dependencies"), - .product(name: "GRDB", package: "GRDB.swift"), - .product(name: "IssueReporting", package: "xctest-dynamic-overlay"), - .product(name: "OrderedCollections", package: "swift-collections"), - .product(name: "Sharing", package: "swift-sharing"), - .product(name: "StructuredQueriesSQLite", package: "swift-structured-queries"), - .product( - name: "Tagged", - package: "swift-tagged", - condition: .when(traits: ["SQLiteDataTagged"]) + name: "sqlite-data", + platforms: [ + .macOS(.v15) + ], + products: [ + .library( + name: "SQLiteData", + targets: ["SQLiteData"] + ), + .library( + name: "SQLiteDataTestSupport", + targets: ["SQLiteDataTestSupport"] + ), + ], + traits: [ + .trait( + name: "SQLiteDataTagged", + description: "Introduce SQLiteData conformances to the swift-tagged package." + ) + ], + dependencies: [ + .package(url: "https://github.com/apple/swift-collections", from: "1.0.0"), + .package(name: "GRDB.swift", path: "../GRDB-swift"), + .package(url: "https://github.com/pointfreeco/swift-concurrency-extras", from: "1.0.0"), + .package(url: "https://github.com/pointfreeco/swift-custom-dump", from: "1.3.3"), + .package(url: "https://github.com/pointfreeco/swift-dependencies", from: "1.9.0"), + .package(url: "https://github.com/pointfreeco/swift-sharing", from: "2.3.0"), + .package(url: "https://github.com/pointfreeco/swift-snapshot-testing", from: "1.18.4"), + .package( + path: "../swift-structured-queries", + traits: [ + .trait( + name: "StructuredQueriesTagged", + condition: .when(traits: ["SQLiteDataTagged"])) + ] + ), + .package(url: "https://github.com/pointfreeco/swift-tagged", from: "0.10.0"), + .package(url: "https://github.com/pointfreeco/xctest-dynamic-overlay", from: "1.5.0"), + ], + targets: [ + .target( + name: "SQLiteData", + dependencies: [ + .product(name: "ConcurrencyExtras", package: "swift-concurrency-extras"), + .product(name: "Dependencies", package: "swift-dependencies"), + .product(name: "GRDB", package: "GRDB.swift"), + .product(name: "IssueReporting", package: "xctest-dynamic-overlay"), + .product(name: "OrderedCollections", package: "swift-collections"), + .product(name: "Sharing", package: "swift-sharing"), + .product(name: "StructuredQueriesSQLite", package: "swift-structured-queries"), + .product( + name: "Tagged", + package: "swift-tagged", + condition: .when(traits: ["SQLiteDataTagged"]) + ), + ] ), - ] - ), - .target( - name: "SQLiteDataTestSupport", - dependencies: [ - "SQLiteData", - .product(name: "ConcurrencyExtras", package: "swift-concurrency-extras"), - .product(name: "CustomDump", package: "swift-custom-dump"), - .product(name: "Dependencies", package: "swift-dependencies"), - .product(name: "InlineSnapshotTesting", package: "swift-snapshot-testing"), - .product(name: "StructuredQueriesTestSupport", package: "swift-structured-queries"), - ] - ), - .testTarget( - name: "SQLiteDataTests", - dependencies: [ - "SQLiteData", - "SQLiteDataTestSupport", - .product(name: "DependenciesTestSupport", package: "swift-dependencies"), - .product(name: "InlineSnapshotTesting", package: "swift-snapshot-testing"), - .product(name: "SnapshotTestingCustomDump", package: "swift-snapshot-testing"), - .product(name: "StructuredQueries", package: "swift-structured-queries"), - ] - ), - ], - swiftLanguageModes: [.v6] + .target( + name: "SQLiteDataTestSupport", + dependencies: [ + "SQLiteData", + .product(name: "ConcurrencyExtras", package: "swift-concurrency-extras"), + .product(name: "CustomDump", package: "swift-custom-dump"), + .product(name: "Dependencies", package: "swift-dependencies"), + .product(name: "InlineSnapshotTesting", package: "swift-snapshot-testing"), + .product(name: "StructuredQueriesTestSupport", package: "swift-structured-queries"), + ] + ), + .testTarget( + name: "SQLiteDataTests", + dependencies: [ + "SQLiteData", + "SQLiteDataTestSupport", + .product(name: "DependenciesTestSupport", package: "swift-dependencies"), + .product(name: "InlineSnapshotTesting", package: "swift-snapshot-testing"), + .product(name: "SnapshotTestingCustomDump", package: "swift-snapshot-testing"), + .product(name: "StructuredQueries", package: "swift-structured-queries"), + ] + ), + ], + swiftLanguageModes: [.v6] ) let swiftSettings: [SwiftSetting] = [ - .enableUpcomingFeature("MemberImportVisibility") - // .unsafeFlags([ - // "-Xfrontend", - // "-warn-long-function-bodies=50", - // "-Xfrontend", - // "-warn-long-expression-type-checking=50", - // ]) + .enableUpcomingFeature("MemberImportVisibility") + // .unsafeFlags([ + // "-Xfrontend", + // "-warn-long-function-bodies=50", + // "-Xfrontend", + // "-warn-long-expression-type-checking=50", + // ]) ] for index in package.targets.indices { - package.targets[index].swiftSettings = swiftSettings + package.targets[index].swiftSettings = swiftSettings } #if !os(Windows) - // Add the documentation compiler plugin if possible - package.dependencies.append( - .package(url: "https://github.com/apple/swift-docc-plugin", from: "1.0.0") - ) + // Add the documentation compiler plugin if possible + package.dependencies.append( + .package(url: "https://github.com/apple/swift-docc-plugin", from: "1.0.0") + ) #endif diff --git a/Package@swift-6.0.swift b/Package@swift-6.0.swift deleted file mode 100644 index 76704aab..00000000 --- a/Package@swift-6.0.swift +++ /dev/null @@ -1,89 +0,0 @@ -// swift-tools-version: 6.0 - -import PackageDescription - -let package = Package( - name: "sqlite-data", - platforms: [ - .macOS(.v15), - ], - products: [ - .library( - name: "SQLiteData", - targets: ["SQLiteData"] - ), - .library( - name: "SQLiteDataTestSupport", - targets: ["SQLiteDataTestSupport"] - ), - ], - dependencies: [ - .package(url: "https://github.com/apple/swift-collections", from: "1.0.0"), - .package(url: "https://github.com/groue/GRDB.swift", from: "7.6.0"), - .package(url: "https://github.com/pointfreeco/swift-concurrency-extras", from: "1.0.0"), - .package(url: "https://github.com/pointfreeco/swift-custom-dump", from: "1.3.3"), - .package(url: "https://github.com/pointfreeco/swift-dependencies", from: "1.9.0"), - .package(url: "https://github.com/pointfreeco/swift-sharing", from: "2.3.0"), - .package(url: "https://github.com/pointfreeco/swift-snapshot-testing", from: "1.18.4"), - .package(url: "https://github.com/pointfreeco/swift-structured-queries", from: "0.24.0"), - .package(url: "https://github.com/pointfreeco/xctest-dynamic-overlay", from: "1.5.0"), - ], - targets: [ - .target( - name: "SQLiteData", - dependencies: [ - .product(name: "ConcurrencyExtras", package: "swift-concurrency-extras"), - .product(name: "Dependencies", package: "swift-dependencies"), - .product(name: "GRDB", package: "GRDB.swift"), - .product(name: "IssueReporting", package: "xctest-dynamic-overlay"), - .product(name: "OrderedCollections", package: "swift-collections"), - .product(name: "Sharing", package: "swift-sharing"), - .product(name: "StructuredQueriesSQLite", package: "swift-structured-queries"), - ] - ), - .target( - name: "SQLiteDataTestSupport", - dependencies: [ - "SQLiteData", - .product(name: "ConcurrencyExtras", package: "swift-concurrency-extras"), - .product(name: "CustomDump", package: "swift-custom-dump"), - .product(name: "Dependencies", package: "swift-dependencies"), - .product(name: "InlineSnapshotTesting", package: "swift-snapshot-testing"), - .product(name: "StructuredQueriesTestSupport", package: "swift-structured-queries"), - ] - ), - .testTarget( - name: "SQLiteDataTests", - dependencies: [ - "SQLiteData", - "SQLiteDataTestSupport", - .product(name: "DependenciesTestSupport", package: "swift-dependencies"), - .product(name: "InlineSnapshotTesting", package: "swift-snapshot-testing"), - .product(name: "SnapshotTestingCustomDump", package: "swift-snapshot-testing"), - .product(name: "StructuredQueries", package: "swift-structured-queries"), - ] - ), - ], - swiftLanguageModes: [.v6] -) - -let swiftSettings: [SwiftSetting] = [ - .enableUpcomingFeature("MemberImportVisibility") - // .unsafeFlags([ - // "-Xfrontend", - // "-warn-long-function-bodies=50", - // "-Xfrontend", - // "-warn-long-expression-type-checking=50", - // ]) -] - -for index in package.targets.indices { - package.targets[index].swiftSettings = swiftSettings -} - -#if !os(Windows) - // Add the documentation compiler plugin if possible - package.dependencies.append( - .package(url: "https://github.com/apple/swift-docc-plugin", from: "1.0.0") - ) -#endif diff --git a/Sources/SQLiteData/CloudKit/CloudKit+StructuredQueries.swift b/Sources/SQLiteData/CloudKit/CloudKit+StructuredQueries.swift index 6e9eacd9..5c53bb93 100644 --- a/Sources/SQLiteData/CloudKit/CloudKit+StructuredQueries.swift +++ b/Sources/SQLiteData/CloudKit/CloudKit+StructuredQueries.swift @@ -284,7 +284,7 @@ self.userModificationTime = other.userModificationTime for column in T.TableColumns.writableColumns { - func open(_ column: some WritableTableColumnExpression) { + func open(_ column: some WritableTableColumnExpression) { let key = column.name let keyPath = column.keyPath as! KeyPath let didSet: Bool diff --git a/Sources/SQLiteData/CloudKit/PrimaryKeyMigration.swift b/Sources/SQLiteData/CloudKit/PrimaryKeyMigration.swift index 9a97fb0b..8616c8bc 100644 --- a/Sources/SQLiteData/CloudKit/PrimaryKeyMigration.swift +++ b/Sources/SQLiteData/CloudKit/PrimaryKeyMigration.swift @@ -181,25 +181,18 @@ newColumns.append(columns.primaryKey.name) } newColumns.append(contentsOf: tableInfo.map(\.name)) - convertedColumns.append( - contentsOf: tableInfo.map { tableInfo -> QueryFragment in - if tableInfo.name == primaryKey.name, tableInfo.isInt { - return $backfillUUID(id: #sql("\(quote: tableInfo.name)"), table: tableName, salt: salt) - .queryFragment - } else if tableInfo.isInt, - let foreignKey = foreignKeys.first(where: { $0.from == tableInfo.name }) - { - return $backfillUUID( - id: #sql("\(quote: foreignKey.from)"), - table: foreignKey.table, - salt: salt - ) - .queryFragment - } else { - return QueryFragment(quote: tableInfo.name) - } - } - ) + // NB: Swift 6.3-dev crashes on complex closures with #sql macro interpolation. + // Extracted to helper function to work around compiler bug. + for info in tableInfo { + let fragment = convertTableInfoToQueryFragment( + info, + primaryKeyName: primaryKey.name, + foreignKeys: foreignKeys, + tableName: tableName, + salt: salt + ) + convertedColumns.append(fragment) + } try #sql(QueryFragment(stringLiteral: newSchema)).execute(db) try #sql( @@ -225,6 +218,32 @@ ) .execute(db) } + + // NB: Extracted from closure to work around Swift 6.3-dev compiler crash. + // The compiler crashes on complex closures mixing #sql macro interpolation with nested closures. + private static func convertTableInfoToQueryFragment( + _ tableInfo: PragmaTableInfo, + primaryKeyName: String, + foreignKeys: [PragmaForeignKeyList], + tableName: String, + salt: String + ) -> QueryFragment { + if tableInfo.name == primaryKeyName, tableInfo.isInt { + return $backfillUUID(id: #sql("\(quote: tableInfo.name)"), table: tableName, salt: salt) + .queryFragment + } else if tableInfo.isInt, + let foreignKey = foreignKeys.first(where: { $0.from == tableInfo.name }) + { + return $backfillUUID( + id: #sql("\(quote: foreignKey.from)"), + table: foreignKey.table, + salt: salt + ) + .queryFragment + } else { + return QueryFragment(quote: tableInfo.name) + } + } } extension StringProtocol { From 766cd7d4f9fec4f0865b71e923c7bc0a3f214cbc Mon Sep 17 00:00:00 2001 From: Stijn Willems Date: Sat, 13 Dec 2025 21:09:23 +0100 Subject: [PATCH 4/9] workaround for compiler crash - no cloudkit for swift 6.3 at the moment (#4) --- .../CloudKit/CloudKit+StructuredQueries.swift | 25 +- .../CloudKit/PrimaryKeyMigration.swift | 420 +++++++++--------- Sources/SQLiteData/CloudKit/SyncEngine.swift | 4 +- .../StructuredQueries+GRDB/Table+GRDB.swift | 63 +++ 4 files changed, 304 insertions(+), 208 deletions(-) create mode 100644 Sources/SQLiteData/StructuredQueries+GRDB/Table+GRDB.swift diff --git a/Sources/SQLiteData/CloudKit/CloudKit+StructuredQueries.swift b/Sources/SQLiteData/CloudKit/CloudKit+StructuredQueries.swift index 5c53bb93..1da15ba4 100644 --- a/Sources/SQLiteData/CloudKit/CloudKit+StructuredQueries.swift +++ b/Sources/SQLiteData/CloudKit/CloudKit+StructuredQueries.swift @@ -283,10 +283,29 @@ typealias EquatableCKRecordValueProtocol = CKRecordValueProtocol & Equatable self.userModificationTime = other.userModificationTime - for column in T.TableColumns.writableColumns { - func open(_ column: some WritableTableColumnExpression) { + _update( + with: other, + row: row, + columnNames: &columnNames, + parentForeignKey: parentForeignKey, + columns: T.TableColumns.writableColumns + ) + } + + private func _update( + with other: CKRecord, + row: T, + columnNames: inout [String], + parentForeignKey: ForeignKey?, + columns: [any WritableTableColumnExpression] + ) { + typealias EquatableCKRecordValueProtocol = CKRecordValueProtocol & Equatable + + for column in columns { + func open(_ column: some WritableTableColumnExpression) { let key = column.name - let keyPath = column.keyPath as! KeyPath + let column = column as! any WritableTableColumnExpression + let keyPath = column.keyPath let didSet: Bool if let value = other[key] as? CKAsset { didSet = setAsset(value, forKey: key, at: other.encryptedValues[at: key]) diff --git a/Sources/SQLiteData/CloudKit/PrimaryKeyMigration.swift b/Sources/SQLiteData/CloudKit/PrimaryKeyMigration.swift index 8616c8bc..22f50a8f 100644 --- a/Sources/SQLiteData/CloudKit/PrimaryKeyMigration.swift +++ b/Sources/SQLiteData/CloudKit/PrimaryKeyMigration.swift @@ -2,103 +2,117 @@ import CryptoKit import Foundation - @available(iOS 17, macOS 14, tvOS 17, watchOS 10, *) - extension SyncEngine { - /// Migrates integer primary-keyed tables and tables without primary keys to - /// CloudKit-compatible, UUID primary keys. - /// - /// To synchronize a table to CloudKit it must have a primary key, and that primary key must - /// be a globally unique identifier, such as a UUID. However, changing the type of a column - /// in SQLite is a [multi-step process] that must be followed very carefully, otherwise you run - /// the risk of corrupting your users' data. - /// - /// [multi-step process]: https://sqlite.org/lang_altertable.html#making_other_kinds_of_table_schema_changes - /// - /// This method is a general purpose tool that analyzes a set of tables to try to automatically - /// perform that migration for you. It performs the following steps: - /// - /// * Computes a random salt to use for backfilling existing integer primary keys with UUIDs. - /// * For each table passed to this method: - /// * Creates a new table with essentially the same schema, but the following changes: - /// * A new temporary name is given to the table. - /// * If an integer primary key exists, it is changed to a "TEXT" column with a - /// "NOT NULL PRIMARY KEY ON CONFLICT REPLACE DEFAULT" constraint, and a default of - /// "uuid()" if no `uuid` argument is given, otherwise the argument is used. - /// * If no primary key exists, one is added with the same constraints as above. - /// * All integer foreign keys are changed to "TEXT" columns with no other changes. - /// * All data from the existing table is copied over into the new table, but all integer - /// IDs (both primary and foreign keys) are transformed into UUIDs by MD5 hashing the - /// integer, the table name, and the salt mentioned above, and turning that hash into a - /// UUID. - /// * The existing table is dropped. - /// * Thew new table is renamed to have the same name as the table just dropped. - /// * Any indexes and stored triggers that were removed from dropping tables in the steps - /// above are recreated. - /// * Executes a "PRAGMA foreign_key_check;" query to make sure that the integrity of the data - /// is preserved. - /// - /// If all of those steps are performed without throwing an error, then your schema and data - /// should have been successfully migrated to UUIDs. If an error is thrown for any reason, - /// then it means the tool was not able to safely migrate your data and so you will need to - /// perform the migration [manually](). - /// - /// - Parameters: - /// - db: A database connection. - /// - tables: Tables to migrate. - /// - uuidFunction: A UUID function to use for the default value of primary keys in your - /// tables' schemas. If `nil`, SQLite's `uuid` function will be used. - public static func migratePrimaryKeys( - _ db: Database, - tables: repeat (each T).Type, - dropUniqueConstraints: Bool = false, - uuid uuidFunction: (any ScalarDatabaseFunction<(), UUID>)? = nil - ) throws - where - repeat (each T).PrimaryKey.QueryOutput: IdentifierStringConvertible, - repeat (each T).TableColumns.PrimaryColumn: TableColumnExpression - { - let salt = - (try uuidFunction.flatMap { uuid -> UUID? in - try #sql("SELECT \(quote: uuid.name)()", as: UUID.self).fetchOne(db) - } - ?? UUID()).uuidString + // NB: Swift 6.2.3 and 6.3-dev crash when compiling the primary key migration feature + // due to a compiler bug with #sql macro interpolation combined with $backfillUUID + // (macro-generated database function). + // + // This entire feature is disabled on Swift 6.2.3+ until the compiler bug is fixed. + // See detailed comments below in the PrimaryKeyedTable extension. + // + // Tracking: https://github.com/doozMen/sqlite-data/issues/2 + // TODO: Re-enable when Swift 6.3 stabilizes or compiler bug is fixed. + #if !compiler(>=6.2.3) + @available(iOS 17, macOS 14, tvOS 17, watchOS 10, *) + extension SyncEngine { + /// Migrates integer primary-keyed tables and tables without primary keys to + /// CloudKit-compatible, UUID primary keys. + /// + /// To synchronize a table to CloudKit it must have a primary key, and that primary key must + /// be a globally unique identifier, such as a UUID. However, changing the type of a column + /// in SQLite is a [multi-step process] that must be followed very carefully, otherwise you run + /// the risk of corrupting your users' data. + /// + /// [multi-step process]: https://sqlite.org/lang_altertable.html#making_other_kinds_of_table_schema_changes + /// + /// This method is a general purpose tool that analyzes a set of tables to try to automatically + /// perform that migration for you. It performs the following steps: + /// + /// * Computes a random salt to use for backfilling existing integer primary keys with UUIDs. + /// * For each table passed to this method: + /// * Creates a new table with essentially the same schema, but the following changes: + /// * A new temporary name is given to the table. + /// * If an integer primary key exists, it is changed to a "TEXT" column with a + /// "NOT NULL PRIMARY KEY ON CONFLICT REPLACE DEFAULT" constraint, and a default of + /// "uuid()" if no `uuid` argument is given, otherwise the argument is used. + /// * If no primary key exists, one is added with the same constraints as above. + /// * All integer foreign keys are changed to "TEXT" columns with no other changes. + /// * All data from the existing table is copied over into the new table, but all integer + /// IDs (both primary and foreign keys) are transformed into UUIDs by MD5 hashing the + /// integer, the table name, and the salt mentioned above, and turning that hash into a + /// UUID. + /// * The existing table is dropped. + /// * Thew new table is renamed to have the same name as the table just dropped. + /// * Any indexes and stored triggers that were removed from dropping tables in the steps + /// above are recreated. + /// * Executes a "PRAGMA foreign_key_check;" query to make sure that the integrity of the data + /// is preserved. + /// + /// If all of those steps are performed without throwing an error, then your schema and data + /// should have been successfully migrated to UUIDs. If an error is thrown for any reason, + /// then it means the tool was not able to safely migrate your data and so you will need to + /// perform the migration [manually](). + /// + /// - Note: This method is unavailable on Swift 6.2.3+ due to a compiler bug. + /// See https://github.com/doozMen/sqlite-data/issues/2 + /// + /// - Parameters: + /// - db: A database connection. + /// - tables: Tables to migrate. + /// - uuidFunction: A UUID function to use for the default value of primary keys in your + /// tables' schemas. If `nil`, SQLite's `uuid` function will be used. + public static func migratePrimaryKeys( + _ db: Database, + tables: repeat (each T).Type, + dropUniqueConstraints: Bool = false, + uuid uuidFunction: (any ScalarDatabaseFunction<(), UUID>)? = nil + ) throws + where + repeat (each T).PrimaryKey.QueryOutput: IdentifierStringConvertible, + repeat (each T).TableColumns.PrimaryColumn: TableColumnExpression + { + let salt = + (try uuidFunction.flatMap { uuid -> UUID? in + try #sql("SELECT \(quote: uuid.name)()", as: UUID.self).fetchOne(db) + } + ?? UUID()).uuidString - db.add(function: $backfillUUID) - defer { db.remove(function: $backfillUUID) } + db.add(function: $backfillUUID) + defer { db.remove(function: $backfillUUID) } - var migratedTableNames: [String] = [] - for table in repeat each tables { - migratedTableNames.append(table.tableName) - } - let indicesAndTriggersSQL = - try SQLiteSchema - .select(\.sql) - .where { - $0.tableName.in(migratedTableNames) - && $0.type.in([#bind(.index), #bind(.trigger)]) - && $0.sql.isNot(nil) + var migratedTableNames: [String] = [] + for table in repeat each tables { + migratedTableNames.append(table.tableName) + } + let indicesAndTriggersSQL = + try SQLiteSchema + .select(\.sql) + .where { + $0.tableName.in(migratedTableNames) + && $0.type.in([#bind(.index), #bind(.trigger)]) + && $0.sql.isNot(nil) + } + .fetchAll(db) + .compactMap(\.self) + for table in repeat each tables { + try table.migratePrimaryKeyToUUID( + db: db, + dropUniqueConstraints: dropUniqueConstraints, + uuidFunction: uuidFunction, + migratedTableNames: migratedTableNames, + salt: salt + ) + } + for sql in indicesAndTriggersSQL { + try #sql(QueryFragment(stringLiteral: sql)).execute(db) } - .fetchAll(db) - .compactMap(\.self) - for table in repeat each tables { - try table.migratePrimaryKeyToUUID( - db: db, - dropUniqueConstraints: dropUniqueConstraints, - uuidFunction: uuidFunction, - migratedTableNames: migratedTableNames, - salt: salt - ) - } - for sql in indicesAndTriggersSQL { - try #sql(QueryFragment(stringLiteral: sql)).execute(db) - } - let foreignKeyChecks = try PragmaForeignKeyCheck.all.fetchAll(db) - if !foreignKeyChecks.isEmpty { - throw ForeignKeyCheckError(checks: foreignKeyChecks) + let foreignKeyChecks = try PragmaForeignKeyCheck.all.fetchAll(db) + if !foreignKeyChecks.isEmpty { + throw ForeignKeyCheckError(checks: foreignKeyChecks) + } } } - } + #endif private struct MigrationError: LocalizedError { let reason: Reason @@ -124,127 +138,127 @@ } } - @available(iOS 16, macOS 13, tvOS 13, watchOS 9, *) - extension PrimaryKeyedTable where TableColumns.PrimaryColumn: TableColumnExpression { - fileprivate static func migratePrimaryKeyToUUID( - db: Database, - dropUniqueConstraints: Bool, - uuidFunction: (any ScalarDatabaseFunction<(), UUID>)? = nil, - migratedTableNames: [String], - salt: String - ) throws { - let schema = - try SQLiteSchema - .select(\.sql) - .where { $0.type.eq(#bind(.table)) && $0.tableName.eq(tableName) } - .fetchOne(db) - ?? nil - - guard let schema - else { - throw MigrationError(reason: .tableNotFound(tableName)) - } - - let tableInfo = try PragmaTableInfo.all.fetchAll(db) - let primaryKeys = tableInfo.filter(\.isPrimaryKey) - guard - (primaryKeys.count == 1 && primaryKeys[0].isInt) - || primaryKeys.isEmpty - else { - throw MigrationError(reason: .invalidPrimaryKey) - } - guard primaryKeys.count <= 1 - else { - throw MigrationError(reason: .invalidPrimaryKey) - } + // NB: Swift 6.2.3 and 6.3-dev crash when compiling this extension due to a compiler bug + // with #sql macro interpolation combined with $backfillUUID (macro-generated database + // function) in complex control flow. + // + // Error: "Assertion failed: (Start.isValid() == End.isValid() && 'Start and end should + // either both be valid or both be invalid!'), function SourceRange, file SourceLoc.h" + // + // This is a CloudKit-specific migration feature that: + // 1. Is only relevant on Apple platforms (CloudKit doesn't exist on Linux/Android) + // 2. Is used for migrating existing integer primary keys to UUID primary keys + // 3. Is not needed for new databases or cross-platform builds + // + // Workaround: Disable on Swift 6.2.3+ until the compiler bug is fixed. + // Tracking: https://github.com/doozMen/sqlite-data/issues/2 + // TODO: Re-enable when Swift 6.3 stabilizes or compiler bug is fixed. + #if !compiler(>=6.2.3) + @available(iOS 16, macOS 13, tvOS 13, watchOS 9, *) + extension PrimaryKeyedTable where TableColumns.PrimaryColumn: TableColumnExpression { + fileprivate static func migratePrimaryKeyToUUID( + db: Database, + dropUniqueConstraints: Bool, + uuidFunction: (any ScalarDatabaseFunction<(), UUID>)? = nil, + migratedTableNames: [String], + salt: String + ) throws { + let schema = + try SQLiteSchema + .select(\.sql) + .where { $0.type.eq(#bind(.table)) && $0.tableName.eq(tableName) } + .fetchOne(db) + ?? nil + + guard let schema + else { + throw MigrationError(reason: .tableNotFound(tableName)) + } - let foreignKeys = try PragmaForeignKeyList.all.fetchAll(db) - guard foreignKeys.allSatisfy({ migratedTableNames.contains($0.table) }) - else { - throw MigrationError(reason: .invalidForeignKey) - } + let tableInfo = try PragmaTableInfo.all.fetchAll(db) + let primaryKeys = tableInfo.filter(\.isPrimaryKey) + guard + (primaryKeys.count == 1 && primaryKeys[0].isInt) + || primaryKeys.isEmpty + else { + throw MigrationError(reason: .invalidPrimaryKey) + } + guard primaryKeys.count <= 1 + else { + throw MigrationError(reason: .invalidPrimaryKey) + } - let newTableName = "new_\(tableName)" - let uuidFunction = uuidFunction?.name ?? "uuid" - let newSchema = try schema.rewriteSchema( - dropUniqueConstraints: dropUniqueConstraints, - oldPrimaryKey: primaryKeys.first?.name, - newPrimaryKey: columns.primaryKey.name, - foreignKeys: foreignKeys.map(\.from), - uuidFunction: uuidFunction - ) + let foreignKeys = try PragmaForeignKeyList.all.fetchAll(db) + guard foreignKeys.allSatisfy({ migratedTableNames.contains($0.table) }) + else { + throw MigrationError(reason: .invalidForeignKey) + } - var newColumns: [String] = [] - var convertedColumns: [QueryFragment] = [] - if primaryKeys.first == nil { - convertedColumns.append("NULL") - newColumns.append(columns.primaryKey.name) - } - newColumns.append(contentsOf: tableInfo.map(\.name)) - // NB: Swift 6.3-dev crashes on complex closures with #sql macro interpolation. - // Extracted to helper function to work around compiler bug. - for info in tableInfo { - let fragment = convertTableInfoToQueryFragment( - info, - primaryKeyName: primaryKey.name, - foreignKeys: foreignKeys, - tableName: tableName, - salt: salt + let newTableName = "new_\(tableName)" + let uuidFunction = uuidFunction?.name ?? "uuid" + let newSchema = try schema.rewriteSchema( + dropUniqueConstraints: dropUniqueConstraints, + oldPrimaryKey: primaryKeys.first?.name, + newPrimaryKey: columns.primaryKey.name, + foreignKeys: foreignKeys.map(\.from), + uuidFunction: uuidFunction ) - convertedColumns.append(fragment) - } - try #sql(QueryFragment(stringLiteral: newSchema)).execute(db) - try #sql( - """ - INSERT INTO \(quote: newTableName) \ - ("rowid", \(newColumns.map { "\(quote: $0)" }.joined(separator: ", "))) - SELECT "rowid", \(convertedColumns.joined(separator: ", ")) \ - FROM \(Self.self) - ORDER BY "rowid" - """ - ) - .execute(db) - try #sql( - """ - DROP TABLE \(Self.self) - """ - ) - .execute(db) - try #sql( - """ - ALTER TABLE \(quote: newTableName) RENAME TO \(Self.self) - """ - ) - .execute(db) - } + var newColumns: [String] = [] + var convertedColumns: [QueryFragment] = [] + if primaryKeys.first == nil { + convertedColumns.append("NULL") + newColumns.append(columns.primaryKey.name) + } + newColumns.append(contentsOf: tableInfo.map(\.name)) + convertedColumns.append( + contentsOf: tableInfo.map { tableInfo -> QueryFragment in + if tableInfo.name == primaryKey.name, tableInfo.isInt { + return $backfillUUID( + id: #sql("\(quote: tableInfo.name)"), table: tableName, salt: salt + ) + .queryFragment + } else if tableInfo.isInt, + let foreignKey = foreignKeys.first(where: { $0.from == tableInfo.name }) + { + return $backfillUUID( + id: #sql("\(quote: foreignKey.from)"), + table: foreignKey.table, + salt: salt + ) + .queryFragment + } else { + return QueryFragment(quote: tableInfo.name) + } + } + ) - // NB: Extracted from closure to work around Swift 6.3-dev compiler crash. - // The compiler crashes on complex closures mixing #sql macro interpolation with nested closures. - private static func convertTableInfoToQueryFragment( - _ tableInfo: PragmaTableInfo, - primaryKeyName: String, - foreignKeys: [PragmaForeignKeyList], - tableName: String, - salt: String - ) -> QueryFragment { - if tableInfo.name == primaryKeyName, tableInfo.isInt { - return $backfillUUID(id: #sql("\(quote: tableInfo.name)"), table: tableName, salt: salt) - .queryFragment - } else if tableInfo.isInt, - let foreignKey = foreignKeys.first(where: { $0.from == tableInfo.name }) - { - return $backfillUUID( - id: #sql("\(quote: foreignKey.from)"), - table: foreignKey.table, - salt: salt + try #sql(QueryFragment(stringLiteral: newSchema)).execute(db) + try #sql( + """ + INSERT INTO \(quote: newTableName) \ + ("rowid", \(newColumns.map { "\(quote: $0)" }.joined(separator: ", "))) + SELECT "rowid", \(convertedColumns.joined(separator: ", ")) \ + FROM \(Self.self) + ORDER BY "rowid" + """ ) - .queryFragment - } else { - return QueryFragment(quote: tableInfo.name) + .execute(db) + try #sql( + """ + DROP TABLE \(Self.self) + """ + ) + .execute(db) + try #sql( + """ + ALTER TABLE \(quote: newTableName) RENAME TO \(Self.self) + """ + ) + .execute(db) } } - } + #endif extension StringProtocol { fileprivate func quoted() -> String { diff --git a/Sources/SQLiteData/CloudKit/SyncEngine.swift b/Sources/SQLiteData/CloudKit/SyncEngine.swift index 76bbbb71..2dfcb1ca 100644 --- a/Sources/SQLiteData/CloudKit/SyncEngine.swift +++ b/Sources/SQLiteData/CloudKit/SyncEngine.swift @@ -166,7 +166,7 @@ database: container.privateCloudDatabase, stateSerialization: try? metadatabase.read { db in try StateSerialization - .find(#bind(.private)) + .where { $0.scope == #bind(.private) } .select(\.data) .fetchOne(db) }, @@ -178,7 +178,7 @@ database: container.sharedCloudDatabase, stateSerialization: try? metadatabase.read { db in try StateSerialization - .find(#bind(.shared)) + .where { $0.scope == #bind(.shared) } .select(\.data) .fetchOne(db) }, diff --git a/Sources/SQLiteData/StructuredQueries+GRDB/Table+GRDB.swift b/Sources/SQLiteData/StructuredQueries+GRDB/Table+GRDB.swift new file mode 100644 index 00000000..025a2cba --- /dev/null +++ b/Sources/SQLiteData/StructuredQueries+GRDB/Table+GRDB.swift @@ -0,0 +1,63 @@ +import StructuredQueriesCore + +extension StructuredQueriesCore.Table { + /// Returns an array of all values fetched from the database. + /// + /// - Parameter db: A database connection. + /// - Returns: An array of all values decoded from the database. + @inlinable + public static func fetchAll(_ db: Database) throws -> [QueryOutput] { + try all.fetchAll(db) + } + + /// Returns a single value fetched from the database. + /// + /// - Parameter db: A database connection. + /// - Returns: A single value decoded from the database. + @inlinable + public static func fetchOne(_ db: Database) throws -> QueryOutput? { + try all.fetchOne(db) + } + + /// Returns the number of rows fetched by the query. + /// + /// - Parameter db: A database connection. + /// - Returns: The number of rows fetched by the query. + @inlinable + public static func fetchCount(_ db: Database) throws -> Int { + try all.fetchCount(db) + } + + /// Returns a cursor to all values fetched from the database. + /// + /// - Parameter db: A database connection. + /// - Returns: A cursor to all values decoded from the database. + @inlinable + public static func fetchCursor(_ db: Database) throws -> QueryCursor { + try all.fetchCursor(db) + } +} + +// NB: Swift 6.2.3 and 6.3-dev guard Select.find(_:) in swift-structured-queries due to compiler crashes. +// This extension depends on that method, so it must also be guarded. +// Tracking: https://github.com/doozMen/sqlite-data/issues/2 +#if !compiler(>=6.2.3) + extension StructuredQueriesCore.PrimaryKeyedTable { + /// Returns a single value fetched from the database for a given primary key. + /// + /// - Parameters + /// - db: A database connection. + /// - primaryKey: A primary key identifying a table row. + /// - Returns: A single value decoded from the database. + @inlinable + public static func find( + _ db: Database, + key primaryKey: some QueryExpression + ) throws -> QueryOutput { + guard let record = try Self.all.find(primaryKey).fetchOne(db) else { + throw NotFound() + } + return record + } + } +#endif From d3afb1e24d71fee0047408fa78dcd61d4b3c195f Mon Sep 17 00:00:00 2001 From: Stijn Willems Date: Sat, 13 Dec 2025 21:11:22 +0100 Subject: [PATCH 5/9] simplify type for compiler (#5) --- Package.resolved | 32 +++++++++++++++---- Package.swift | 10 ++++-- .../CloudKit/CloudKit+StructuredQueries.swift | 4 ++- .../SQLiteData/CloudKit/CloudKitSharing.swift | 2 +- .../CloudKit/DefaultSyncEngine.swift | 2 +- .../CloudKit/Internal/CloudContainer.swift | 2 +- .../CloudKit/Internal/CloudDatabase.swift | 2 +- .../CloudKit/Internal/CloudKitFunctions.swift | 2 +- .../CloudKit/Internal/DataManager.swift | 2 +- .../CloudKit/Internal/DatetimeGenerator.swift | 2 +- .../Internal/DefaultNotificationCenter.swift | 2 +- .../CloudKit/Internal/ForeignKey.swift | 2 +- .../CloudKit/Internal/IsolatedWeakVar.swift | 2 +- .../CloudKit/Internal/Logging.swift | 2 +- .../CloudKit/Internal/Metadatabase.swift | 2 +- .../Internal/MockCloudContainer.swift | 2 +- .../CloudKit/Internal/MockCloudDatabase.swift | 2 +- .../CloudKit/Internal/MockSyncEngine.swift | 2 +- .../Internal/PendingRecordZoneChange.swift | 2 +- .../CloudKit/Internal/Pragmas.swift | 2 +- .../CloudKit/Internal/RecordType.swift | 2 +- .../CloudKit/Internal/SQLiteSchema.swift | 2 +- .../Internal/StateSerialization.swift | 2 +- .../CloudKit/Internal/SyncEngine.Event.swift | 2 +- .../Internal/SyncEngineProtocol+Live.swift | 2 +- .../Internal/SyncEngineProtocol.swift | 2 +- .../CloudKit/Internal/TableInfo.swift | 2 +- .../CloudKit/Internal/Triggers.swift | 2 +- .../CloudKit/Internal/UnsyncedRecordID.swift | 2 +- .../CloudKit/Internal/UserDatabase.swift | 2 +- .../CloudKit/Internal/_SendableMetatype.swift | 2 +- .../CloudKit/PrimaryKeyMigration.swift | 2 +- Sources/SQLiteData/CloudKit/SyncEngine.swift | 2 +- .../CloudKit/SyncEngineDelegate.swift | 2 +- .../SQLiteData/CloudKit/SyncMetadata.swift | 2 +- 35 files changed, 67 insertions(+), 43 deletions(-) diff --git a/Package.resolved b/Package.resolved index 41a5cdb7..ba38b909 100644 --- a/Package.resolved +++ b/Package.resolved @@ -1,5 +1,5 @@ { - "originHash" : "a18b1644857cf7bbf788548464ff5983bac7f7a8faa125c59045f5d830aa5f28", + "originHash" : "c53c34c164015d035216379ca730f2630209ddabb19d29107d35f34491225ea9", "pins" : [ { "identity" : "combine-schedulers", @@ -10,6 +10,15 @@ "version" : "1.1.0" } }, + { + "identity" : "grdb.swift", + "kind" : "remoteSourceControl", + "location" : "https://github.com/doozMen/GRDB.swift", + "state" : { + "branch" : "master", + "revision" : "aa0079aeb82a4bf00324561a40bffe68c6fe1c26" + } + }, { "identity" : "swift-clocks", "kind" : "remoteSourceControl", @@ -85,19 +94,19 @@ { "identity" : "swift-perception", "kind" : "remoteSourceControl", - "location" : "https://github.com/pointfreeco/swift-perception", + "location" : "https://github.com/doozMen/swift-perception", "state" : { - "revision" : "4f47ebafed5f0b0172cf5c661454fa8e28fb2ac4", - "version" : "2.0.9" + "branch" : "main", + "revision" : "9237a92716ccbcd4be8c5330ed372f243c9d23d9" } }, { "identity" : "swift-sharing", "kind" : "remoteSourceControl", - "location" : "https://github.com/pointfreeco/swift-sharing", + "location" : "https://github.com/doozMen/swift-sharing", "state" : { - "revision" : "3bfc408cc2d0bee2287c174da6b1c76768377818", - "version" : "2.7.4" + "branch" : "main", + "revision" : "a367f93207aa67a7a9953946ae3b8d47d223f6af" } }, { @@ -109,6 +118,15 @@ "version" : "1.18.7" } }, + { + "identity" : "swift-structured-queries", + "kind" : "remoteSourceControl", + "location" : "https://github.com/doozMen/swift-structured-queries", + "state" : { + "branch" : "main", + "revision" : "85f39901d6c6046fa2f5119717741d9cc8a50b7f" + } + }, { "identity" : "swift-syntax", "kind" : "remoteSourceControl", diff --git a/Package.swift b/Package.swift index fa9fcc85..45f20e2b 100644 --- a/Package.swift +++ b/Package.swift @@ -25,14 +25,18 @@ let package = Package( ], dependencies: [ .package(url: "https://github.com/apple/swift-collections", from: "1.0.0"), - .package(name: "GRDB.swift", path: "../GRDB-swift"), + // NB: Fork synced with upstream v7.9.0 + .package(url: "https://github.com/doozMen/GRDB.swift", branch: "master"), .package(url: "https://github.com/pointfreeco/swift-concurrency-extras", from: "1.0.0"), .package(url: "https://github.com/pointfreeco/swift-custom-dump", from: "1.3.3"), .package(url: "https://github.com/pointfreeco/swift-dependencies", from: "1.9.0"), - .package(url: "https://github.com/pointfreeco/swift-sharing", from: "2.3.0"), + // NB: Fork with Swift 6.3 fixes (uses doozMen/swift-perception) + .package(url: "https://github.com/doozMen/swift-sharing", branch: "main"), .package(url: "https://github.com/pointfreeco/swift-snapshot-testing", from: "1.18.4"), + // NB: Fork with Swift 6.3 fixes .package( - path: "../swift-structured-queries", + url: "https://github.com/doozMen/swift-structured-queries", + branch: "main", traits: [ .trait( name: "StructuredQueriesTagged", diff --git a/Sources/SQLiteData/CloudKit/CloudKit+StructuredQueries.swift b/Sources/SQLiteData/CloudKit/CloudKit+StructuredQueries.swift index 1da15ba4..7387b693 100644 --- a/Sources/SQLiteData/CloudKit/CloudKit+StructuredQueries.swift +++ b/Sources/SQLiteData/CloudKit/CloudKit+StructuredQueries.swift @@ -1,4 +1,6 @@ -#if canImport(CloudKit) +// NB: Swift 6.3-dev compiler crashes on the generic `open` function in _update. +// Tracking: https://github.com/doozMen/sqlite-data/issues/2 +#if canImport(CloudKit) && !compiler(>=6.3) import CloudKit import CryptoKit import StructuredQueriesCore diff --git a/Sources/SQLiteData/CloudKit/CloudKitSharing.swift b/Sources/SQLiteData/CloudKit/CloudKitSharing.swift index 09f4181b..dda920be 100644 --- a/Sources/SQLiteData/CloudKit/CloudKitSharing.swift +++ b/Sources/SQLiteData/CloudKit/CloudKitSharing.swift @@ -1,4 +1,4 @@ -#if canImport(CloudKit) +#if canImport(CloudKit) && !compiler(>=6.3) import CloudKit import Dependencies import SwiftUI diff --git a/Sources/SQLiteData/CloudKit/DefaultSyncEngine.swift b/Sources/SQLiteData/CloudKit/DefaultSyncEngine.swift index 9a2c27be..2eaf080a 100644 --- a/Sources/SQLiteData/CloudKit/DefaultSyncEngine.swift +++ b/Sources/SQLiteData/CloudKit/DefaultSyncEngine.swift @@ -1,4 +1,4 @@ -#if canImport(CloudKit) +#if canImport(CloudKit) && !compiler(>=6.3) import CloudKit import Dependencies diff --git a/Sources/SQLiteData/CloudKit/Internal/CloudContainer.swift b/Sources/SQLiteData/CloudKit/Internal/CloudContainer.swift index 4829102f..b0cc5191 100644 --- a/Sources/SQLiteData/CloudKit/Internal/CloudContainer.swift +++ b/Sources/SQLiteData/CloudKit/Internal/CloudContainer.swift @@ -1,4 +1,4 @@ -#if canImport(CloudKit) +#if canImport(CloudKit) && !compiler(>=6.3) import CloudKit @available(iOS 15, tvOS 15, macOS 12, watchOS 8, *) diff --git a/Sources/SQLiteData/CloudKit/Internal/CloudDatabase.swift b/Sources/SQLiteData/CloudKit/Internal/CloudDatabase.swift index 94a0dc61..76da5142 100644 --- a/Sources/SQLiteData/CloudKit/Internal/CloudDatabase.swift +++ b/Sources/SQLiteData/CloudKit/Internal/CloudDatabase.swift @@ -1,4 +1,4 @@ -#if canImport(CloudKit) +#if canImport(CloudKit) && !compiler(>=6.3) import CloudKit package protocol CloudDatabase: AnyObject, Hashable, Sendable { diff --git a/Sources/SQLiteData/CloudKit/Internal/CloudKitFunctions.swift b/Sources/SQLiteData/CloudKit/Internal/CloudKitFunctions.swift index 5d166e16..64545208 100644 --- a/Sources/SQLiteData/CloudKit/Internal/CloudKitFunctions.swift +++ b/Sources/SQLiteData/CloudKit/Internal/CloudKitFunctions.swift @@ -1,4 +1,4 @@ -#if canImport(CloudKit) +#if canImport(CloudKit) && !compiler(>=6.3) import CloudKit import Foundation diff --git a/Sources/SQLiteData/CloudKit/Internal/DataManager.swift b/Sources/SQLiteData/CloudKit/Internal/DataManager.swift index 0bf280c4..27f848c8 100644 --- a/Sources/SQLiteData/CloudKit/Internal/DataManager.swift +++ b/Sources/SQLiteData/CloudKit/Internal/DataManager.swift @@ -1,4 +1,4 @@ -#if canImport(CloudKit) && canImport(CryptoKit) +#if canImport(CloudKit) && canImport(CryptoKit) && !compiler(>=6.3) import CryptoKit import Dependencies import Foundation diff --git a/Sources/SQLiteData/CloudKit/Internal/DatetimeGenerator.swift b/Sources/SQLiteData/CloudKit/Internal/DatetimeGenerator.swift index dd161e50..675babfb 100644 --- a/Sources/SQLiteData/CloudKit/Internal/DatetimeGenerator.swift +++ b/Sources/SQLiteData/CloudKit/Internal/DatetimeGenerator.swift @@ -1,4 +1,4 @@ -#if canImport(CloudKit) +#if canImport(CloudKit) && !compiler(>=6.3) import Dependencies import Foundation diff --git a/Sources/SQLiteData/CloudKit/Internal/DefaultNotificationCenter.swift b/Sources/SQLiteData/CloudKit/Internal/DefaultNotificationCenter.swift index d1423e4e..3fca7742 100644 --- a/Sources/SQLiteData/CloudKit/Internal/DefaultNotificationCenter.swift +++ b/Sources/SQLiteData/CloudKit/Internal/DefaultNotificationCenter.swift @@ -1,4 +1,4 @@ -#if canImport(CloudKit) && canImport(UIKit) +#if canImport(CloudKit) && canImport(UIKit) && !compiler(>=6.3) import UIKit private enum DefaultNotificationCenterKey: DependencyKey { diff --git a/Sources/SQLiteData/CloudKit/Internal/ForeignKey.swift b/Sources/SQLiteData/CloudKit/Internal/ForeignKey.swift index ae329bb6..d8bec02e 100644 --- a/Sources/SQLiteData/CloudKit/Internal/ForeignKey.swift +++ b/Sources/SQLiteData/CloudKit/Internal/ForeignKey.swift @@ -1,4 +1,4 @@ -#if canImport(CloudKit) +#if canImport(CloudKit) && !compiler(>=6.3) import Foundation import StructuredQueriesCore diff --git a/Sources/SQLiteData/CloudKit/Internal/IsolatedWeakVar.swift b/Sources/SQLiteData/CloudKit/Internal/IsolatedWeakVar.swift index 4a17ef04..28674b35 100644 --- a/Sources/SQLiteData/CloudKit/Internal/IsolatedWeakVar.swift +++ b/Sources/SQLiteData/CloudKit/Internal/IsolatedWeakVar.swift @@ -1,4 +1,4 @@ -#if canImport(CloudKit) +#if canImport(CloudKit) && !compiler(>=6.3) import Foundation final class IsolatedWeakVar: @unchecked Sendable { diff --git a/Sources/SQLiteData/CloudKit/Internal/Logging.swift b/Sources/SQLiteData/CloudKit/Internal/Logging.swift index b7d4b214..d0f7f059 100644 --- a/Sources/SQLiteData/CloudKit/Internal/Logging.swift +++ b/Sources/SQLiteData/CloudKit/Internal/Logging.swift @@ -1,4 +1,4 @@ -#if DEBUG && canImport(CloudKit) +#if DEBUG && canImport(CloudKit) && !compiler(>=6.3) import CloudKit import TabularData import os diff --git a/Sources/SQLiteData/CloudKit/Internal/Metadatabase.swift b/Sources/SQLiteData/CloudKit/Internal/Metadatabase.swift index 8ea33c42..9dc19936 100644 --- a/Sources/SQLiteData/CloudKit/Internal/Metadatabase.swift +++ b/Sources/SQLiteData/CloudKit/Internal/Metadatabase.swift @@ -1,4 +1,4 @@ -#if canImport(CloudKit) +#if canImport(CloudKit) && !compiler(>=6.3) import Foundation import os diff --git a/Sources/SQLiteData/CloudKit/Internal/MockCloudContainer.swift b/Sources/SQLiteData/CloudKit/Internal/MockCloudContainer.swift index f0421c82..65cb276a 100644 --- a/Sources/SQLiteData/CloudKit/Internal/MockCloudContainer.swift +++ b/Sources/SQLiteData/CloudKit/Internal/MockCloudContainer.swift @@ -1,4 +1,4 @@ -#if canImport(CloudKit) +#if canImport(CloudKit) && !compiler(>=6.3) import CloudKit @available(iOS 17, macOS 14, tvOS 17, watchOS 10, *) diff --git a/Sources/SQLiteData/CloudKit/Internal/MockCloudDatabase.swift b/Sources/SQLiteData/CloudKit/Internal/MockCloudDatabase.swift index 7edfeccb..17000d63 100644 --- a/Sources/SQLiteData/CloudKit/Internal/MockCloudDatabase.swift +++ b/Sources/SQLiteData/CloudKit/Internal/MockCloudDatabase.swift @@ -1,4 +1,4 @@ -#if canImport(CloudKit) +#if canImport(CloudKit) && !compiler(>=6.3) import CloudKit import IssueReporting diff --git a/Sources/SQLiteData/CloudKit/Internal/MockSyncEngine.swift b/Sources/SQLiteData/CloudKit/Internal/MockSyncEngine.swift index 31f1c02c..608a223f 100644 --- a/Sources/SQLiteData/CloudKit/Internal/MockSyncEngine.swift +++ b/Sources/SQLiteData/CloudKit/Internal/MockSyncEngine.swift @@ -1,4 +1,4 @@ -#if canImport(CloudKit) +#if canImport(CloudKit) && !compiler(>=6.3) import CloudKit import OrderedCollections diff --git a/Sources/SQLiteData/CloudKit/Internal/PendingRecordZoneChange.swift b/Sources/SQLiteData/CloudKit/Internal/PendingRecordZoneChange.swift index fad64e0d..4772ad69 100644 --- a/Sources/SQLiteData/CloudKit/Internal/PendingRecordZoneChange.swift +++ b/Sources/SQLiteData/CloudKit/Internal/PendingRecordZoneChange.swift @@ -1,4 +1,4 @@ -#if canImport(CloudKit) +#if canImport(CloudKit) && !compiler(>=6.3) import CloudKit @Table("sqlitedata_icloud_pendingRecordZoneChanges") diff --git a/Sources/SQLiteData/CloudKit/Internal/Pragmas.swift b/Sources/SQLiteData/CloudKit/Internal/Pragmas.swift index e30a254f..798f58c2 100644 --- a/Sources/SQLiteData/CloudKit/Internal/Pragmas.swift +++ b/Sources/SQLiteData/CloudKit/Internal/Pragmas.swift @@ -1,4 +1,4 @@ -#if canImport(CloudKit) +#if canImport(CloudKit) && !compiler(>=6.3) @Table struct PragmaDatabaseList { static var tableAlias: String? { "databases" } diff --git a/Sources/SQLiteData/CloudKit/Internal/RecordType.swift b/Sources/SQLiteData/CloudKit/Internal/RecordType.swift index 4c610b80..ea440f28 100644 --- a/Sources/SQLiteData/CloudKit/Internal/RecordType.swift +++ b/Sources/SQLiteData/CloudKit/Internal/RecordType.swift @@ -1,4 +1,4 @@ -#if canImport(CloudKit) +#if canImport(CloudKit) && !compiler(>=6.3) @Table("sqlitedata_icloud_recordTypes") package struct RecordType: Hashable { @Column(primaryKey: true) diff --git a/Sources/SQLiteData/CloudKit/Internal/SQLiteSchema.swift b/Sources/SQLiteData/CloudKit/Internal/SQLiteSchema.swift index 40fa7d87..2d9b629d 100644 --- a/Sources/SQLiteData/CloudKit/Internal/SQLiteSchema.swift +++ b/Sources/SQLiteData/CloudKit/Internal/SQLiteSchema.swift @@ -1,4 +1,4 @@ -#if canImport(CloudKit) +#if canImport(CloudKit) && !compiler(>=6.3) @Table("sqlite_schema") package struct SQLiteSchema { package let type: ObjectType diff --git a/Sources/SQLiteData/CloudKit/Internal/StateSerialization.swift b/Sources/SQLiteData/CloudKit/Internal/StateSerialization.swift index 2b76b33b..5febee44 100644 --- a/Sources/SQLiteData/CloudKit/Internal/StateSerialization.swift +++ b/Sources/SQLiteData/CloudKit/Internal/StateSerialization.swift @@ -1,4 +1,4 @@ -#if canImport(CloudKit) +#if canImport(CloudKit) && !compiler(>=6.3) import CloudKit import StructuredQueriesCore diff --git a/Sources/SQLiteData/CloudKit/Internal/SyncEngine.Event.swift b/Sources/SQLiteData/CloudKit/Internal/SyncEngine.Event.swift index 230aac02..12f42947 100644 --- a/Sources/SQLiteData/CloudKit/Internal/SyncEngine.Event.swift +++ b/Sources/SQLiteData/CloudKit/Internal/SyncEngine.Event.swift @@ -1,4 +1,4 @@ -#if canImport(CloudKit) +#if canImport(CloudKit) && !compiler(>=6.3) import CloudKit @available(iOS 17, macOS 14, tvOS 17, watchOS 10, *) diff --git a/Sources/SQLiteData/CloudKit/Internal/SyncEngineProtocol+Live.swift b/Sources/SQLiteData/CloudKit/Internal/SyncEngineProtocol+Live.swift index d462e198..4055aaf6 100644 --- a/Sources/SQLiteData/CloudKit/Internal/SyncEngineProtocol+Live.swift +++ b/Sources/SQLiteData/CloudKit/Internal/SyncEngineProtocol+Live.swift @@ -1,4 +1,4 @@ -#if canImport(CloudKit) +#if canImport(CloudKit) && !compiler(>=6.3) import CloudKit @available(iOS 17, macOS 14, tvOS 17, watchOS 10, *) diff --git a/Sources/SQLiteData/CloudKit/Internal/SyncEngineProtocol.swift b/Sources/SQLiteData/CloudKit/Internal/SyncEngineProtocol.swift index 58cff003..8857f998 100644 --- a/Sources/SQLiteData/CloudKit/Internal/SyncEngineProtocol.swift +++ b/Sources/SQLiteData/CloudKit/Internal/SyncEngineProtocol.swift @@ -1,4 +1,4 @@ -#if canImport(CloudKit) +#if canImport(CloudKit) && !compiler(>=6.3) import CloudKit @available(iOS 17, macOS 14, tvOS 17, watchOS 10, *) diff --git a/Sources/SQLiteData/CloudKit/Internal/TableInfo.swift b/Sources/SQLiteData/CloudKit/Internal/TableInfo.swift index 2207ce94..415c4036 100644 --- a/Sources/SQLiteData/CloudKit/Internal/TableInfo.swift +++ b/Sources/SQLiteData/CloudKit/Internal/TableInfo.swift @@ -1,4 +1,4 @@ -#if canImport(CloudKit) +#if canImport(CloudKit) && !compiler(>=6.3) import StructuredQueriesCore @Table diff --git a/Sources/SQLiteData/CloudKit/Internal/Triggers.swift b/Sources/SQLiteData/CloudKit/Internal/Triggers.swift index c0aa01b4..b0908649 100644 --- a/Sources/SQLiteData/CloudKit/Internal/Triggers.swift +++ b/Sources/SQLiteData/CloudKit/Internal/Triggers.swift @@ -1,4 +1,4 @@ -#if canImport(CloudKit) +#if canImport(CloudKit) && !compiler(>=6.3) import CloudKit import Foundation diff --git a/Sources/SQLiteData/CloudKit/Internal/UnsyncedRecordID.swift b/Sources/SQLiteData/CloudKit/Internal/UnsyncedRecordID.swift index f24a3e04..d138c951 100644 --- a/Sources/SQLiteData/CloudKit/Internal/UnsyncedRecordID.swift +++ b/Sources/SQLiteData/CloudKit/Internal/UnsyncedRecordID.swift @@ -1,4 +1,4 @@ -#if canImport(CloudKit) +#if canImport(CloudKit) && !compiler(>=6.3) import CloudKit import StructuredQueriesCore diff --git a/Sources/SQLiteData/CloudKit/Internal/UserDatabase.swift b/Sources/SQLiteData/CloudKit/Internal/UserDatabase.swift index b0fb5edc..1c651213 100644 --- a/Sources/SQLiteData/CloudKit/Internal/UserDatabase.swift +++ b/Sources/SQLiteData/CloudKit/Internal/UserDatabase.swift @@ -1,4 +1,4 @@ -#if canImport(CloudKit) +#if canImport(CloudKit) && !compiler(>=6.3) import Dependencies package struct UserDatabase { diff --git a/Sources/SQLiteData/CloudKit/Internal/_SendableMetatype.swift b/Sources/SQLiteData/CloudKit/Internal/_SendableMetatype.swift index 55ccae7f..28ea67c0 100644 --- a/Sources/SQLiteData/CloudKit/Internal/_SendableMetatype.swift +++ b/Sources/SQLiteData/CloudKit/Internal/_SendableMetatype.swift @@ -1,4 +1,4 @@ -#if canImport(CloudKit) +#if canImport(CloudKit) && !compiler(>=6.3) #if swift(>=6.2) public typealias _SendableMetatype = SendableMetatype #else diff --git a/Sources/SQLiteData/CloudKit/PrimaryKeyMigration.swift b/Sources/SQLiteData/CloudKit/PrimaryKeyMigration.swift index 22f50a8f..9473c61c 100644 --- a/Sources/SQLiteData/CloudKit/PrimaryKeyMigration.swift +++ b/Sources/SQLiteData/CloudKit/PrimaryKeyMigration.swift @@ -1,4 +1,4 @@ -#if canImport(CloudKit) && canImport(CryptoKit) +#if canImport(CloudKit) && canImport(CryptoKit) && !compiler(>=6.3) import CryptoKit import Foundation diff --git a/Sources/SQLiteData/CloudKit/SyncEngine.swift b/Sources/SQLiteData/CloudKit/SyncEngine.swift index 2dfcb1ca..0dcd48ab 100644 --- a/Sources/SQLiteData/CloudKit/SyncEngine.swift +++ b/Sources/SQLiteData/CloudKit/SyncEngine.swift @@ -1,4 +1,4 @@ -#if canImport(CloudKit) +#if canImport(CloudKit) && !compiler(>=6.3) import CloudKit import ConcurrencyExtras import Dependencies diff --git a/Sources/SQLiteData/CloudKit/SyncEngineDelegate.swift b/Sources/SQLiteData/CloudKit/SyncEngineDelegate.swift index b373dfc4..60c16adb 100644 --- a/Sources/SQLiteData/CloudKit/SyncEngineDelegate.swift +++ b/Sources/SQLiteData/CloudKit/SyncEngineDelegate.swift @@ -1,4 +1,4 @@ -#if canImport(CloudKit) +#if canImport(CloudKit) && !compiler(>=6.3) import CloudKit import CustomDump diff --git a/Sources/SQLiteData/CloudKit/SyncMetadata.swift b/Sources/SQLiteData/CloudKit/SyncMetadata.swift index 2d64e7a4..683f544a 100644 --- a/Sources/SQLiteData/CloudKit/SyncMetadata.swift +++ b/Sources/SQLiteData/CloudKit/SyncMetadata.swift @@ -1,4 +1,4 @@ -#if canImport(CloudKit) +#if canImport(CloudKit) && !compiler(>=6.3) import CloudKit /// A table that tracks metadata related to synchronized data. From 7cc08272ecc683a0327e1f06e3e8aed142842a9a Mon Sep 17 00:00:00 2001 From: Stijn Willems Date: Sat, 13 Dec 2025 17:46:31 +0100 Subject: [PATCH 6/9] workaround for compiler crash - no cloudkit for swift 6.3 at the moment From 656c44cbea29f63af78a254d112b44061cf267f3 Mon Sep 17 00:00:00 2001 From: Stijn Willems Date: Sat, 13 Dec 2025 19:03:15 +0100 Subject: [PATCH 7/9] chore: Use local swift-perception fork with Swift 6.3 fixes MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Points to ../swift-perception which has fixes for Swift 6.3-dev compiler compatibility. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 --- Package.swift | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/Package.swift b/Package.swift index 45f20e2b..7cc044a1 100644 --- a/Package.swift +++ b/Package.swift @@ -26,17 +26,17 @@ let package = Package( dependencies: [ .package(url: "https://github.com/apple/swift-collections", from: "1.0.0"), // NB: Fork synced with upstream v7.9.0 - .package(url: "https://github.com/doozMen/GRDB.swift", branch: "master"), + .package(url: "https://github.com/doozMen/GRDB.swift", revision: "aa0079aeb82a4bf00324561a40bffe68c6fe1c26"), .package(url: "https://github.com/pointfreeco/swift-concurrency-extras", from: "1.0.0"), .package(url: "https://github.com/pointfreeco/swift-custom-dump", from: "1.3.3"), .package(url: "https://github.com/pointfreeco/swift-dependencies", from: "1.9.0"), // NB: Fork with Swift 6.3 fixes (uses doozMen/swift-perception) - .package(url: "https://github.com/doozMen/swift-sharing", branch: "main"), + .package(url: "https://github.com/doozMen/swift-sharing", revision: "f1170dc9b28faea3edec20705839eb2bc349bcdb"), .package(url: "https://github.com/pointfreeco/swift-snapshot-testing", from: "1.18.4"), // NB: Fork with Swift 6.3 fixes .package( url: "https://github.com/doozMen/swift-structured-queries", - branch: "main", + revision: "85f39901d6c6046fa2f5119717741d9cc8a50b7f", traits: [ .trait( name: "StructuredQueriesTagged", From ddf6c26bf8f39dd481a7444f345d471a24c7ea38 Mon Sep 17 00:00:00 2001 From: Stijn Willems Date: Sat, 13 Dec 2025 19:08:29 +0100 Subject: [PATCH 8/9] simplify type for compiler --- Package.resolved | 150 ----------------------------------------------- 1 file changed, 150 deletions(-) delete mode 100644 Package.resolved diff --git a/Package.resolved b/Package.resolved deleted file mode 100644 index ba38b909..00000000 --- a/Package.resolved +++ /dev/null @@ -1,150 +0,0 @@ -{ - "originHash" : "c53c34c164015d035216379ca730f2630209ddabb19d29107d35f34491225ea9", - "pins" : [ - { - "identity" : "combine-schedulers", - "kind" : "remoteSourceControl", - "location" : "https://github.com/pointfreeco/combine-schedulers", - "state" : { - "revision" : "fd16d76fd8b9a976d88bfb6cacc05ca8d19c91b6", - "version" : "1.1.0" - } - }, - { - "identity" : "grdb.swift", - "kind" : "remoteSourceControl", - "location" : "https://github.com/doozMen/GRDB.swift", - "state" : { - "branch" : "master", - "revision" : "aa0079aeb82a4bf00324561a40bffe68c6fe1c26" - } - }, - { - "identity" : "swift-clocks", - "kind" : "remoteSourceControl", - "location" : "https://github.com/pointfreeco/swift-clocks", - "state" : { - "revision" : "cc46202b53476d64e824e0b6612da09d84ffde8e", - "version" : "1.0.6" - } - }, - { - "identity" : "swift-collections", - "kind" : "remoteSourceControl", - "location" : "https://github.com/apple/swift-collections", - "state" : { - "revision" : "7b847a3b7008b2dc2f47ca3110d8c782fb2e5c7e", - "version" : "1.3.0" - } - }, - { - "identity" : "swift-concurrency-extras", - "kind" : "remoteSourceControl", - "location" : "https://github.com/pointfreeco/swift-concurrency-extras", - "state" : { - "revision" : "5a3825302b1a0d744183200915a47b508c828e6f", - "version" : "1.3.2" - } - }, - { - "identity" : "swift-custom-dump", - "kind" : "remoteSourceControl", - "location" : "https://github.com/pointfreeco/swift-custom-dump", - "state" : { - "revision" : "82645ec760917961cfa08c9c0c7104a57a0fa4b1", - "version" : "1.3.3" - } - }, - { - "identity" : "swift-dependencies", - "kind" : "remoteSourceControl", - "location" : "https://github.com/pointfreeco/swift-dependencies", - "state" : { - "revision" : "a10f9feeb214bc72b5337b6ef6d5a029360db4cc", - "version" : "1.10.0" - } - }, - { - "identity" : "swift-docc-plugin", - "kind" : "remoteSourceControl", - "location" : "https://github.com/apple/swift-docc-plugin", - "state" : { - "revision" : "3e4f133a77e644a5812911a0513aeb7288b07d06", - "version" : "1.4.5" - } - }, - { - "identity" : "swift-docc-symbolkit", - "kind" : "remoteSourceControl", - "location" : "https://github.com/swiftlang/swift-docc-symbolkit", - "state" : { - "revision" : "b45d1f2ed151d057b54504d653e0da5552844e34", - "version" : "1.0.0" - } - }, - { - "identity" : "swift-identified-collections", - "kind" : "remoteSourceControl", - "location" : "https://github.com/pointfreeco/swift-identified-collections", - "state" : { - "revision" : "322d9ffeeba85c9f7c4984b39422ec7cc3c56597", - "version" : "1.1.1" - } - }, - { - "identity" : "swift-perception", - "kind" : "remoteSourceControl", - "location" : "https://github.com/doozMen/swift-perception", - "state" : { - "branch" : "main", - "revision" : "9237a92716ccbcd4be8c5330ed372f243c9d23d9" - } - }, - { - "identity" : "swift-sharing", - "kind" : "remoteSourceControl", - "location" : "https://github.com/doozMen/swift-sharing", - "state" : { - "branch" : "main", - "revision" : "a367f93207aa67a7a9953946ae3b8d47d223f6af" - } - }, - { - "identity" : "swift-snapshot-testing", - "kind" : "remoteSourceControl", - "location" : "https://github.com/pointfreeco/swift-snapshot-testing", - "state" : { - "revision" : "a8b7c5e0ed33d8ab8887d1654d9b59f2cbad529b", - "version" : "1.18.7" - } - }, - { - "identity" : "swift-structured-queries", - "kind" : "remoteSourceControl", - "location" : "https://github.com/doozMen/swift-structured-queries", - "state" : { - "branch" : "main", - "revision" : "85f39901d6c6046fa2f5119717741d9cc8a50b7f" - } - }, - { - "identity" : "swift-syntax", - "kind" : "remoteSourceControl", - "location" : "https://github.com/swiftlang/swift-syntax", - "state" : { - "revision" : "4799286537280063c85a32f09884cfbca301b1a1", - "version" : "602.0.0" - } - }, - { - "identity" : "xctest-dynamic-overlay", - "kind" : "remoteSourceControl", - "location" : "https://github.com/pointfreeco/xctest-dynamic-overlay", - "state" : { - "revision" : "31073495cae9caf243c440eac94b3ab067e3d7bc", - "version" : "1.8.0" - } - } - ], - "version" : 3 -} From b3082bb45743170ff2dc5824097142eaa62ef8d2 Mon Sep 17 00:00:00 2001 From: Stijn Willems Date: Sat, 13 Dec 2025 19:22:37 +0100 Subject: [PATCH 9/9] refactor: Use GitHub forks for Swift 6.3 compatibility MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Update all local path dependencies to use GitHub forks: - doozMen/GRDB.swift (master) - synced with upstream v7.9.0 - doozMen/swift-sharing (main) - Swift 6.3 fixes for swift-perception - doozMen/swift-structured-queries (main) - Swift 6.3 compiler crash guards All CloudKit code guarded with `!compiler(>=6.3)` to avoid compiler crashes. Tested successfully with Swift 6.3-dev snapshot. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 --- Package.resolved | 150 +++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 150 insertions(+) create mode 100644 Package.resolved diff --git a/Package.resolved b/Package.resolved new file mode 100644 index 00000000..ba38b909 --- /dev/null +++ b/Package.resolved @@ -0,0 +1,150 @@ +{ + "originHash" : "c53c34c164015d035216379ca730f2630209ddabb19d29107d35f34491225ea9", + "pins" : [ + { + "identity" : "combine-schedulers", + "kind" : "remoteSourceControl", + "location" : "https://github.com/pointfreeco/combine-schedulers", + "state" : { + "revision" : "fd16d76fd8b9a976d88bfb6cacc05ca8d19c91b6", + "version" : "1.1.0" + } + }, + { + "identity" : "grdb.swift", + "kind" : "remoteSourceControl", + "location" : "https://github.com/doozMen/GRDB.swift", + "state" : { + "branch" : "master", + "revision" : "aa0079aeb82a4bf00324561a40bffe68c6fe1c26" + } + }, + { + "identity" : "swift-clocks", + "kind" : "remoteSourceControl", + "location" : "https://github.com/pointfreeco/swift-clocks", + "state" : { + "revision" : "cc46202b53476d64e824e0b6612da09d84ffde8e", + "version" : "1.0.6" + } + }, + { + "identity" : "swift-collections", + "kind" : "remoteSourceControl", + "location" : "https://github.com/apple/swift-collections", + "state" : { + "revision" : "7b847a3b7008b2dc2f47ca3110d8c782fb2e5c7e", + "version" : "1.3.0" + } + }, + { + "identity" : "swift-concurrency-extras", + "kind" : "remoteSourceControl", + "location" : "https://github.com/pointfreeco/swift-concurrency-extras", + "state" : { + "revision" : "5a3825302b1a0d744183200915a47b508c828e6f", + "version" : "1.3.2" + } + }, + { + "identity" : "swift-custom-dump", + "kind" : "remoteSourceControl", + "location" : "https://github.com/pointfreeco/swift-custom-dump", + "state" : { + "revision" : "82645ec760917961cfa08c9c0c7104a57a0fa4b1", + "version" : "1.3.3" + } + }, + { + "identity" : "swift-dependencies", + "kind" : "remoteSourceControl", + "location" : "https://github.com/pointfreeco/swift-dependencies", + "state" : { + "revision" : "a10f9feeb214bc72b5337b6ef6d5a029360db4cc", + "version" : "1.10.0" + } + }, + { + "identity" : "swift-docc-plugin", + "kind" : "remoteSourceControl", + "location" : "https://github.com/apple/swift-docc-plugin", + "state" : { + "revision" : "3e4f133a77e644a5812911a0513aeb7288b07d06", + "version" : "1.4.5" + } + }, + { + "identity" : "swift-docc-symbolkit", + "kind" : "remoteSourceControl", + "location" : "https://github.com/swiftlang/swift-docc-symbolkit", + "state" : { + "revision" : "b45d1f2ed151d057b54504d653e0da5552844e34", + "version" : "1.0.0" + } + }, + { + "identity" : "swift-identified-collections", + "kind" : "remoteSourceControl", + "location" : "https://github.com/pointfreeco/swift-identified-collections", + "state" : { + "revision" : "322d9ffeeba85c9f7c4984b39422ec7cc3c56597", + "version" : "1.1.1" + } + }, + { + "identity" : "swift-perception", + "kind" : "remoteSourceControl", + "location" : "https://github.com/doozMen/swift-perception", + "state" : { + "branch" : "main", + "revision" : "9237a92716ccbcd4be8c5330ed372f243c9d23d9" + } + }, + { + "identity" : "swift-sharing", + "kind" : "remoteSourceControl", + "location" : "https://github.com/doozMen/swift-sharing", + "state" : { + "branch" : "main", + "revision" : "a367f93207aa67a7a9953946ae3b8d47d223f6af" + } + }, + { + "identity" : "swift-snapshot-testing", + "kind" : "remoteSourceControl", + "location" : "https://github.com/pointfreeco/swift-snapshot-testing", + "state" : { + "revision" : "a8b7c5e0ed33d8ab8887d1654d9b59f2cbad529b", + "version" : "1.18.7" + } + }, + { + "identity" : "swift-structured-queries", + "kind" : "remoteSourceControl", + "location" : "https://github.com/doozMen/swift-structured-queries", + "state" : { + "branch" : "main", + "revision" : "85f39901d6c6046fa2f5119717741d9cc8a50b7f" + } + }, + { + "identity" : "swift-syntax", + "kind" : "remoteSourceControl", + "location" : "https://github.com/swiftlang/swift-syntax", + "state" : { + "revision" : "4799286537280063c85a32f09884cfbca301b1a1", + "version" : "602.0.0" + } + }, + { + "identity" : "xctest-dynamic-overlay", + "kind" : "remoteSourceControl", + "location" : "https://github.com/pointfreeco/xctest-dynamic-overlay", + "state" : { + "revision" : "31073495cae9caf243c440eac94b3ab067e3d7bc", + "version" : "1.8.0" + } + } + ], + "version" : 3 +}