Skip to content

Commit

Permalink
Merge pull request #6 from narek-sv/privacy-manifest
Browse files Browse the repository at this point in the history
Privacy manifest
  • Loading branch information
narek-sv authored Apr 3, 2024
2 parents 4ae0c09 + ace0309 commit b2e0f3c
Show file tree
Hide file tree
Showing 13 changed files with 122 additions and 33 deletions.
4 changes: 2 additions & 2 deletions .github/workflows/swift.yml
Original file line number Diff line number Diff line change
Expand Up @@ -11,10 +11,10 @@ jobs:
strategy:
matrix:
os: [macos-14]
swift: ["5.9"]
swift: ["5.10"]
runs-on: ${{ matrix.os }}
steps:
- uses: swift-actions/setup-swift@v1
- uses: swift-actions/setup-swift@v2
name: Set up Swift
with:
swift-version: ${{ matrix.swift }}
Expand Down
8 changes: 5 additions & 3 deletions KeyValueStorageSwift.podspec
Original file line number Diff line number Diff line change
@@ -1,20 +1,22 @@
Pod::Spec.new do |spec|
spec.name = "KeyValueStorageSwift"
spec.version = "2.0.0"
spec.version = "2.1.0"

spec.summary = "Key-value storage written in Swift."
spec.description = "An elegant, multipurpose key-value storage, compatible with all Apple platforms."
spec.homepage = "https://github.com/narek-sv/KeyValueStorage"
spec.license = { :type => "MIT", :file => "LICENSE" }
spec.author = { "Narek Sahakyan" => "[email protected]" }

spec.swift_version = "5.9"
spec.swift_version = "5.10"
spec.ios.deployment_target = "13.0"
spec.osx.deployment_target = "10.15"
spec.watchos.deployment_target = "6.0"
spec.tvos.deployment_target = "13.0"

spec.source = { :git => "https://github.com/narek-sv/KeyValueStorage.git", :tag => "v2.0.0" }
spec.source = { :git => "https://github.com/narek-sv/KeyValueStorage.git", :tag => "v2.1.0" }
spec.source_files = "Sources/KeyValueStorage/**/*"

spec.resource_bundles = {"KeyValueStorageSwift" => ["Sources/Resources/PrivacyInfo.xcprivacy"]}

end
3 changes: 2 additions & 1 deletion Package.swift
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// swift-tools-version:5.9
// swift-tools-version:5.10
// The swift-tools-version declares the minimum version of Swift required to build this package.

