Skip to content
Merged
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: 1 addition & 1 deletion .buildkite/shared-pipeline-vars
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
# This file is `source`'d before calling `buildkite-agent pipeline upload`, and can be used
# to set up some variables that will be interpolated in the `.yml` pipeline before uploading it.

XCODE_VERSION="16.3-v2"
XCODE_VERSION="26.0"
CI_TOOLKIT_PLUGIN_VERSION="3.7.1"
TEST_COLLECTOR_VERSION="v1.10.2"

Expand Down
2 changes: 1 addition & 1 deletion .buildkite/swift-test.sh
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ function build_for_real_device() {
echo "--- :swift: Building for $platform device"
export NSUnbufferedIO=YES
xcodebuild -destination "generic/platform=$platform" \
-scheme WordPressAPI \
-scheme WordPressAPI-Package \
-derivedDataPath DerivedData \
-skipPackagePluginValidation \
build | xcbeautify
Expand Down
5 changes: 4 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,10 @@
/docs
/docs.tar.gz

# Test DB Files
kotlin.db
swift.db

# Ignore Gradle project-specific cache directory
.gradle

Expand Down Expand Up @@ -33,7 +37,6 @@ fastlane/report.xml
libwordPressFFI.xcframework*
/swift-docs.tar.gz


# Auto-generated Swift Files
native/swift/Sources/wordpress-api-wrapper/*.swift

Expand Down
56 changes: 56 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

11 changes: 6 additions & 5 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -102,7 +102,7 @@ _build-apple-%-tvos _build-apple-%-tvos-sim _build-apple-%-watchos _build-apple-

# Build the library for a specific target
_build-apple-%:
cargo $(CARGO_OPTS) $(cargo_config_library) build --target $* --features export-uncancellable-endpoints --package wp_api --profile $(CARGO_PROFILE)
cargo $(CARGO_OPTS) $(cargo_config_library) build --target $* --features export-uncancellable-endpoints --package wp_api --profile $(CARGO_PROFILE) --no-default-features
./scripts/swift-bindings.sh target/$*/$(CARGO_PROFILE_DIRNAME)/libwp_api.a

# Build the library for one single platform, including real device and simulator.
Expand Down Expand Up @@ -153,7 +153,8 @@ swift-example-app-mac:
xcodebuild -project native/swift/Example/Example.xcodeproj -scheme Example -destination 'platform=macOS,arch=arm64' -skipPackagePluginValidation build

swift-example-app-ios:
bundle exec fastlane run run_tests project:native/swift/Example/Example.xcodeproj scheme:Example build_for_testing:true ensure_devices_found:true device:"iPhone 16 (18.4)" xcargs:"-skipPackagePluginValidation"
xcrun simctl create "iPhone 17 Pro Test Device" "com.apple.CoreSimulator.SimDeviceType.iPhone-17-Pro"
bundle exec fastlane run run_tests project:native/swift/Example/Example.xcodeproj scheme:Example build_for_testing:true ensure_devices_found:true device:"iPhone 17 Pro Test Device (26.0)" xcargs:"-skipPackagePluginValidation"

test-swift:
$(MAKE) test-swift-$(uname)
Expand All @@ -170,13 +171,13 @@ test-swift-darwin: xcframework
test-swift-macOS: test-swift-darwin

test-swift-iOS: xcframework
scripts/xcodebuild-test.sh iOS-18-4
scripts/xcodebuild-test.sh iOS-26-0

test-swift-tvOS: xcframework
scripts/xcodebuild-test.sh tvOS-18-4
scripts/xcodebuild-test.sh tvOS-26-0

test-swift-watchOS: xcframework
scripts/xcodebuild-test.sh watchOS-11-4
scripts/xcodebuild-test.sh watchOS-26-0

test-rust-lib:
$(rust_docker_run) cargo test --lib -- --nocapture
Expand Down
2 changes: 1 addition & 1 deletion Package.resolved

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

19 changes: 19 additions & 0 deletions Package.swift
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,10 @@ var package = Package(
.library(
name: "WordPressAPI",
targets: ["WordPressAPI"]
),
.library(
name: "WordPressApiCache",
targets: ["WordPressApiCache"]
)
],
dependencies: [
Expand Down Expand Up @@ -56,6 +60,13 @@ var package = Package(
.swiftLanguageMode(.v5)
]
),
.target(
name: "WordPressApiCache",
dependencies: [
.target(name: "WordPressAPIInternal")
],
path: "native/swift/Sources/wordpress-api-cache"
),
libwordpressFFI,
.testTarget(
name: "WordPressAPITests",
Expand All @@ -68,6 +79,14 @@ var package = Package(
swiftSettings: [
.define("PROGRESS_REPORTING_ENABLED", .when(platforms: [.iOS, .macOS, .tvOS, .watchOS]))
]
),
.testTarget(
name: "WordPressApiCacheTests",
dependencies: [
.target(name: "WordPressApiCache"),
.target(name: "WordPressAPIInternal")
],
path: "native/swift/Tests/wordpress-api-cache"
)
].addingIntegrationTests()
)
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
import kotlinx.coroutines.test.runTest
import org.junit.jupiter.api.Test
import org.junit.jupiter.api.parallel.Execution
import org.junit.jupiter.api.parallel.ExecutionMode
import rs.wordpress.cache.kotlin.WordPressApiCache
import rs.wordpress.cache.kotlin.WordPressApiCacheDelegate
import kotlin.test.assertEquals

