# 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: "1.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` that authenticates each request with a JSON Web Token (JWT). To get a token, create an API key in App Store Connect and sign a JWT with its key ID, issuer ID, and private key: ```swift import ASConnectService import OpenAPIURLSession let client = Client( serverURL: try Servers.Server1.url(), transport: URLSessionTransport(), middlewares: [ BearerAuthMiddleware(token: yourJWTToken) ] ) ``` Tokens expire after 20 minutes at most. For longer-lived clients, use `APIKeyTokenProvider`, which signs new ones with your API key as needed: ```swift let tokenProvider = try APIKeyTokenProvider( issuerID: yourIssuerID, keyID: yourKeyID, privateKey: yourP8FileContents ) BearerAuthMiddleware { try await tokenProvider.token() } ``` ### 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. Pass a page's `links.nextCursor` as the `cursor` of the next request: ```swift var apps: [Components.Schemas.App] = [] var cursor: String? repeat { let page = try await client.appsGetCollection(query: .init(limit: 200, cursor: cursor)).ok.body.json apps += page.data cursor = page.links.nextCursor } while cursor != nil ``` ### Handling Rate Limits Add `RateLimitMiddleware` before the authentication middleware to retry `429 Too Many Requests` responses: ```swift middlewares: [ RateLimitMiddleware(), BearerAuthMiddleware { try await tokenProvider.token() } ] ``` ## Supported Platforms - 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 ``` ### 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 ``` ## 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.