Skip to content

brightdigit/MistKit

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

85 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

MistKit Logo

MistKit

SwiftPM Swift Versions Platforms License GitHub Workflow Status Codecov CodeFactor Grade Maintainability Documentation

A Swift Package for Server-Side and Command-Line Access to CloudKit Web Services

Overview

MistKit provides a modern Swift interface to CloudKit Web Services REST API, enabling cross-platform CloudKit access for server-side Swift applications, command-line tools, and platforms where the CloudKit framework isn't available.

Built with Swift concurrency (async/await) and designed for modern Swift applications, MistKit supports all three CloudKit authentication methods and provides type-safe access to CloudKit operations.

Key Features

  • 🌍 Cross-Platform Support: Works on macOS, iOS, tvOS, watchOS, visionOS, and Linux
  • ⚡ Modern Swift: Built with Swift 6 concurrency features and structured error handling
  • 🔐 Multiple Authentication Methods: API token, web authentication, and server-to-server authentication
  • 🛡️ Type-Safe: Comprehensive type safety with Swift's type system
  • 📋 OpenAPI-Based: Generated from CloudKit Web Services OpenAPI specification
  • 🔒 Secure: Built-in security best practices and credential management

Installation

Swift Package Manager

Add MistKit to your Package.swift file:

dependencies: [
    .package(url: "https://github.com/brightdigit/MistKit.git", from: "1.0.0-alpha.1")
]

Or add it through Xcode:

  1. File → Add Package Dependencies
  2. Enter: https://github.com/brightdigit/MistKit.git
  3. Select version and add to your target

Quick Start

1. Choose Your Authentication Method

MistKit supports three authentication methods depending on your use case:

API Token (Container-level access)

import MistKit

let service = try CloudKitService(
    containerIdentifier: "iCloud.com.example.MyApp",
    apiToken: ProcessInfo.processInfo.environment["CLOUDKIT_API_TOKEN"]!
)

Web Authentication (User-specific access)

let service = try CloudKitService(
    containerIdentifier: "iCloud.com.example.MyApp",
    apiToken: ProcessInfo.processInfo.environment["CLOUDKIT_API_TOKEN"]!,
    webAuthToken: userWebAuthToken
)

Server-to-Server (Enterprise access, public database only)

let serverManager = try ServerToServerAuthManager(
    keyIdentifier: ProcessInfo.processInfo.environment["CLOUDKIT_KEY_ID"]!,
    privateKeyData: privateKeyData
)

let service = try CloudKitService(
    containerIdentifier: "iCloud.com.example.MyApp",
    tokenManager: serverManager,
    environment: .production,
    database: .public
)

2. Create CloudKit Service

do {
    let service = try CloudKitService(
        containerIdentifier: "iCloud.com.example.MyApp",
        apiToken: ProcessInfo.processInfo.environment["CLOUDKIT_API_TOKEN"]!
    )
    // Use service for CloudKit operations
} catch {
    print("Failed to create service: \\(error)")
}

Authentication Setup

API Token Authentication

  1. Get API Token:

  2. Set Environment Variable:

    export CLOUDKIT_API_TOKEN="your_api_token_here"
  3. Use in Code:

    let service = try CloudKitService(
        containerIdentifier: "iCloud.com.example.MyApp",
        apiToken: ProcessInfo.processInfo.environment["CLOUDKIT_API_TOKEN"]!
    )

Web Authentication

Web authentication enables user-specific operations and requires both an API token and a web authentication token obtained through CloudKit JS authentication.

let service = try CloudKitService(
    containerIdentifier: "iCloud.com.example.MyApp",
    apiToken: apiToken,
    webAuthToken: webAuthToken
)

Server-to-Server Authentication

Server-to-server authentication provides enterprise-level access using ECDSA P-256 key signing. Note that this method only supports the public database.

  1. Generate Key Pair:

    # Generate private key
    openssl ecparam -genkey -name prime256v1 -noout -out private_key.pem
    
    # Extract public key
    openssl ec -in private_key.pem -pubout -out public_key.pem
  2. Upload Public Key: Upload the public key to Apple Developer Console

  3. Use in Code:

    let privateKeyData = try Data(contentsOf: URL(fileURLWithPath: "private_key.pem"))
    
    let serverManager = try ServerToServerAuthManager(
        keyIdentifier: "your_key_id",
        privateKeyData: privateKeyData
    )
    
    let service = try CloudKitService(
        containerIdentifier: "iCloud.com.example.MyApp",
        tokenManager: serverManager,
        environment: .production,
        database: .public
    )

