diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 33afc68..2cf762a 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -32,3 +32,71 @@ jobs: if [ "`ls -A | grep -i \\.xcworkspace\$`" ]; then filetype_parameter="workspace" && file_to_build="`ls -A | grep -i \\.xcworkspace\$`"; else filetype_parameter="project" && file_to_build="`ls -A | grep -i \\.xcodeproj\$`"; fi file_to_build=`echo $file_to_build | awk '{$1=$1;print}'` xcodebuild test -scheme "$scheme" -"$filetype_parameter" "$file_to_build" -destination "platform=iOS Simulator,name=iPhone 13 Pro,OS=15.2" + - name: Prepare codecov + uses: sersoft-gmbh/swift-coverage-action@v2 + id: coverage-files + with: + format: lcov + search-paths: ./DerivedData + env: + DEVELOPER_DIR: ${{ env.CI_XCODE_13 }} + - name: Upload coverage to Codecov + uses: codecov/codecov-action@v2 + with: + files: ${{join(fromJSON(steps.coverage-files.outputs.files), ',')}} + env_vars: IOS + +# spm-test: +# runs-on: macos-latest +# steps: +# - uses: maxim-lobanov/setup-xcode@v1 +# with: +# xcode-version: latest-stable +# - name: Checkout +# uses: actions/checkout@v2 +# - name: Build and Test +# run: swift test --enable-code-coverage -v +# - name: Prepare codecov +# uses: sersoft-gmbh/swift-coverage-action@v2 +# id: coverage-files +# with: +# format: lcov +# search-paths: ./.build +# - name: Upload coverage to Codecov +# uses: codecov/codecov-action@v2 +# with: +# files: ${{join(fromJSON(steps.coverage-files.outputs.files), ',')}} +# env_vars: SPM + +# linux: +# runs-on: ubuntu-18.04 +# steps: +# - uses: actions/checkout@v2 +# - uses: sersoft-gmbh/SwiftyActions@v1 +# with: +# release-version: "5" +# github-token: ${{ secrets.GITHUB_TOKEN }} +# - name: Build and Test +# run: swift test --enable-test-discovery --enable-code-coverage -v +# - name: Prepare codecov +# run: | +# llvm-cov export -format="lcov" .build/x86_64-unknown-linux-gnu/debug/PapyrusPackageTests.xctest -instr-profile .build/x86_64-unknown-linux-gnu/debug/codecov/default.profdata > info_linux.lcov +# - name: Upload coverage to Codecov +# uses: codecov/codecov-action@v2 +# with: +# env_vars: LINUX +# fail_ci_if_error: true + +# windows: +# runs-on: windows-2019 +# steps: +# - uses: actions/checkout@v2 +# - uses: MaxDesiatov/swift-windows-action@v1 +# with: +# swift-version: "5.5.1" +# shell-action: swift test --enable-test-discovery --enable-code-coverage -v +# - name: Upload coverage to Codecov +# uses: codecov/codecov-action@v2 +# with: +# env_vars: WINDOWS + diff --git a/.gitignore b/.gitignore index 4c3f3d9..310ce4d 100644 --- a/.gitignore +++ b/.gitignore @@ -10,6 +10,7 @@ xcuserdata profile *.moved-aside +.swiftpm DerivedData .idea/ *.hmap diff --git a/Package.swift b/Package.swift index bd22d3f..eea7281 100644 --- a/Package.swift +++ b/Package.swift @@ -1,4 +1,4 @@ -// swift-tools-version:5.3 +// swift-tools-version:5.5 // The swift-tools-version declares the minimum version of Swift required to build this package. import PackageDescription @@ -7,8 +7,10 @@ import PackageDescription let package = Package( name: "Papyrus", platforms: [ - .iOS("15.0"), - .macOS("12.0") + .iOS(.v15), + .macOS(.v12), + .tvOS(.v15), + .watchOS(.v8) ], products: [ .library( @@ -24,7 +26,8 @@ let package = Package( .testTarget( name: "PapyrusTests", dependencies: ["Papyrus"], - path: "PapyrusTests" + path: "PapyrusTests", + exclude: ["Supporting Files/Info.plist"] ) ] ) diff --git a/Papyrus/Source/Logger.swift b/Papyrus/Source/Logger.swift index 87bdeeb..3a1565f 100644 --- a/Papyrus/Source/Logger.swift +++ b/Papyrus/Source/Logger.swift @@ -1,3 +1,5 @@ +#if !os(Linux) && !os(Android) && !os(Windows) + import Foundation import os.log @@ -75,3 +77,4 @@ public enum LogLevel: Int { extension LogLevel: Comparable { public static func <(lhs: LogLevel, rhs: LogLevel) -> Bool { lhs.rawValue < rhs.rawValue } } +#endif diff --git a/Papyrus/Source/PapyrusStore.swift b/Papyrus/Source/PapyrusStore.swift index f98d2f6..28a8de4 100644 --- a/Papyrus/Source/PapyrusStore.swift +++ b/Papyrus/Source/PapyrusStore.swift @@ -1,4 +1,6 @@ +#if canImport(Combine) import Combine +#endif import Foundation @@ -7,18 +9,23 @@ import Foundation /// `PapyrusStore` aims to hit the sweet spot between saving raw API responses to the file system /// and a fully fledged database like Realm. public final class PapyrusStore { - + #if !os(Linux) && !os(Android) && !os(Windows) /// The verboseness of the logger. public var logLevel: LogLevel { get { self.logger.logLevel } set { self.logger.logLevel = newValue } } + #endif // Private private let fileManager = FileManager.default + #if canImport(Combine) private var cancellables: Set = [] + #endif private let url: URL + #if !os(Linux) && !os(Android) && !os(Windows) private let logger: Logger + #endif private let encoder: JSONEncoder private let decoder: JSONDecoder @@ -35,12 +42,14 @@ public final class PapyrusStore { encoder: JSONEncoder = JSONEncoder(), decoder: JSONDecoder = JSONDecoder()) { self.url = url + self.encoder = encoder + self.decoder = decoder + #if !os(Linux) && !os(Android) && !os(Windows) self.logger = Logger( subsystem: "com.reddavis.PapyrusStore", category: "PapyrusStore" ) - self.encoder = encoder - self.decoder = decoder + #endif self.setupDataDirectory() } @@ -63,7 +72,9 @@ public final class PapyrusStore { do { try self.createDirectoryIfNeeded(at: self.url) } catch { + #if !os(Linux) && !os(Android) && !os(Windows) self.logger.fault("Unable to create store directory: \(error)") + #endif } } @@ -101,7 +112,9 @@ public final class PapyrusStore { // Create directory try self.fileManager.createDirectory(at: url, withIntermediateDirectories: true, attributes: nil) + #if !os(Linux) && !os(Android) && !os(Windows) self.logger.debug("Created directory: \(url.absoluteString)") + #endif } } @@ -123,9 +136,11 @@ public extension PapyrusStore { self.save($0, filename: $0.filename) touchedDirectories.insert(self.directoryURL(for: $0.typeDescription)) } - + + #if !os(Linux) && !os(Android) && !os(Windows) // Touch all changed directories self.logger.debug("Touching directories: \(touchedDirectories)") + #endif let now = Date() touchedDirectories.forEach { @@ -150,9 +165,13 @@ public extension PapyrusStore { try self.createDirectoryIfNeeded(for: object.typeDescription) let data = try self.encoder.encode(object) try data.write(to: self.fileURL(for: object.typeDescription, filename: filename)) + #if !os(Linux) && !os(Android) && !os(Windows) self.logger.debug("Saved: \(object.typeDescription) [Filename: \(filename)]") + #endif } catch { + #if !os(Linux) && !os(Android) && !os(Windows) self.logger.fault("Failed to save: \(error)") + #endif } } } @@ -225,12 +244,16 @@ public extension PapyrusStore { group.addTask { let url = self.fileURL(for: String(describing: type), id: id) try? self.fileManager.removeItem(at: url) + #if !os(Linux) && !os(Android) && !os(Windows) self.logger.debug("Deleted: \(url)") + #endif } } + #if !os(Linux) && !os(Android) && !os(Windows) // Touch all changed directories self.logger.debug("Touching directories: \(touchedDirectories)") + #endif let now = Date() for url in touchedDirectories { diff --git a/Papyrus/Source/Publishers/Collection/CollectionObserverPublisher.swift b/Papyrus/Source/Publishers/Collection/CollectionObserverPublisher.swift index 027e63f..ea9ca8b 100644 --- a/Papyrus/Source/Publishers/Collection/CollectionObserverPublisher.swift +++ b/Papyrus/Source/Publishers/Collection/CollectionObserverPublisher.swift @@ -1,3 +1,4 @@ +#if canImport(Combine) import Combine import Foundation @@ -22,3 +23,4 @@ struct CollectionObserverPublisher: Publisher where T: Papyrus { subscriber.receive(subscription: subscription) } } +#endif diff --git a/Papyrus/Source/Publishers/Collection/CollectionObserverSubscription.swift b/Papyrus/Source/Publishers/Collection/CollectionObserverSubscription.swift index 975df50..f0ec672 100644 --- a/Papyrus/Source/Publishers/Collection/CollectionObserverSubscription.swift +++ b/Papyrus/Source/Publishers/Collection/CollectionObserverSubscription.swift @@ -1,3 +1,4 @@ +#if canImport(Combine) import Combine import Foundation @@ -70,3 +71,4 @@ where T.Input == [Output] { } } } +#endif diff --git a/Papyrus/Source/Publishers/Object/ObjectObserverPublisher.swift b/Papyrus/Source/Publishers/Object/ObjectObserverPublisher.swift index 256d860..1c0eeac 100644 --- a/Papyrus/Source/Publishers/Object/ObjectObserverPublisher.swift +++ b/Papyrus/Source/Publishers/Object/ObjectObserverPublisher.swift @@ -1,3 +1,5 @@ +#if canImport(Combine) + import Combine import Foundation @@ -28,3 +30,4 @@ struct ObjectObserverPublisher: Publisher where T: Papyrus & Equatable { subscriber.receive(subscription: subscription) } } +#endif diff --git a/Papyrus/Source/Publishers/Object/ObjectObserverSubscription.swift b/Papyrus/Source/Publishers/Object/ObjectObserverSubscription.swift index d2ba748..836e354 100644 --- a/Papyrus/Source/Publishers/Object/ObjectObserverSubscription.swift +++ b/Papyrus/Source/Publishers/Object/ObjectObserverSubscription.swift @@ -1,3 +1,4 @@ +#if canImport(Combine) import Combine import Foundation @@ -62,3 +63,4 @@ where T.Input == Output, } } } +#endif diff --git a/Papyrus/Source/Queries/CollectionQuery.swift b/Papyrus/Source/Queries/CollectionQuery.swift index 210ef5a..745d377 100644 --- a/Papyrus/Source/Queries/CollectionQuery.swift +++ b/Papyrus/Source/Queries/CollectionQuery.swift @@ -1,4 +1,6 @@ +#if canImport(Combine) import Combine +#endif import Foundation @@ -68,7 +70,8 @@ public class CollectionQuery where T: Papyrus { self.sort = onSort return self } - + + #if canImport(Combine) /// Observe changes to the query. /// - Returns: A publisher that emits values when /// valid objects are changed. @@ -79,7 +82,8 @@ public class CollectionQuery where T: Papyrus { .replaceError(with: []) .eraseToAnyPublisher() } - + #endif + /// Observe changes to the query. /// - Returns: A `AsyncThrowingStream` instance. public func stream() -> AsyncThrowingStream<[T], Error> { diff --git a/Papyrus/Source/Queries/ObjectQuery.swift b/Papyrus/Source/Queries/ObjectQuery.swift index 25fe4fa..7c0abe4 100644 --- a/Papyrus/Source/Queries/ObjectQuery.swift +++ b/Papyrus/Source/Queries/ObjectQuery.swift @@ -1,4 +1,6 @@ +#if canImport(Combine) import Combine +#endif import Foundation @@ -40,7 +42,8 @@ public class ObjectQuery { throw PapyrusStore.QueryError.invalidSchema(details: error) } } - + + #if canImport(Combine) /// Observe changes to the query via a publisher. /// - Returns: A publisher that emits values when /// valid objects are changed. @@ -51,6 +54,7 @@ public class ObjectQuery { ) .eraseToAnyPublisher() } + #endif /// Observe changes to the query via an async stream. /// - Returns: A `AsyncThrowingStream` instance. diff --git a/PapyrusTests/Source/Tests/CollectionObserverPublisherTests.swift b/PapyrusTests/Source/Tests/CollectionObserverPublisherTests.swift index 34b682f..5308df5 100644 --- a/PapyrusTests/Source/Tests/CollectionObserverPublisherTests.swift +++ b/PapyrusTests/Source/Tests/CollectionObserverPublisherTests.swift @@ -1,3 +1,4 @@ +#if canImport(Combine) import Combine import XCTest @testable import Papyrus @@ -105,3 +106,4 @@ final class CollectionObserverPublisherTests: XCTestCase { self.waitForExpectations(timeout: 2.0) } } +#endif diff --git a/PapyrusTests/Source/Tests/CollectionQueryTests.swift b/PapyrusTests/Source/Tests/CollectionQueryTests.swift index 02c2906..239499a 100644 --- a/PapyrusTests/Source/Tests/CollectionQueryTests.swift +++ b/PapyrusTests/Source/Tests/CollectionQueryTests.swift @@ -1,4 +1,6 @@ +#if canImport(Combine) import Combine +#endif import XCTest @testable import Papyrus @@ -7,7 +9,9 @@ import XCTest final class CollectionQueryTests: XCTestCase { private var storeDirectory: URL! private let numberOfDummyObjects = 10 + #if canImport(Combine) private var cancellables: Set! + #endif // MARK: Setup diff --git a/PapyrusTests/Source/Tests/ObjectObserverPublisherTests.swift b/PapyrusTests/Source/Tests/ObjectObserverPublisherTests.swift index f02cf45..5e683fd 100644 --- a/PapyrusTests/Source/Tests/ObjectObserverPublisherTests.swift +++ b/PapyrusTests/Source/Tests/ObjectObserverPublisherTests.swift @@ -1,3 +1,4 @@ +#if canImport(Combine) import Combine import XCTest @testable import Papyrus @@ -184,3 +185,4 @@ extension ObjectObserverPublisherTests { ) } } +#endif diff --git a/PapyrusTests/Source/Tests/ObjectQueryTests.swift b/PapyrusTests/Source/Tests/ObjectQueryTests.swift index 66b2a43..a5edd98 100644 --- a/PapyrusTests/Source/Tests/ObjectQueryTests.swift +++ b/PapyrusTests/Source/Tests/ObjectQueryTests.swift @@ -1,4 +1,6 @@ +#if canImport(Combine) import Combine +#endif import XCTest @testable import Papyrus @@ -7,7 +9,9 @@ import XCTest final class ObjectQueryTests: XCTestCase { private let fileManager = FileManager.default private var storeDirectory: URL! + #if canImport(Combine) private var cancellables: Set! + #endif // MARK: Setup diff --git a/PapyrusTests/Source/Tests/PapyrusStoreTests.swift b/PapyrusTests/Source/Tests/PapyrusStoreTests.swift index 7349b51..3098038 100644 --- a/PapyrusTests/Source/Tests/PapyrusStoreTests.swift +++ b/PapyrusTests/Source/Tests/PapyrusStoreTests.swift @@ -1,4 +1,6 @@ +#if canImport(Combine) import Combine +#endif import XCTest @testable import Papyrus @@ -8,7 +10,9 @@ final class PapyrusStoreTests: XCTestCase { private let fileManager = FileManager.default private var store: PapyrusStore! private var storeDirectory: URL! + #if canImport(Combine) private var cancellables: Set! + #endif // MARK: Setup