diff --git a/README.md b/README.md index cbe98b92..a126df00 100644 --- a/README.md +++ b/README.md @@ -470,7 +470,7 @@ Articles on brightdigit.com: [Rebuilding MistKit with Claude Code, part 1](https ### CloudKit as Your Backend (talk) -*From iOS to Server-Side Swift* — given in 2026 at Swift Craft, Swift Rockies, and iOSDevUK by Leo Dion ([@leogdion@c.im](https://c.im/@leogdion)). The full article, following the slide order with screenshots and code from this repository, is in the DocC catalog: **[CloudKit as Your Backend](https://swiftpackageindex.com/brightdigit/MistKit/~/documentation/mistkit/cloudkitasyourbackend)** (source: [`CloudKitAsYourBackend.md`](Sources/MistKit/Documentation.docc/CloudKitAsYourBackend.md)). +*From iOS to Server-Side Swift* — given in 2026 at Swift Craft and iOSDevUK by Leo Dion ([@leogdion@c.im](https://c.im/@leogdion)). The full article, following the slide order with screenshots and code from this repository, is in the DocC catalog: **[CloudKit as Your Backend](https://swiftpackageindex.com/brightdigit/MistKit/~/documentation/mistkit/cloudkitasyourbackend)** (source: [`CloudKitAsYourBackend.md`](Sources/MistKit/Documentation.docc/CloudKitAsYourBackend.md)). > CloudKit has excellent documentation for iOS and macOS client development. But backend services — podcast aggregation, RSS readers, data processing — face APIs that Apple barely documents. I rebuilt a comprehensive CloudKit library using AI-generated OpenAPI specifications. The result: type-safe Swift code supporting three authentication methods (server-to-server, web authentication token, and API token), typed error handling, and production deployments. @@ -588,126 +588,6 @@ MistKit is released under the MIT License. See [LICENSE](LICENSE) for details. ## Roadmap -### v1.0.0-alpha.1 - -- [x] [Composing Web Service Requests](https://github.com/brightdigit/MistKit/issues/111) ✅ -- [x] [Modifying Records (records/modify)](https://github.com/brightdigit/MistKit/issues/114) ✅ -- [x] [Fetching Records Using a Query (records/query)](https://github.com/brightdigit/MistKit/issues/114) ✅ -- [x] [Fetching Records by Record Name (records/lookup)](https://github.com/brightdigit/MistKit/issues/114) ✅ -- [x] [Fetching Current User Identity (users/caller)](https://github.com/brightdigit/MistKit/issues/114) ✅ - -### v1.0.0-alpha.2 - -- [x] [Vapor Token Client](https://github.com/brightdigit/MistKit/issues/113) ✅ -- [x] [Vapor Token Storage](https://github.com/brightdigit/MistKit/issues/113) ✅ -- [x] [Vapor URL Client](https://github.com/brightdigit/MistKit/issues/113) ✅ -- [x] [Swift NIO URL Client](https://github.com/brightdigit/MistKit/issues/113) ✅ -- [x] [Date Field Types](https://github.com/brightdigit/MistKit/issues/110) ✅ -- [x] [Location Field Types](https://github.com/brightdigit/MistKit/issues/110) ✅ -- [x] [List Field Types](https://github.com/brightdigit/MistKit/issues/110) ✅ -- [x] [Reference Field Types](https://github.com/brightdigit/MistKit/issues/110) ✅ -- [x] [Error Codes](https://github.com/brightdigit/MistKit/issues/115) ✅ -- [x] [Fetching Zones (zones/list)](https://github.com/brightdigit/MistKit/issues/116) ✅ - -### v1.0.0-alpha.3 - -- [x] [Uploading Assets (assets/upload)](https://github.com/brightdigit/MistKit/issues/30) ✅ -- [x] [Add Support for swiftlang/swift-source-compat-suite](https://github.com/brightdigit/MistKit/issues/185) ✅ - -### v1.0.0-alpha.4 - -- [x] [Uploading Assets (assets/upload)](https://github.com/brightdigit/MistKit/issues/30) ✅ -- [x] [Add Support for swiftlang/swift-source-compat-suite](https://github.com/brightdigit/MistKit/issues/185) ✅ -- [x] [MistDemo - Web Authentication Demo](https://github.com/brightdigit/MistKit/pull/227) ✅ -- [x] [WASM Platform Support](https://github.com/brightdigit/MistKit/pull/206) ✅ -- [x] [Android Platform Support](https://github.com/brightdigit/MistKit/pull/189) ✅ - -### v1.0.0-alpha.5 - -- [x] [Name Component Types](https://github.com/brightdigit/MistKit/issues/26) ✅ -- [x] [Discovering User Identities (POST users/discover)](https://github.com/brightdigit/MistKit/issues/27) ✅ -- [x] [Fetching Record Changes (records/changes)](https://github.com/brightdigit/MistKit/issues/40) ✅ -- [x] [Fetching Zones by Identifier (zones/lookup)](https://github.com/brightdigit/MistKit/issues/44) ✅ -- [x] [Fetching Zone Changes (zones/changes)](https://github.com/brightdigit/MistKit/issues/48) ✅ *(Apple-deprecated — prefer `fetchDatabaseChanges`)* -- [x] [Fix QueryFilter IN/NOT_IN serialization](https://github.com/brightdigit/MistKit/issues/192) ✅ - -### v1.0.0-beta.1 - -**Querying & Sync** -- [x] Query pagination with continuation markers ([#306](https://github.com/brightdigit/MistKit/pull/306)) ✅ -- [x] Operation classification & batch sync result tracking ([#296](https://github.com/brightdigit/MistKit/pull/296)) ✅ - -**Authentication** -- [x] `AuthenticationMiddleware` refactor — each `Authenticator` applies itself ([#294](https://github.com/brightdigit/MistKit/pull/294)) ✅ -- [x] Strengthened environment & database configuration validation ([#293](https://github.com/brightdigit/MistKit/pull/293)) ✅ - -**Error Handling** -- [x] Typed `TokenManagerError` and safe `RecordOperation` conversion ([#305](https://github.com/brightdigit/MistKit/pull/305)) ✅ -- [x] Move `CloudKitResponseType` defaults to protocol extension ([#292](https://github.com/brightdigit/MistKit/pull/292)) ✅ - -**Concurrency** -- [x] Replace custom `AsyncChannel` with `swift-async-algorithms` ([#280](https://github.com/brightdigit/MistKit/pull/280)) ✅ - -**MistDemo** -- [x] `--database` flag and `demo-errors` command ([#282](https://github.com/brightdigit/MistKit/pull/282)) ✅ -- [x] Test split, CRUD commands, auth fix, native app ([#271](https://github.com/brightdigit/MistKit/pull/271) / [#273](https://github.com/brightdigit/MistKit/pull/273)) ✅ -- [x] `IntegrationTestRunner` refactored into protocol-based phase pipeline ([#283](https://github.com/brightdigit/MistKit/pull/283)) ✅ - -**Tooling & CI** -- [x] Test suite improvements ([#286](https://github.com/brightdigit/MistKit/pull/286) / [#287](https://github.com/brightdigit/MistKit/pull/287)) ✅ -- [x] CI updates for May 2026 ([#277](https://github.com/brightdigit/MistKit/pull/277)) ✅ -- [x] Fail lint job when any command fails ([#303](https://github.com/brightdigit/MistKit/pull/303)) ✅ - -### v1.0.0-beta.2 - -- [x] [Referencing Existing Assets (assets/rereference)](https://github.com/brightdigit/MistKit/issues/31) ✅ -- [x] [Modifying Zones (zones/modify)](https://github.com/brightdigit/MistKit/issues/45) ✅ -- [x] [Fetching Subscriptions (subscriptions/list)](https://github.com/brightdigit/MistKit/issues/49) ✅ -- [x] [Fetching Subscriptions by Identifier (subscriptions/lookup)](https://github.com/brightdigit/MistKit/issues/50) ✅ -- [x] [Modifying Subscriptions (subscriptions/modify)](https://github.com/brightdigit/MistKit/issues/51) ✅ -- [x] [Creating APNs Tokens (tokens/create)](https://github.com/brightdigit/MistKit/issues/52) ✅ -- [x] [Registering Tokens (tokens/register)](https://github.com/brightdigit/MistKit/issues/53) ✅ -- [x] [Fetching Users by Email (users/lookup/email)](https://github.com/brightdigit/MistKit/issues/34) ✅ *(Apple-deprecated — prefer `discoverAllUserIdentities`)* -- [x] [Fetching Users by Record Name (users/lookup/id)](https://github.com/brightdigit/MistKit/issues/35) ✅ *(Apple-deprecated — prefer `discoverAllUserIdentities`)* -- [x] Auto-chunking conveniences for batch operations ([#389](https://github.com/brightdigit/MistKit/pull/389)) ✅ - -### v1.0.0-beta.4 - -- [x] [Fetching Record Information (records/resolve)](https://github.com/brightdigit/MistKit/issues/41) ✅ -- [x] [Accepting Share Records (records/accept)](https://github.com/brightdigit/MistKit/issues/42) ✅ -- [x] [Curated createShare for share URL creation](https://github.com/brightdigit/MistKit/issues/437) ✅ -- [x] [Fetching Database Changes (changes/database)](https://github.com/brightdigit/MistKit/issues/46) ✅ -- [x] [Fetching Record Zone Changes (changes/zone)](https://github.com/brightdigit/MistKit/issues/47) ✅ -- [x] [Clarify change-tracking endpoint coverage](https://github.com/brightdigit/MistKit/issues/401) ✅ *(deprecates `zones/changes` in favor of `changes/database`)* -- [x] [Add custom CloudKit zone support for queries](https://github.com/brightdigit/MistKit/issues/146) ✅ - -### v1.0.0-beta.5 - -- [x] [Zone payloads: `deleted`, `zoneType`, and `ownerRecordName` decoding](https://github.com/brightdigit/MistKit/issues/444) ✅ -- [x] [Zone-aware writes (CRUD + assets)](https://github.com/brightdigit/MistKit/issues/454) ✅ -- [x] [Consume web auth token rotation (`X-Apple-CloudKit-Web-Auth-Token`)](https://github.com/brightdigit/MistKit/issues/462) ✅ -- [x] [Add `Asset.download(using:)`](https://github.com/brightdigit/MistKit/issues/466) ✅ — checksum verification turned out to be impossible: `fileChecksum` is an opaque server-minted token ([#473](https://github.com/brightdigit/MistKit/pull/473)) -- [x] [Change `FieldValue.bytes` from `String` to `Data`](https://github.com/brightdigit/MistKit/issues/467) ✅ -- [x] [Add `VALIDATE` to `Reference.Action`](https://github.com/brightdigit/MistKit/issues/464) ✅ -- [x] [MistDemo web UI: `zoneName`/`zoneOwner` inputs on the query panel](https://github.com/brightdigit/MistKit/issues/438) ✅ -- [x] [Create `MistKitConfiguration` package for shared CloudKit config glue](https://github.com/brightdigit/MistKit/issues/407) ✅ -- [x] [Complete iOSDevUK talk material — talk article and guides in DocC, `docs/` removed](https://github.com/brightdigit/MistKit/issues/447) ✅ - -### Backlog / Post-beta - -- [ ] [Discovering All User Identities (GET users/discover)](https://github.com/brightdigit/MistKit/issues/28) -- [ ] [Fetching Contacts (users/lookup/contacts)](https://github.com/brightdigit/MistKit/issues/33) - -### v1.0.0 - -- [ ] [System Field Integration](https://github.com/brightdigit/MistKit/issues/116) -- [ ] [Handle Data Size Limits](https://github.com/brightdigit/MistKit/issues/38) -- [ ] [Add architecture diagrams to Bushel documentation](https://github.com/brightdigit/MistKit/issues/140) -- [ ] [Add comprehensive test suite for Bushel demo](https://github.com/brightdigit/MistKit/issues/136) -- [ ] [Implement incremental sync with change tracking for Bushel](https://github.com/brightdigit/MistKit/issues/137) -- [ ] [Migrate Bushel Demo to it's own Repository](https://github.com/brightdigit/MistKit/issues/183) -- [ ] [Migrate Celestra Demo to it's own Repository](https://github.com/brightdigit/MistKit/issues/184) - ### v1.1.0 - [ ] [Add CloudKit Schema Management APIs (cktool/cktooljs functionality)](https://github.com/brightdigit/MistKit/issues/135) diff --git a/Sources/MistKit/Documentation.docc/CloudKitAsYourBackend.md b/Sources/MistKit/Documentation.docc/CloudKitAsYourBackend.md index 75819c77..dd32510f 100644 --- a/Sources/MistKit/Documentation.docc/CloudKitAsYourBackend.md +++ b/Sources/MistKit/Documentation.docc/CloudKitAsYourBackend.md @@ -6,12 +6,32 @@ From iOS to server-side Swift — the talk behind MistKit, consolidated into one CloudKit is great for iOS apps. How about backend services? This article is the written form of a conference talk by Leo Dion ([@leogdion@c.im](https://c.im/@leogdion)) that walks from "what is CloudKit" to a scheduled GitHub Actions job writing to a CloudKit public database from a stock Ubuntu runner, and explains the three problems that shaped MistKit along the way: authentication, field-type polymorphism, and error handling. -The talk was given in 2026 at Swift Craft, Swift Rockies (Calgary), and iOSDevUK (Aberystwyth). The abstract: +The talk was given in 2026 at Swift Craft and iOSDevUK (Aberystwyth). The abstract: > CloudKit has excellent documentation for iOS and macOS client development. But backend services — podcast aggregation, RSS readers, data processing — face APIs that Apple barely documents. I rebuilt a comprehensive CloudKit library using AI-generated OpenAPI specifications. The result: type-safe Swift code supporting three authentication methods (server-to-server, web authentication token, and API token), typed error handling, and production deployments. The sections below follow the slide order. Every code sample is taken from the current MistKit source or its example projects, so the article stays accurate as the library evolves. A complete list of the links shown during the talk is at the end, in . +## Table of Contents + +- [Overview](#overview) +- [What is CloudKit](#what-is-cloudkit) +- [What is CloudKit Web Services](#what-is-cloudkit-web-services) +- [Why server-side CloudKit](#why-server-side-cloudkit) + - [Private database: Heartwitch](#private-database-heartwitch) + - [Public database: Bushel](#public-database-bushel) +- [Building MistKit](#building-mistkit) +- [Authentication](#authentication) + - [API token](#api-token) + - [Web auth token](#web-auth-token) + - [Server to server](#server-to-server) +- [Field type polymorphism](#field-type-polymorphism) +- [Error handling](#error-handling) +- [Deployment](#deployment) +- [What's next](#whats-next) +- [Links](#links) +- [Questions](#questions) + ## What is CloudKit Travel back to WWDC 2014 — the year Swift was introduced — and you also find the introduction of CloudKit. The idea was simple: give iOS developers a backend for storage, logic, database, search, and notifications without running a server. diff --git a/Tests/MistKitTests/CloudKitService/SizeLimits/CloudKitServiceTests.SizeLimits+Records.swift b/Tests/MistKitTests/CloudKitService/SizeLimits/CloudKitServiceTests.SizeLimits+Records.swift index a59f48ed..8bb9a688 100644 --- a/Tests/MistKitTests/CloudKitService/SizeLimits/CloudKitServiceTests.SizeLimits+Records.swift +++ b/Tests/MistKitTests/CloudKitService/SizeLimits/CloudKitServiceTests.SizeLimits+Records.swift @@ -54,7 +54,9 @@ extension CloudKitServiceTests.SizeLimits { ) } - @Test("modifyRecords enriches QUOTA_EXCEEDED with recordExceedsSizeLimit hint") + @Test( + "modifyRecords enriches QUOTA_EXCEEDED with recordExceedsSizeLimit hint", + .disabled(if: Platform.isWasm)) internal func recordHintAttachedOnOversizedBatch() async throws { let service = try Self.makeService()