Platform Support

Minimum Platform Versions

Platform Minimum Version Server-to-Server Auth
macOS 10.15+ 11.0+
iOS 13.0+ 14.0+
tvOS 13.0+ 14.0+
watchOS 6.0+ 7.0+
visionOS 1.0+ 1.0+
Linux Ubuntu 18.04+
Windows 10+

Error Handling

MistKit provides comprehensive error handling with typed errors:

do {
    let service = try CloudKitService(
        containerIdentifier: "iCloud.com.example.MyApp",
        apiToken: apiToken
    )
    // Perform operations
} catch let error as CloudKitError {
    print("CloudKit error: \\(error.localizedDescription)")
} catch let error as TokenManagerError {
    print("Authentication error: \\(error.localizedDescription)")
} catch {
    print("Unexpected error: \\(error)")
}

Error Types

  • CloudKitError: CloudKit Web Services API errors
  • TokenManagerError: Authentication and credential errors
  • TokenStorageError: Token storage and persistence errors

Security Best Practices

Environment Variables

Always store sensitive credentials in environment variables:

# .env file (never commit this!)
CLOUDKIT_API_TOKEN=your_api_token_here
CLOUDKIT_KEY_ID=your_key_id_here

Secure Logging

MistKit automatically masks sensitive information in logs:

// Sensitive data is automatically redacted in log output
print("Token: \\(secureToken)") // Outputs: Token: abc12345***

Token Storage

For persistent applications, use secure token storage:

let storage = InMemoryTokenStorage() // For development
// Use KeychainTokenStorage() for production (implement as needed)

let tokenManager = WebAuthTokenManager(
    apiToken: apiToken,
    webAuthToken: webAuthToken,
    storage: storage
)

let service = try CloudKitService(
    containerIdentifier: "iCloud.com.example.MyApp",
    tokenManager: tokenManager,
    environment: .development,
    database: .private
)

Advanced Usage

Using AsyncHTTPClient Transport

For server-side applications, MistKit can use swift-openapi-async-http-client as the underlying HTTP transport. This is particularly useful for server-side Swift applications that need robust HTTP client capabilities.

import MistKit
import OpenAPIAsyncHTTPClient

// Create an AsyncHTTPClient instance
let httpClient = HTTPClient(eventLoopGroupProvider: .createNew)

// Create the transport
let transport = AsyncHTTPClientTransport(client: httpClient)

// Use with CloudKit service
let service = try CloudKitService(
    containerIdentifier: "iCloud.com.example.MyApp",
    apiToken: apiToken,
    transport: transport
)

// Don't forget to shutdown the client when done
defer {
    try? httpClient.syncShutdown()
}

Benefits

  • Production Ready: AsyncHTTPClient is battle-tested in server environments
  • Performance: Optimized for high-throughput server applications
  • Configuration: Extensive configuration options for timeouts, connection pooling, and more
  • Platform Support: Works across all supported platforms including Linux

Adaptive Token Manager

For applications that might upgrade from API-only to web authentication:

let adaptiveManager = AdaptiveTokenManager(
    apiToken: apiToken,
    storage: storage
)

// Later, upgrade to web authentication
try await adaptiveManager.upgradeToWebAuth(webAuthToken: webToken)

Examples

Check out the Examples/ directory for complete working examples:

  • Command Line Tool: Basic CloudKit operations from the command line
  • Server Application: Using MistKit in a server-side Swift application
  • Cross-Platform App: Shared CloudKit logic across multiple platforms

Documentation

Requirements

  • Swift 6.1+
  • Xcode 16.0+ (for iOS/macOS development)
  • Linux: Ubuntu 18.04+ with Swift 6.1+

License

MistKit is released under the MIT License. See LICENSE for details.

Acknowledgments

Roadmap

v0.2.4

Current Version

v1.0.0

Support


MistKit: Bringing CloudKit to every Swift platform 🌟

About

Swift Package for Server-Side and Command-Line Access to CloudKit Web Services

Topics

Resources

License

Stars

Watchers

Forks

Packages

 
 
 

Contributors 4

  •  
  •  
  •  
  •  

Languages