@Execution(ExecutionMode.CONCURRENT)
class WordPressApiCacheTest {

@Test
fun testThatMigrationsWork() = runTest {
assertEquals(2, WordPressApiCache().performMigrations())
}

@Test
fun testBackgroundUpdateNotificationsWork() = runTest {
var updateCount = 0
val delegate = WordPressApiCacheDelegate(
callback = { updateHook ->
updateCount += 1
}
)

val cache = WordPressApiCache(delegate = delegate)
cache.startListeningForUpdates()

val migrationCount = cache.performMigrations()
assertEquals(updateCount, migrationCount)
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
package rs.wordpress.cache.kotlin

import kotlinx.coroutines.asCoroutineDispatcher
import kotlinx.coroutines.withContext
import uniffi.wp_api.DatabaseDelegate
import uniffi.wp_api.UpdateHook
import uniffi.wp_api.WpApiCache
import java.nio.file.Path
import java.util.concurrent.Executors

class WordPressApiCacheLoggingDelegate : DatabaseDelegate {
override fun didUpdate(updateHook: UpdateHook) {
println("Received update: $updateHook")
}
}
class WordPressApiCacheDelegate(
private val callback: (updateHook: UpdateHook) -> Unit
) : DatabaseDelegate {

override fun didUpdate(updateHook: UpdateHook) {
callback(updateHook)
}
}

class WordPressApiCache {
private val cache: WpApiCache
private val internalDispatcher = Executors.newSingleThreadExecutor().asCoroutineDispatcher()
private val delegate: DatabaseDelegate?

// Creates a new in-memory cache
constructor(delegate: WordPressApiCacheDelegate? = null) : this(":memory:", delegate)

// Creates a new cache at the specified file system URL
constructor(path: Path, delegate: WordPressApiCacheDelegate? = null) : this(path.toString(), delegate)

// Creates a new cache at the specified path
constructor(string: String, delegate: WordPressApiCacheDelegate? = null) {
this.cache = WpApiCache(string)
this.delegate = delegate
}

suspend fun performMigrations(): Int = withContext(internalDispatcher) {
cache.performMigrations().toInt()
}
fun startListeningForUpdates() {
if (this.delegate != null) {
this.cache.startListeningForUpdates(this.delegate)
}
}

fun stopListeningForUpdates() {
this.cache.stopListeningForUpdates()
}
}
57 changes: 57 additions & 0 deletions native/swift/Sources/wordpress-api-cache/WordPressApiCache.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
import Foundation
import WordPressAPIInternal

public actor WordPressApiCache {

private let cache: WpApiCache
private let delegate: any DatabaseDelegate

public struct Notifications {
public static let cacheDidUpdate = Notification.Name("WordPressApiCache.cacheDidUpdate")

public static func name(for table: String) -> Notification.Name {
Notification.Name(rawValue: "WordPressApiCache.cacheDidUpdate.\(table)")
}
}

final public class ApiCacheDelegate: DatabaseDelegate {
public init() {}

public func didUpdate(updateHook: WordPressAPIInternal.UpdateHook) {
let name = Notifications.name(for: updateHook.tableName)
NotificationCenter.default.post(name: name, object: updateHook)
}
}

/// Creates a new in-memory cache
public init(delegate: DatabaseDelegate = ApiCacheDelegate()) throws {
try self.init(path: ":memory:", delegate: delegate)
}

/// Creates a new cache at the specified file system URL
public init(url: URL, delegate: DatabaseDelegate = ApiCacheDelegate()) throws {
try self.init(path: url.absoluteString, delegate: delegate)
}

/// Creates a new cache at the specified path
public init(path: String, delegate: DatabaseDelegate = ApiCacheDelegate()) throws {
self.cache = try WpApiCache(path: path)
self.delegate = delegate
}

public func performMigrations() async throws -> Int {
return Int(try self.cache.performMigrations())
}

public func startListeningForUpdates() {
self.cache.startListeningForUpdates(delegate: self.delegate)
}

public func stopListeningForUpdates() {
self.cache.stopListeningForUpdates()
}

deinit {
self.cache.stopListeningForUpdates()
}
}
Loading