import PackageDescription
Expand Down Expand Up @@ -32,6 +32,7 @@ let package = Package(
.target(
name: "KeyValueStorage",
dependencies: [],
resources: [.process("Resources/PrivacyInfo.xcprivacy")],
swiftSettings: [
.enableExperimentalFeature("StrictConcurrency"),
]),
Expand Down
23 changes: 23 additions & 0 deletions Sources/KeyValueStorage/Resources/PrivacyInfo.xcprivacy
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>NSPrivacyTracking</key>
<false/>
<key>NSPrivacyTrackingDomains</key>
<array/>
<key>NSPrivacyCollectedDataTypes</key>
<array/>
<key>NSPrivacyAccessedAPITypes</key>
<array>
<dict>
<key>NSPrivacyAccessedAPIType</key>
<string>NSPrivacyAccessedAPICategoryUserDefaults</string>
<key>NSPrivacyAccessedAPITypeReasons</key>
<array>
<string>C56D.1</string>
</array>
</dict>
</array>
</dict>
</plist>
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ extension KeyValueCodingStorageKey: Hashable {

// MARK: - Coding Storage

@CodingStorageActor
open class KeyValueCodingStorage<Storage: KeyValueDataStorage>: @unchecked Sendable, Clearing {

// MARK: Properties
Expand Down Expand Up @@ -88,14 +89,16 @@ open class KeyValueCodingStorage<Storage: KeyValueDataStorage>: @unchecked Senda
}
}

protocol Clearing {
// MARK: - Helper Protocols

protocol Clearing: Sendable {
func clear() async throws
}

// MARK: - Global Actors

@globalActor
public final class ObservableCodingStorageActor {
public final class CodingStorageActor {
public actor Actor { }
public static let shared = Actor()
}
Original file line number Diff line number Diff line change
Expand Up @@ -7,12 +7,12 @@

import Combine

@ObservableCodingStorageActor
@CodingStorageActor
private final class KeyValueObservations {
fileprivate static var observations = [AnyHashable?: [AnyHashable: Any]]()
}

@ObservableCodingStorageActor
@CodingStorageActor
open class KeyValueObservableStorage<Storage: KeyValueDataStorage>: KeyValueCodingStorage<Storage>, @unchecked Sendable {

// MARK: Observations
Expand Down
16 changes: 8 additions & 8 deletions Sources/KeyValueStorage/UnifiedStorage.swift
Original file line number Diff line number Diff line change
Expand Up @@ -41,12 +41,12 @@ extension UnifiedStorageKey: Hashable {

// MARK: - Unified Storage Factory

public protocol UnifiedStorageFactory {
public protocol UnifiedStorageFactory: Sendable {
func dataStorage<Storage: KeyValueDataStorage>(for domain: Storage.Domain?) async throws -> Storage
func codingStorage<Storage: KeyValueDataStorage>(for storage: Storage) throws -> KeyValueCodingStorage<Storage>
func codingStorage<Storage: KeyValueDataStorage>(for storage: Storage) async throws -> KeyValueCodingStorage<Storage>
}

open class DefaultUnifiedStorageFactory: UnifiedStorageFactory {
open class DefaultUnifiedStorageFactory: UnifiedStorageFactory, @unchecked Sendable {
public func dataStorage<Storage: KeyValueDataStorage>(for domain: Storage.Domain?) async throws -> Storage {
if let domain {
return try await Storage(domain: domain)
Expand All @@ -55,14 +55,14 @@ open class DefaultUnifiedStorageFactory: UnifiedStorageFactory {
return try await Storage()
}

public func codingStorage<Storage: KeyValueDataStorage>(for storage: Storage) throws -> KeyValueCodingStorage<Storage> {
KeyValueCodingStorage(storage: storage)
public func codingStorage<Storage: KeyValueDataStorage>(for storage: Storage) async throws -> KeyValueCodingStorage<Storage> {
await KeyValueCodingStorage(storage: storage)
}
}

public final class ObservableUnifiedStorageFactory: DefaultUnifiedStorageFactory {
public override func codingStorage<Storage: KeyValueDataStorage>(for storage: Storage) throws -> KeyValueCodingStorage<Storage> {
KeyValueObservableStorage(storage: storage)
public override func codingStorage<Storage: KeyValueDataStorage>(for storage: Storage) async throws -> KeyValueCodingStorage<Storage> {
await KeyValueObservableStorage(storage: storage)
}
}

Expand Down Expand Up @@ -157,7 +157,7 @@ public actor UnifiedStorage {
}

let dataStorage: Storage = try await factory.dataStorage(for: domain)
let codingStorage = try factory.codingStorage(for: dataStorage)
let codingStorage = try await factory.codingStorage(for: dataStorage)
storages[underlyingKey] = codingStorage


Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,6 @@ import XCTest
import Foundation
@testable import KeyValueStorage

@FileActor
final class FileStorageTests: XCTestCase {
static let otherStorageDomain = "other"
var fileManager = FileManager.default
Expand All @@ -18,6 +17,7 @@ final class FileStorageTests: XCTestCase {
var standardStorage: FileStorage!
var otherStorage: FileStorage!

@FileActor
override func setUpWithError() throws {
let id = Bundle.main.bundleIdentifier!
standardPath = fileManager.urls(for: .documentDirectory, in: .userDomainMask)[0].appendingPathComponent(id, isDirectory: true)
Expand All @@ -32,11 +32,13 @@ final class FileStorageTests: XCTestCase {
otherStorage = try FileStorage(domain: Self.otherStorageDomain)
}

@FileActor
func testFileDomain() {
XCTAssertEqual(standardStorage.domain, nil)
XCTAssertEqual(otherStorage.domain, Self.otherStorageDomain)
}

@FileActor
func testFileFetch() throws {
// Given
let data1 = Data([0xAA, 0xBB, 0xCC])
Expand Down Expand Up @@ -105,6 +107,7 @@ final class FileStorageTests: XCTestCase {
XCTAssertNil(fetched2)
}

@FileActor
func testFileFetchDifferentDomains() throws {
// Given
let data1 = Data([0xAA, 0xBB, 0xCC])
Expand Down Expand Up @@ -173,6 +176,7 @@ final class FileStorageTests: XCTestCase {
XCTAssertNil(fetched2)
}

@FileActor
func testFileSave() throws {
// Given
let data1 = Data([0xAA, 0xBB, 0xCC])
Expand Down Expand Up @@ -207,6 +211,7 @@ final class FileStorageTests: XCTestCase {
XCTAssertEqual(fileManager.contents(atPath: filePath2), data1)
}

@FileActor
func testFileSaveDifferentDomains() throws {
// Given
let data1 = Data([0xAA, 0xBB, 0xCC])
Expand Down Expand Up @@ -237,6 +242,7 @@ final class FileStorageTests: XCTestCase {
XCTAssertEqual(fileManager.contents(atPath: filePath2), data2)
}

@FileActor
func testFileDelete() throws {
// Given
let data1 = Data([0xAA, 0xBB, 0xCC])
Expand Down Expand Up @@ -273,6 +279,7 @@ final class FileStorageTests: XCTestCase {
XCTAssertNil(fileManager.contents(atPath: filePath2))
}

@FileActor
func testFileDeleteDifferentDomains() throws {
// Given
let data1 = Data([0xAA, 0xBB, 0xCC])
Expand Down Expand Up @@ -305,6 +312,7 @@ final class FileStorageTests: XCTestCase {
XCTAssertNil(fileManager.contents(atPath: filePath2))
}

@FileActor
func testFileSet() throws {
// Given
let data1 = Data([0xAA, 0xBB, 0xCC])
Expand Down Expand Up @@ -345,6 +353,7 @@ final class FileStorageTests: XCTestCase {
XCTAssertNil(fileManager.contents(atPath: filePath2))
}

@FileActor
func testFileSetDifferentDomains() throws {
// Given
let data1 = Data([0xAA, 0xBB, 0xCC])
Expand Down Expand Up @@ -384,6 +393,7 @@ final class FileStorageTests: XCTestCase {
XCTAssertNil(fileManager.contents(atPath: filePath2))
}

@FileActor
func testFileClear() throws {
// Given
let data1 = Data([0xAA, 0xBB, 0xCC])
Expand Down Expand Up @@ -438,6 +448,7 @@ final class FileStorageTests: XCTestCase {
XCTAssertNil(fileManager.contents(atPath: filePath22))
}

@FileActor
func testErrorCaseDelete() {
// Given
let mock = FileManagerMock()
Expand Down Expand Up @@ -482,6 +493,7 @@ final class FileStorageTests: XCTestCase {
}
}

@FileActor
func testErrorCaseSave() {
// Given
let mock = FileManagerMock()
Expand Down Expand Up @@ -548,6 +560,7 @@ final class FileStorageTests: XCTestCase {
}
}

@FileActor
func testThreadSafety() throws {
// Given
let iterations = 5000
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,24 +9,26 @@ import XCTest
import Foundation
@testable import KeyValueStorage

@InMemoryActor
final class InMemoryStorageTests: XCTestCase {
static let otherStorageDomain = "other"
var standardStorage: InMemoryStorage!
var otherStorage: InMemoryStorage!

@InMemoryActor
override func setUp() {
standardStorage = InMemoryStorage()
otherStorage = InMemoryStorage(domain: Self.otherStorageDomain)

InMemoryStorage.container = [:]
}

@InMemoryActor
func testInMemoryDomain() {
XCTAssertEqual(standardStorage.domain, nil)
XCTAssertEqual(otherStorage.domain, Self.otherStorageDomain)
}

@InMemoryActor
func testInMemoryFetch() {
// Given
let data1 = Data([0xAA, 0xBB, 0xCC])
Expand Down Expand Up @@ -88,6 +90,7 @@ final class InMemoryStorageTests: XCTestCase {
XCTAssertNil(fetched2)
}

@InMemoryActor
func testInMemoryFetchDifferentDomains() {
// Given
let data1 = Data([0xAA, 0xBB, 0xCC])
Expand Down Expand Up @@ -148,6 +151,7 @@ final class InMemoryStorageTests: XCTestCase {
XCTAssertNil(fetched2)
}

@InMemoryActor
func testInMemorySave() {
// Given
let data1 = Data([0xAA, 0xBB, 0xCC])
Expand Down Expand Up @@ -177,6 +181,7 @@ final class InMemoryStorageTests: XCTestCase {
XCTAssertEqual(InMemoryStorage.container[nil]?[key2], data1)
}

@InMemoryActor
func testInMemorySaveDifferentDomains() {
// Given
let data1 = Data([0xAA, 0xBB, 0xCC])
Expand Down Expand Up @@ -205,6 +210,7 @@ final class InMemoryStorageTests: XCTestCase {
XCTAssertEqual(InMemoryStorage.container["other"]?[key], data2)
}

@InMemoryActor
func testInMemoryDelete() {
// Given
let data1 = Data([0xAA, 0xBB, 0xCC])
Expand Down Expand Up @@ -235,6 +241,7 @@ final class InMemoryStorageTests: XCTestCase {
XCTAssertNil(InMemoryStorage.container[nil]?[key2])
}

@InMemoryActor
func testInMemoryDeleteDifferentDomains() {
// Given
let data1 = Data([0xAA, 0xBB, 0xCC])
Expand Down Expand Up @@ -264,6 +271,7 @@ final class InMemoryStorageTests: XCTestCase {
XCTAssertNil(InMemoryStorage.container["other"]?[key])
}

@InMemoryActor
func testInMemorySet() {
// Given
let data1 = Data([0xAA, 0xBB, 0xCC])
Expand Down Expand Up @@ -301,6 +309,7 @@ final class InMemoryStorageTests: XCTestCase {
XCTAssertNil(InMemoryStorage.container[nil]?[key2])
}

@InMemoryActor
func testInMemorySetDifferentDomains() {
// Given
let data1 = Data([0xAA, 0xBB, 0xCC])
Expand Down Expand Up @@ -337,6 +346,7 @@ final class InMemoryStorageTests: XCTestCase {
XCTAssertNil(InMemoryStorage.container["other"]?[key])
}

@InMemoryActor
func testInMemoryClear() {
// Given
let data1 = Data([0xAA, 0xBB, 0xCC])
Expand Down Expand Up @@ -379,6 +389,7 @@ final class InMemoryStorageTests: XCTestCase {
XCTAssertEqual(InMemoryStorage.container["other"], [:])
}

@InMemoryActor
func testThreadSafety() {
// Given
let iterations = 5000
Expand Down
Loading

0 comments on commit b2e0f3c

Please sign in to comment.