Files
asconnect-service/README.md
T
javier 0431fb5133 Overhauled the library with several new features (#5)
## Summary

Updates the library to v4.5.1 of the App Store Connect API, and ships it as a breaking 2.0.0 release with pagination, API key authentication, rate limiting, and a lighter install for consumers.

## Breaking changes

- **Minimum platforms:** iOS 14, macOS 11, tvOS 14, watchOS 7, and visionOS 1.
- **Toolchain:** Swift 6.0+ (Xcode 16+). The package builds in the Swift 6 language mode.
- **Runtime:** requires `swift-openapi-runtime` 1.11.0 or later.

## Changes

- **API:** updated the OpenAPI specification to v4.5.1, covering 1,303 operations and 1,473 schemas.
- **Pagination:** the spec patch adds the undocumented `cursor` query parameter to the 465 paged operations. `PagedDocumentLinks.nextCursor` reads the cursor from a page, and `PagedSequence` iterates every page.
- **Authentication:** `APIKeyTokenProvider` signs ES256 tokens from an API key and reuses each one until a minute before it expires. `BearerAuthMiddleware` now accepts a token provider.
- **Rate limiting:** `RateLimitMiddleware` retries `429` responses, waiting for `Retry-After` or backing off exponentially.
- **Generated code:** committed to `Sources/ASConnectService/Sources/Public/Generated` instead of generated by a build plugin. Consumers now resolve 4 packages instead of 12, and Xcode no longer asks to trust a plugin.
- **Tooling:**
  - `make oas-download` now downloads, patches, generates, and checks the docs in one go.
  - New `make oas-generate`, `make oas-validate`, and `make doc-check` targets.
  - The generator is pinned in `Tools/`, and the DocC plugin is only resolved by the documentation targets.
- **Documentation:** the DocC catalog now lists every operation and schema in the spec, and the catalog and README are rewritten for the new APIs.
- **Housekeeping:** Apache 2.0 license headers on every Swift file, including `Package.swift` and the tests.

Reviewed-on: #5
Co-authored-by: Javier Cicchelli <javier@rock-n-code.com>
2026-10-25 17:52:37 +00:00

172 lines
4.0 KiB
Markdown

# App Store Connect Service (ASConnectService)
A Swift client library for the App Store Connect API, generated from the official OpenAPI specification.
## Overview
`ASConnectService` exposes every endpoint of Apple's App Store Connect API as a Swift method with typed requests and responses. It's generated from the official OpenAPI specification with [Swift OpenAPI Generator](https://github.com/apple/swift-openapi-generator).
## Installation
Add `ASConnectService` as a dependency in your `Package.swift` file:
```swift
dependencies: [
.package(url: "https://github.com/rock-n-code/asconnect-service.git", from: "2.0.0")
]
```
Then add it to your target dependencies:
```swift
.target(
name: "YourTarget",
dependencies: [
"ASConnectService"
]
)
```
## Usage
### Creating a Client
Create a `Client` with a server URL, a transport, and a `BearerAuthMiddleware`. With an API key from App Store Connect, `APIKeyTokenProvider` signs the JSON Web Tokens (JWT) the API requires, and renews them before they expire:
```swift
import ASConnectService
import OpenAPIURLSession
let tokenProvider = try APIKeyTokenProvider(
issuerID: yourIssuerID,
keyID: yourKeyID,
privateKey: yourP8FileContents
)
let client = Client(
serverURL: try Servers.Server1.url(),
transport: URLSessionTransport(),
middlewares: [
BearerAuthMiddleware { try await tokenProvider.token() }
]
)
```
To use a token you signed yourself, pass it directly. It expires after 20 minutes at most:
```swift
BearerAuthMiddleware(token: yourJWTToken)
```
### Making API Calls
Each endpoint is a method on `Client`, declared by `APIProtocol`. It returns an `Output` enum with a case for each documented response:
```swift
let response = try await client.appsGetCollection(query: .init(limit: 10))
let apps = try response.ok.body.json.data
```
The `ok` property throws for any other response. To handle those, switch over the `Output` cases, such as `.unauthorized` or `.undocumented(statusCode:_:)`.
### Fetching More Pages
Lists are paged. Iterate a `PagedSequence` to fetch each page in turn:
```swift
let pages = PagedSequence(links: \.links) { cursor in
try await client.appsGetCollection(query: .init(limit: 200, cursor: cursor)).ok.body.json
}
var apps: [Components.Schemas.App] = []
for try await page in pages {
apps += page.data
}
```
To fetch pages yourself, pass a page's `links.nextCursor` as the `cursor` of the next request.
### Handling Rate Limits
Add `RateLimitMiddleware` before the authentication middleware to retry `429 Too Many Requests` responses:
```swift
middlewares: [
RateLimitMiddleware(),
BearerAuthMiddleware { try await tokenProvider.token() }
]
```
## Requirements
- Swift 6.0+ (Xcode 16+)
- iOS 14.0+
- macOS 11.0+
- tvOS 14.0+
- visionOS 1.0+
- watchOS 7.0+
## Development
### Building
```bash
make lib-build
```
### Testing
```bash
make lib-test
```
### Generating Documentation
```bash
# Generate documentation archive (for Xcode)
make doc-generate-archive
# Generate documentation for static hosting (e.g. GitHub Pages)
make doc-generate-github
# Preview documentation locally in Safari
make doc-preview
# Check the catalog covers the generated code
make doc-check
```
### Updating the API
The generated code is committed in `Sources/ASConnectService/Sources/Public/Generated`, so consumers don't run the generator.
```bash
# Update to the latest specification
make oas-download
# Regenerate the code only
make oas-generate
# Validate the specification only
make oas-validate
```
## Dependencies
- [swift-openapi-runtime](https://github.com/apple/swift-openapi-runtime)
- [swift-openapi-urlsession](https://github.com/apple/swift-openapi-urlsession)
Development only:
- [swift-openapi-generator](https://github.com/apple/swift-openapi-generator), in `Tools`
- [swift-docc-plugin](https://github.com/swiftlang/swift-docc-plugin)
## License
Licensed under the Apache License, Version 2.0. See [LICENSE](LICENSE) for details.
## Contributing
See [CONTRIBUTORS](CONTRIBUTORS) for the list of project authors.