{"id":21169142,"url":"https://github.com/cosmicjs/cosmic-sdk-swift","last_synced_at":"2026-03-04T15:01:29.510Z","repository":{"id":195976021,"uuid":"694073713","full_name":"cosmicjs/cosmic-sdk-swift","owner":"cosmicjs","description":"A pure Swift interpretation of the Cosmic JavaScript SDK for use in Swift and SwiftUI projects.","archived":false,"fork":false,"pushed_at":"2025-12-04T18:35:59.000Z","size":217,"stargazers_count":7,"open_issues_count":0,"forks_count":1,"subscribers_count":1,"default_branch":"main","last_synced_at":"2025-12-08T02:04:56.741Z","etag":null,"topics":["cosmicjs","headless-cms","swift","swiftui"],"latest_commit_sha":null,"homepage":"https://www.cosmicjs.com","language":"Swift","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/cosmicjs.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2023-09-20T09:24:39.000Z","updated_at":"2025-12-04T18:36:04.000Z","dependencies_parsed_at":"2023-09-22T19:21:30.338Z","dependency_job_id":"491238b0-c276-41e6-aef7-a3327e3d3fac","html_url":"https://github.com/cosmicjs/cosmic-sdk-swift","commit_stats":null,"previous_names":["cosmicjs/cosmicsdkswift","cosmicjs/cosmic-sdk-swift"],"tags_count":1,"template":false,"template_full_name":null,"purl":"pkg:github/cosmicjs/cosmic-sdk-swift","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/cosmicjs%2Fcosmic-sdk-swift","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/cosmicjs%2Fcosmic-sdk-swift/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/cosmicjs%2Fcosmic-sdk-swift/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/cosmicjs%2Fcosmic-sdk-swift/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/cosmicjs","download_url":"https://codeload.github.com/cosmicjs/cosmic-sdk-swift/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/cosmicjs%2Fcosmic-sdk-swift/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":30084685,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-03-04T13:22:36.021Z","status":"ssl_error","status_checked_at":"2026-03-04T13:20:45.750Z","response_time":59,"last_error":"SSL_read: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["cosmicjs","headless-cms","swift","swiftui"],"created_at":"2024-11-20T15:24:16.356Z","updated_at":"2026-03-04T15:01:29.475Z","avatar_url":"https://github.com/cosmicjs.png","language":"Swift","funding_links":[],"categories":[],"sub_categories":[],"readme":"\u003ca href=\"https://app.cosmicjs.com/signup\"\u003e\n  \u003cimg src=\"https://imgix.cosmicjs.com/7d4c82a0-589d-11ee-8d99-6566412c38cc-GitHub.png?mask=corners\u0026w=2000\u0026auto=format\u0026corner-radius=24,24,24,24\" alt=\"Cosmic dashboard darkmode\" /\u003e\n\u003c/a\u003e\n\n# CosmicSDKSwift\n\nA pure Swift interpretation of the Cosmic SDK for use in Swift and SwiftUI projects.\n\n## About this project\n\nThis project is heavily inspired by our [JavaScript SDK](https://github.com/cosmicjs/cosmic-sdk-js) and [Adam Rushy's OpenAISwift](https://github.com/adamrushy/OpenAISwift/tree/main).\n\nHaving built multiple Cosmic-powered SwiftUI apps, it felt time to provide a smart SDK that mapped as closely to our JavaScript SDK without moving away from common Swift conventions.\n\n[Cosmic](https://www.cosmicjs.com/) is a [headless CMS](https://www.cosmicjs.com/headless-cms) (content management system) that provides a web dashboard to create content and an API toolkit to deliver content to any website or application. Nearly any type of content can be built using the dashboard and delivered using this SDK.\n\n[Get started free →](https://app.cosmicjs.com/signup)\n\n## Install\n\n### Swift Package Manager\n\nYou can use Swift Package Manager to integrate the SDK by adding the following dependency in the `Package.swift` file or by adding it directly within Xcode.\n\n`.package(url: \"https://github.com/cosmicjs/cosmic-sdk-swift.git\", from: \"1.0.0\")`\n\n## Usage\n\nImport the framework in your project:\n\n`import CosmicSDK`\n\nYou can get your API access keys by going to Bucket Settings \u003e API Access in the [Cosmic dashboard](https://app.cosmicjs.com/login).\n\n### Testing Your Connection\n\nIf you're experiencing issues, you can test your connection first:\n\n```swift\n// Test basic connection\ndo {\n    let response = try await cosmic.testConnection()\n    print(\"Connection successful: \\(response)\")\n} catch {\n    print(\"Connection failed: \\(error)\")\n}\n\n// Get bucket information to see available object types\ndo {\n    let bucketInfo = try await cosmic.getBucketInfo()\n    print(\"Bucket title: \\(bucketInfo.bucket.title)\")\n    // This will help you see what object types are available\n} catch {\n    print(\"Failed to get bucket info: \\(error)\")\n}\n```\n\n### Common Issues\n\n1. **HTML Response Instead of JSON**: This usually means authentication failed\n\n   - Check your bucket slug and read key\n   - Ensure your read key has the correct permissions\n   - Verify the bucket exists and is accessible\n\n2. **Object Types Not Found**: Make sure the object types exist in your bucket\n\n   - Check your Cosmic dashboard for available object types\n   - Object type names are case-sensitive\n   - Use `getBucketInfo()` to see available object types\n\n3. **Empty Query Parameters**: The SDK now automatically filters out empty parameters\n\n4. **Network Issues**: Ensure your app has internet connectivity\n\n## TODO\n\n- [x] Add depth parameter to find methods\n- [x] Add skip parameter for pagination\n- [x] Update README with pagination examples\n\n```swift\nlet cosmic = CosmicSDKSwift(\n    .createBucketClient(\n        bucketSlug: BUCKET,\n        readKey: READ_KEY,\n        writeKey: WRITE_KEY\n    )\n)\n```\n\nTo see all the available methods, you can look at our [JavaScript implementation](https://www.cosmicjs.com/docs/api/) for now. This project is not at feature parity or feature complete, but the methods listed below are.\n\nFrom the SDK you can create your own state to hold your results, map a variable of any name to an array of type `Object` which is defined in our [model structure](https://www.cosmicjs.com/docs/api/objects#the-object-model). This is a singular `Object` that reflects any content model you create.\n\n## Modern Swift Support\n\nThe SDK now supports both completion handlers (for backward compatibility) and modern async/await patterns. Choose the style that best fits your project.\n\n## Metadata Access\n\nThe SDK now provides flexible metadata access with support for both the new dictionary format and legacy array format from the Cosmic API.\n\n### Clean \u0026 Intuitive Access\n\nThe new API provides the cleanest possible syntax for metadata access:\n\n```swift\n// Direct comparisons - no casting needed!\nif user.metadata?.is_premium == true {\n    // Premium user logic\n}\n\nif user.metadata?.name == \"John Doe\" {\n    // Name matches\n}\n\n// Works in conditionals\nguard product.metadata?.in_stock == true else {\n    return\n}\n\n// When you need to store values, use typed accessors\nlet name = user.metadata?.name.string\nlet age = user.metadata?.age.int\nlet tags = user.metadata?.tags.array(of: String.self)\n```\n\n### Three Ways to Access Metadata\n\n```swift\n// 1. Direct comparison (cleanest for conditionals)\nif event.metadata?.is_virtual == true { }\n\n// 2. Typed accessors (when you need the value)\nlet price = product.metadata?.price.double\n\n// 3. Nested access (for complex structures)\nlet city = user.metadata?.address.city.string\n```\n\nAvailable type accessors:\n\n- `.string` - String values\n- `.int` - Integer values\n- `.double` - Double/Float values\n- `.bool` - Boolean values\n- `.array(of:)` - Typed arrays\n- `.dictionary(keyType:valueType:)` - Typed dictionaries\n- `.raw` - Access raw value for custom types\n- `.exists` - Check if field exists\n\n### Real-World Examples\n\n```swift\n// Fetch a user object\nlet result = try await cosmic.findOne(type: \"users\", id: userId)\nlet user = result.object\n\n// Direct comparisons - the cleanest syntax!\nif user.metadata?.is_premium == true {\n    print(\"Welcome, premium user!\")\n}\n\nif user.metadata?.account_type == \"enterprise\" {\n    enableEnterpriseFeatures()\n}\n\n// When you need to store values\nlet name = user.metadata?.name.string\nlet email = user.metadata?.email.string\nlet credits = user.metadata?.credits.int\n\n// Nested object access\nlet city = user.metadata?.address.city.string\nlet country = user.metadata?.address.country.string\n\n// Arrays with type safety\nif let roles = user.metadata?.roles.array(of: String.self) {\n    print(\"User roles: \\(roles.joined(separator: \", \"))\")\n}\n\n// Check field existence\nif user.metadata?.premium_expires.exists {\n    // Handle premium expiration\n}\n```\n\n### Alternative Access Methods\n\n```swift\n// Method 1: Using metafieldValue (returns AnyCodable)\nlet nameValue = user.metafieldValue(for: \"name\")?.value as? String\n\n// Method 2: Using metafieldsDict\nif let metadata = user.metafieldsDict {\n    let name = metadata[\"name\"]?.value as? String\n    let email = metadata[\"email\"]?.value as? String\n}\n\n// Method 3: For legacy support - access as array\nif let fields = user.metafields {\n    for field in fields {\n        print(\"\\(field.key): \\(field.value?.value ?? \"nil\")\")\n    }\n}\n```\n\n### SwiftUI Example\n\n```swift\nstruct ProductView: View {\n    let product: Object\n\n    var body: some View {\n        VStack {\n            // Direct usage in SwiftUI views\n            if product.metadata?.featured == true {\n                Badge(\"Featured\")\n                    .foregroundColor(.yellow)\n            }\n\n            Text(product.metadata?.name.string ?? \"Unknown Product\")\n                .font(.title)\n\n            if let price = product.metadata?.price.double {\n                Text(\"$\\(price, specifier: \"%.2f\")\")\n                    .font(.headline)\n            }\n\n            // Conditional rendering based on stock\n            if product.metadata?.in_stock == true {\n                Button(\"Add to Cart\") {\n                    addToCart()\n                }\n            } else {\n                Text(\"Out of Stock\")\n                    .foregroundColor(.gray)\n            }\n\n            // Display tags if available\n            if let tags = product.metadata?.tags.array(of: String.self) {\n                ScrollView(.horizontal) {\n                    HStack {\n                        ForEach(tags, id: \\.self) { tag in\n                            TagView(tag: tag)\n                        }\n                    }\n                }\n            }\n        }\n    }\n}\n```\n\n### Creating/Updating Objects with Metadata\n\n```swift\n// Create new object with metadata\nlet response = try await cosmic.insertOne(\n    type: \"products\",\n    title: \"Premium Subscription\",\n    metadata: [\n        \"price\": 99.99,\n        \"currency\": \"USD\",\n        \"features\": [\"Ad-free\", \"Priority support\", \"Advanced analytics\"],\n        \"is_featured\": true,\n        \"billing\": [\n            \"cycle\": \"monthly\",\n            \"trial_days\": 14\n        ]\n    ]\n)\n\n// Update existing object metadata\ntry await cosmic.updateOne(\n    type: \"products\",\n    id: productId,\n    metadata: [\n        \"price\": 79.99,  // Update price\n        \"sale_ends\": \"2024-12-31T23:59:59Z\"\n    ]\n)\n```\n\n### [Find](https://www.cosmicjs.com/docs/api/objects#get-objects)\n\nThe SDK automatically formats requests to match the Cosmic API specification, including proper query parameters and authentication.\n\n### Pagination\n\nThe `find` method supports pagination using the `limit` and `skip` parameters:\n\n- **`limit`**: Number of objects to return (default: 10)\n- **`skip`**: Number of objects to skip before returning results (default: 0)\n\nThis allows you to implement pagination in your app:\n\n**Using Async/Await (Recommended):**\n\n```swift\n@State var objects: [Object] = []\n\nTask {\n    do {\n        let result = try await cosmic.find(type: TYPE)\n        self.objects = result.objects\n    } catch {\n        print(\"Error: \\(error)\")\n    }\n}\n\n// With pagination\nTask {\n    do {\n        // Get first 10 objects\n        let firstPage = try await cosmic.find(type: TYPE, limit: 10, skip: 0)\n\n        // Get next 10 objects\n        let secondPage = try await cosmic.find(type: TYPE, limit: 10, skip: 10)\n\n        self.objects = firstPage.objects + secondPage.objects\n    } catch {\n        print(\"Error: \\(error)\")\n    }\n}\n```\n\n**Using Completion Handlers:**\n\n```swift\n@State var objects: [Object] = []\n\ncosmic.find(type: TYPE) { results in\n    switch results {\n    case .success(let result):\n        self.objects = result.objects\n    case .failure(let error):\n        print(error)\n    }\n}\n```\n\nWith optional props, limit, sorting and status parameters:\n\n**Async/Await:**\n\n```swift\nlet result = try await cosmic.find(\n    type: TYPE,\n    props: \"metadata.image.imgix_url,slug\",\n    limit: 10,  // Now accepts Int instead of String\n    sort: .random,\n    status: .any  // Query for both published and draft objects\n)\nself.objects = result.objects\n```\n\n**Completion Handler:**\n\n```swift\ncosmic.find(\n    type: TYPE,\n    props: \"metadata.image.imgix_url,slug\",\n    limit: 10,\n    sort: .random,\n    status: .any\n) { results in\n    switch results {\n    case .success(let result):\n        self.objects = result.objects\n    case .failure(let error):\n        print(error)\n    }\n}\n```\n\n### Regex queries\n\nUse `findRegex` for server-side regex filtering (mirrors the JavaScript SDK's `$regex` / `$options`). Supports nested fields like `metadata.brand`.\n\n**Async/Await:**\n\n```swift\n// Case-insensitive title match\nlet hoodieResults = try await cosmic.findRegex(\n    type: \"products\",\n    field: \"title\",\n    pattern: \"Hoodie\",            // regex pattern\n    options: [.caseInsensitive],   // defaults to case-insensitive\n    limit: 10\n)\n\n// Regex on nested metadata field\nlet brandResults = try await cosmic.findRegex(\n    type: \"products\",\n    field: \"metadata.brand\",\n    pattern: \"^acme$\",\n    options: [.caseInsensitive]\n)\n```\n\n**Completion Handler:**\n\n```swift\ncosmic.findRegex(\n    type: \"products\",\n    field: \"title\",\n    pattern: \"Hoodie\",\n    options: [.caseInsensitive],\n    limit: 10\n) { results in\n    switch results {\n    case .success(let result):\n        print(\"Found: \\(result.objects.count)\")\n    case .failure(let error):\n        print(error)\n    }\n}\n```\n\n### MongoDB-Style Query Filters\n\nThe `find` method now supports MongoDB-style query filters, allowing you to build complex queries with operators like `$in`, `$eq`, `$gt`, `$lt`, `$exists`, and more. This is particularly useful for filtering by relationship IDs in nested metadata fields.\n\n**Async/Await:**\n\n```swift\n// Filter by single relationship ID\nlet episodes = try await cosmic.find(\n    type: \"episode\",\n    query: [\"metadata.regular_hosts.id\": \"host-id-123\"],\n    depth: 2\n)\n\n// Filter by multiple relationship IDs using $in operator\nlet episodes = try await cosmic.find(\n    type: \"episode\",\n    query: [\n        \"metadata.regular_hosts.id\": [\"$in\": [\"host-id-1\", \"host-id-2\", \"host-id-3\"]]\n    ],\n    props: \"id,slug,title,content,metadata\",\n    limit: 20,\n    depth: 2\n)\n\n// Filter by date range\nlet recentEpisodes = try await cosmic.find(\n    type: \"episode\",\n    query: [\n        \"metadata.broadcast_date\": [\"$gte\": \"2024-01-01\"]\n    ],\n    limit: 10\n)\n\n// Check field existence\nlet episodesWithTakeovers = try await cosmic.find(\n    type: \"episode\",\n    query: [\n        \"metadata.takeovers\": [\"$exists\": true]\n    ]\n)\n\n// Combine multiple filters\nlet filteredEpisodes = try await cosmic.find(\n    type: \"episode\",\n    query: [\n        \"metadata.regular_hosts.id\": [\"$in\": [\"host-1\", \"host-2\"]],\n        \"metadata.broadcast_date\": [\"$gte\": \"2024-01-01\", \"$lte\": \"2024-12-31\"],\n        \"status\": \"published\"\n    ],\n    depth: 2\n)\n```\n\n**Completion Handler:**\n\n```swift\ncosmic.find(\n    type: \"episode\",\n    query: [\n        \"metadata.regular_hosts.id\": [\"$in\": [\"host-id-1\", \"host-id-2\"]]\n    ],\n    depth: 2\n) { results in\n    switch results {\n    case .success(let result):\n        print(\"Found \\(result.objects.count) episodes\")\n    case .failure(let error):\n        print(error)\n    }\n}\n```\n\n**Supported MongoDB Operators:**\n\n- `$in`: Value is in array\n- `$nin`: Value is not in array\n- `$eq`: Equal to (can also use direct value)\n- `$ne`: Not equal to\n- `$gt`: Greater than\n- `$gte`: Greater than or equal\n- `$lt`: Less than\n- `$lte`: Less than or equal\n- `$exists`: Field exists\n- `$regex`: Regular expression match (or use `findRegex` for a more convenient API)\n\n**Benefits Over Regex:**\n\nWhen querying by relationship IDs, MongoDB-style filters are more efficient than regex patterns:\n\n```swift\n// Less efficient: Using regex\nlet episodes = try await cosmic.findRegex(\n    type: \"episode\",\n    field: \"metadata.regular_hosts.id\",\n    pattern: \"^\\(hostId)$\",  // Exact match regex\n    depth: 2\n)\n\n// More efficient: Using query filters\nlet episodes = try await cosmic.find(\n    type: \"episode\",\n    query: [\"metadata.regular_hosts.id\": hostId],\n    depth: 2\n)\n```\n\n### [Find One](https://www.cosmicjs.com/docs/api/objects#get-a-single-object-by-id)\n\n**Async/Await:**\n\n```swift\n@State private var object: Object?\n\ndo {\n    let result = try await cosmic.findOne(type: TYPE, id: objectId)\n    self.object = result.object\n} catch {\n    print(\"Error: \\(error)\")\n}\n```\n\n**Completion Handler:**\n\n```swift\ncosmic.findOne(type: TYPE, id: objectId) { results in\n    switch results {\n    case .success(let result):\n        self.object = result.object\n    case .failure(let error):\n        print(error)\n    }\n}\n```\n\nYou can't initialize a single Object with a specific type, so instead, mark as optional and handle the optionality accordingly.\n\n```swift\nif let object = object {\n    Text(object.title)\n}\n```\n\n### [Insert One](https://www.cosmicjs.com/docs/api/objects#create-an-object)\n\n`.insertOne()` adds a new Object to your Cosmic Bucket. Use this for adding a new Object to an existing Object Type.\n\n**Async/Await:**\n\n```swift\ndo {\n    let response = try await cosmic.insertOne(\n        type: TYPE,\n        title: \"New Object Title\"\n    )\n    print(\"Created successfully: \\(response.message ?? \"\")\")\n} catch {\n    print(\"Error: \\(error)\")\n}\n```\n\n**Completion Handler:**\n\n```swift\ncosmic.insertOne(\n    type: TYPE,\n    title: \"New Object Title\"\n) { results in\n    switch results {\n    case .success(let response):\n        print(\"Created successfully\")\n    case .failure(let error):\n        print(error)\n    }\n}\n```\n\nWith optional props for content, metadata and slug:\n\n**Async/Await:**\n\n```swift\nlet response = try await cosmic.insertOne(\n    type: TYPE,\n    title: \"New Product\",\n    slug: \"new-product\",\n    content: \"Product description here\",\n    metadata: [\n        \"price\": 49.99,\n        \"sku\": \"PROD-001\",\n        \"in_stock\": true,\n        \"categories\": [\"Electronics\", \"Gadgets\"]\n    ]\n)\nprint(\"Created object with ID: \\(response.message ?? \"\")\")\n```\n\n**Completion Handler:**\n\n```swift\ncosmic.insertOne(\n    type: TYPE,\n    title: \"New Product\",\n    content: \"Product description\",\n    metadata: [\"key\": \"value\"],\n    slug: \"new-product\"\n) { results in\n    switch results {\n    case .success(let response):\n        print(\"Created successfully\")\n    case .failure(let error):\n        print(error)\n    }\n}\n```\n\n### [Update One](https://www.cosmicjs.com/docs/api/objects#update-an-object)\n\nWhen using `.updateOne()` you can update an Object's metadata by passing the optional metadata dictionary with one, or many, `key:value` pairs.\n\n**Async/Await:**\n\n```swift\ndo {\n    let response = try await cosmic.updateOne(\n        type: TYPE,\n        id: objectId,\n        title: \"Updated Title\",\n        metadata: [\"last_updated\": Date().ISO8601Format()]\n    )\n    print(\"Updated successfully\")\n} catch {\n    print(\"Error: \\(error)\")\n}\n```\n\n**Completion Handler:**\n\n```swift\ncosmic.updateOne(\n    type: TYPE,\n    id: objectId,\n    title: \"Updated Title\",\n    content: \"New content\",\n    metadata: [\"key\": \"value\"],\n    status: .published\n) { results in\n    switch results {\n    case .success(_):\n        print(\"Updated successfully\")\n    case .failure(let error):\n        print(error)\n    }\n}\n```\n\n### [Delete One](https://www.cosmicjs.com/docs/api/objects#delete-an-object)\n\n**Async/Await:**\n\n```swift\ndo {\n    let response = try await cosmic.deleteOne(type: TYPE, id: objectId)\n    print(\"Deleted successfully\")\n} catch {\n    print(\"Error: \\(error)\")\n}\n```\n\n**Completion Handler:**\n\n```swift\ncosmic.deleteOne(type: TYPE, id: objectId) { results in\n    switch results {\n    case .success(_):\n        print(\"Deleted successfully\")\n    case .failure(let error):\n        print(error)\n    }\n}\n```\n\nDepending on how you handle your data, you will have to account for `id` being a required parameter in the API.\n\n## New Features\n\n### Scheduled Publishing\n\nYou can now schedule objects to be published or unpublished at specific dates:\n\n```swift\n// Schedule publish date\ncosmic.insertOne(\n    type: \"posts\",\n    title: \"Holiday Sale\",\n    publish_at: \"2024-12-25T00:00:00.000Z\"  // ISO 8601 format\n) { ... }\n\n// Schedule unpublish date\ncosmic.updateOne(\n    type: \"events\",\n    id: eventId,\n    title: \"Limited Time Offer\",\n    unpublish_at: \"2024-12-31T23:59:59.000Z\"\n) { ... }\n```\n\nNote: Objects with `publish_at` or `unpublish_at` dates are automatically saved as drafts.\n\n### Query Any Status\n\nUse `.any` status to query both published and draft objects:\n\n```swift\ncosmic.find(\n    type: \"posts\",\n    status: .any  // Returns both published and draft objects\n) { ... }\n```\n\n## Migration Guide\n\n### Limit Parameter Change\n\nThe `limit` parameter now accepts `Int` instead of `String`. If you have existing code using String limits:\n\n```swift\n// Old code\ncosmic.find(type: \"posts\", limit: \"10\") { ... }\n\n// New code\ncosmic.find(type: \"posts\", limit: 10) { ... }\n\n// If you have a String variable\nlet stringLimit = \"10\"\ncosmic.find(type: \"posts\", limit: Int(stringLimit) ?? 10) { ... }\n```\n\n## License\n\nThe MIT License (MIT)\n\nCopyright (c) 2024 CosmicJS\n\nPermission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the \"Software\"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fcosmicjs%2Fcosmic-sdk-swift","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fcosmicjs%2Fcosmic-sdk-swift","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fcosmicjs%2Fcosmic-sdk-swift/lists"}