Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions .github/workflows/test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,8 @@ jobs:
contents: read
uses: vapor/ci/.github/workflows/run-unit-tests.yml@main
secrets: inherit
with:
with_wasm: true

# Make sure downstream dependents still work
dependents-check:
Expand Down
13 changes: 11 additions & 2 deletions Package.swift
Original file line number Diff line number Diff line change
@@ -1,6 +1,11 @@
// swift-tools-version:5.8
import PackageDescription

/// This list matches the [supported platforms on the Swift 5.8 release of SPM](https://github.com/swiftlang/swift-package-manager/blob/release/5.8/Sources/PackageDescription/SupportedPlatforms.swift).
/// Don't add new platforms here unless raising the swift-tools-version of this manifest.
let allPlatforms: [Platform] = [.macOS, .macCatalyst, .iOS, .tvOS, .watchOS, .visionOS, .driverKit, .linux, .windows, .android, .wasi, .openbsd]
let nonWASIPlatforms: [Platform] = allPlatforms.filter { $0 != .wasi }

let package = Package(
name: "sqlite-kit",
platforms: [
Expand All @@ -22,8 +27,12 @@ let package = Package(
.target(
name: "SQLiteKit",
dependencies: [
.product(name: "NIOFoundationCompat", package: "swift-nio"),
.product(name: "AsyncKit", package: "async-kit"),
// Neither SwiftNIO nor AsyncKit builds for wasm32-unknown-wasip1. Target dependency
// conditions are evaluated per platform, so on WASI these are simply not linked;
// SQLiteKit then compiles without the connection pool and without the
// EventLoopFuture surface (see the `#if canImport(...)` gates in Sources/).
.product(name: "NIOFoundationCompat", package: "swift-nio", condition: .when(platforms: nonWASIPlatforms)),
.product(name: "AsyncKit", package: "async-kit", condition: .when(platforms: nonWASIPlatforms)),
.product(name: "SQLiteNIO", package: "sqlite-nio"),
.product(name: "SQLKit", package: "sql-kit"),
],
Expand Down
13 changes: 11 additions & 2 deletions Package@swift-5.9.swift
Original file line number Diff line number Diff line change
@@ -1,6 +1,11 @@
// swift-tools-version:5.9
import PackageDescription

/// This list matches the [supported platforms on the Swift 5.9 release of SPM](https://github.com/swiftlang/swift-package-manager/blob/release/5.9/Sources/PackageDescription/SupportedPlatforms.swift).
/// Don't add new platforms here unless raising the swift-tools-version of this manifest.
let allPlatforms: [Platform] = [.macOS, .macCatalyst, .iOS, .tvOS, .watchOS, .visionOS, .driverKit, .linux, .windows, .android, .wasi, .openbsd]
let nonWASIPlatforms: [Platform] = allPlatforms.filter { $0 != .wasi }

let package = Package(
name: "sqlite-kit",
platforms: [
Expand All @@ -22,8 +27,12 @@ let package = Package(
.target(
name: "SQLiteKit",
dependencies: [
.product(name: "NIOFoundationCompat", package: "swift-nio"),
.product(name: "AsyncKit", package: "async-kit"),
// Neither SwiftNIO nor AsyncKit builds for wasm32-unknown-wasip1. Target dependency
// conditions are evaluated per platform, so on WASI these are simply not linked;
// SQLiteKit then compiles without the connection pool and without the
// EventLoopFuture surface (see the `#if canImport(...)` gates in Sources/).
.product(name: "NIOFoundationCompat", package: "swift-nio", condition: .when(platforms: nonWASIPlatforms)),
.product(name: "AsyncKit", package: "async-kit", condition: .when(platforms: nonWASIPlatforms)),
.product(name: "SQLiteNIO", package: "sqlite-nio"),
.product(name: "SQLKit", package: "sql-kit"),
],
Expand Down
3 changes: 3 additions & 0 deletions Sources/SQLiteKit/Exports.swift
Original file line number Diff line number Diff line change
@@ -1,4 +1,7 @@
@_documentation(visibility: internal) @_exported import SQLKit
@_documentation(visibility: internal) @_exported import SQLiteNIO
// AsyncKit — and with it the connection pool — is unavailable where SwiftNIO is (see Package.swift).
#if canImport(AsyncKit)
@_documentation(visibility: internal) @_exported import AsyncKit
#endif
@_documentation(visibility: internal) @_exported import struct Logging.Logger
10 changes: 10 additions & 0 deletions Sources/SQLiteKit/SQLiteConnection+SQLKit.swift
Original file line number Diff line number Diff line change
Expand Up @@ -173,11 +173,13 @@ struct SQLiteDatabaseVersion: SQLDatabaseReportedVersion {
@usableFromInline
let decoder: SQLiteDataDecoder

#if canImport(NIOCore)
// See `SQLDatabase.eventLoop`.
@usableFromInline
var eventLoop: any EventLoop {
self.database.eventLoop
}
#endif

// See `SQLDatabase.version`.
@usableFromInline
Expand Down Expand Up @@ -209,6 +211,9 @@ struct SQLiteDatabaseVersion: SQLDatabaseReportedVersion {
self.queryLogLevel = queryLogLevel
}

// The `EventLoopFuture` overload only exists where SwiftNIO does; SQLKit's protocol drops the
// requirement on the other platforms and the `async` overload below carries the whole surface.
#if canImport(NIOCore)
// See `SQLDatabase.execute(sql:_:)`.
@usableFromInline
func execute(
Expand All @@ -234,6 +239,7 @@ struct SQLiteDatabaseVersion: SQLDatabaseReportedVersion {
{ onRow($0.sql(decoder: self.decoder)) }
)
}
#endif

// See `SQLDatabase.execute(sql:_:)`.
@usableFromInline
Expand All @@ -254,11 +260,15 @@ struct SQLiteDatabaseVersion: SQLDatabaseReportedVersion {
)
}

// `withSession(_:)` rides sqlite-nio's protocol-level `withConnection`, which exists only on the
// SwiftNIO build; elsewhere SQLKit's default `withSession` applies.
#if canImport(NIOCore)
// See `SQLDatabase.withSession(_:)`.
@usableFromInline
func withSession<R>(_ closure: @escaping @Sendable (any SQLDatabase) async throws -> R) async throws -> R {
try await self.database.withConnection {
try await closure($0.sql(encoder: self.encoder, decoder: self.decoder, queryLogLevel: self.queryLogLevel))
}
}
#endif
}
5 changes: 5 additions & 0 deletions Sources/SQLiteKit/SQLiteConnectionSource.swift
Original file line number Diff line number Diff line change
@@ -1,3 +1,7 @@
// ``SQLiteConnectionSource`` is a `ConnectionPoolSource`, built on AsyncKit and SwiftNIO's thread
// pool. Neither is available on every platform SQLiteKit supports; where they are absent, callers
// use sqlite-nio's concrete async `SQLiteConnection` directly and there is no pool.
#if canImport(AsyncKit)
#if canImport(Darwin)
import Foundation
#else
Expand Down Expand Up @@ -97,3 +101,4 @@ fileprivate extension SQLiteConfiguration.Storage {
}
}
}
#endif // canImport(AsyncKit)
6 changes: 6 additions & 0 deletions Sources/SQLiteKit/SQLiteDataDecoder.swift
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
import Foundation
import SQLiteNIO
@_spi(CodableUtilities) import SQLKit
#if canImport(NIOFoundationCompat)
import NIOFoundationCompat
#endif

/// Translates `SQLiteData` values received from the database into `Decodable` values.
///
Expand Down Expand Up @@ -51,7 +53,11 @@ public struct SQLiteDataDecoder: Sendable {

switch data {
case .text(let str): buf = .init(str.utf8)
#if canImport(NIOCore)
case .blob(let blob): buf = .init(buffer: blob, byteTransferStrategy: .noCopy)
#else
case .blob(let blob): buf = .init(blob) // `SQLiteData.blob` carries `[UInt8]` without SwiftNIO
#endif
// The remaining cases should never happen, but we implement them anyway just in case.
case .integer(let n): buf = .init(String(n).utf8)
case .float(let n): buf = .init(String(n).utf8)
Expand Down
2 changes: 2 additions & 0 deletions Sources/SQLiteKit/SQLiteDataEncoder.swift
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
#if canImport(NIOCore)
import NIOCore
#endif
import Foundation
@_spi(CodableUtilities) import SQLKit
import SQLiteNIO
Expand Down