Bagbutik

基于官方 OpenAPI 规范App Store Connect API 生成的 Swift 代码。
Swift versions Platforms
CI Documentation
Twitter Mastodon

什么是 Bagbutik?

Bag·bu·tik (名词) /ˈb̥a̝w-ˌb̥u-tiːk/ - (丹麦语) 商店后面的房间

Bagbutik 包含两个部分:一个用于生成 Swift 代码的命令行工具,以及一个包含为 App Store Connect API 生成代码的库。该命令行工具解码 Apple App Store Connect API 的官方 OpenAPI 规范

在生成代码的同时,该命令行工具还会从 Apple 开发者文档网站 下载 App Store Connect API 的官方文档,并将其应用到生成的代码中,以便您可以在 Xcode 中直接获得文档。

只有当 Apple 发布新版本的规范时才需要使用命令行工具。GitHub Action 会自动检查规范的新版本,并创建一个包含更改的拉取请求。

如何使用 Bagbutik

Bagbutik 使用 JSON Web Tokens (JWT) 进行授权。您需要从您组织的 App Store Connect 账户中获取所需的密钥。

请参阅 为 App Store Connect API 创建 API 密钥 了解如何创建您的密钥。

以下是一个基本示例,用于获取所有 iOS 应用的 Bundle ID,包括相关的描述文件,并按 Seed ID 和 Bundle ID 本身降序排序。

import Bagbutik_Core
import Bagbutik_Provisioning

let service = BagbutikService(jwt: try .init(
    keyId: "P9M252746H",
    issuerId: "82067982-6b3b-4a48-be4f-5b10b373c5f2",
    privateKey: """
    -----BEGIN PRIVATE KEY-----
    MIGHAgEAMBMGByqGSM49AgEGCCqGSM49AwEHBG0wawIBAQQgevZzL1gdAFr88hb2
    OF/2NxApJCzGCEDdfSp6VQO30hyhRANCAAQRWz+jn65BtOMvdyHKcvjBeBSDZH2r
    1RTwjmYSi9R/zpBnuQ4EiMnCqfMPWiZqB4QdbAd0E7oH50VpuZ1P087G
    -----END PRIVATE KEY-----
    """
))
let response = try await service.request(
    .listBundleIdsV1(filters: [.platform([.iOS])],
                     includes: [.profiles],
                     sorts: [.seedIdDescending, .idDescending])
)
print(response)

如何将 Bagbutik 添加到项目中

Bagbutik 支持 Swift Package Manager,并且用于生成代码的内部库也由此进行管理。

生成的代码库实际上由多个库组成,以便消费者仅依赖所需的功能端点。因此,要获取 Bagbutik,您需要决定您需要哪些功能。

在您的 Package.swift 文件中,将 Bagbutik 添加为依赖项

dependencies: [
    .package(url: "https://github.com/MortenGregersen/Bagbutik", from: "8.0.0"),

然后在 targets 中添加您的目标所需的库

targets: [
    .target(
        name: "Awesome",
        dependencies: [
            .product(name: "Bagbutik-AppStore", package: "Bagbutik"),
            .product(name: "Bagbutik-TestFlight", package: "Bagbutik"),

如果需要所有库,可以使用 umbrella 库 Bagbutik

targets: [
    .target(
        name: "Awesome",
        dependencies: [
            .product(name: "Bagbutik", package: "Bagbutik"),

请记住在导入库时将连字符替换为下划线。

当导入 Bagbutik-TestFlight 时,应写成

import Bagbutik_TestFlight

Bagbutik-Core

核心库是 Bagbutik-Core,它包含 BagbutikServiceJWT、协议和通用生成的类型,如 ErrorResponsePagingInformation

所有其他库都依赖于 Bagbutik-Core。这是唯一在 Bagbutik.dev 上有文档的库,因为其他库仅包含已经由 Apple 文档 记录的类型。

Bagbutik-Models

由于 API 中的模型被许多不同的端点使用,它们都位于 Bagbutik-Models 中。所有包含端点的库都依赖于 Bagbutik-Models

Bagbutik-<API 区域>

App Store Connect API 所有区域的端点都位于不同的库中,并带有描述性名称。

目前有 7 个包含端点的库

应用于 OpenAPI 规范的手动补丁

Apple 提供的 OpenAPI 规范并不总是与从 API 接收的数据对齐。每当发现此类不匹配时,都会向 Apple 提交反馈并应用补丁。每当问题得到解决,补丁就会再次移除。

当前开放的反馈和应用的补丁

FB8977648: "BundleIdPlatform" 模式缺少 "UNIVERSAL" 和 "SERVICES"

标题: App Store Connect API 的 BundleIdPlatform 模式缺少 "UNIVERSAL" 类型

描述

在 App Store Connect API 的 OpenAPI 规范中,"BundleIdPlatform" 模式据说只可以是 "IOS" 或 "MAC_OS"。这是不正确的,因为通用应用(iOS 和 macOS)具有 "UNIVERSAL" 平台。

FB12292035: ErrorResponse.Errors 在 "meta" 中具有必需的可选 "detail" 且没有 "associatedErrors"

在 Apple 的 OpenAPI 规范中,ErrorResponse.Errors 上的 detail 属性被标记为 required。在 2023 年 12 月 1 日,观察到一些错误(状态码 409)没有 detail

在 Apple 的 OpenAPI 规范和文档中,associatedErrorsmeta 属性中没有被提及(上次检查于 2023 年 12 月 1 日)。但是当创建 ReviewSubmissionItem 时,如果 AppStoreVersion 失败,则会观察到它。

FB15681740: App Store Connect API 规范的 Device 类类型模式缺少 "APPLE_VISION_PRO" 类型

在 App Store Connect API 的 OpenAPI 规范中,“Device.deviceClass” 模式据说不包含 "APPLE_VISION_PRO”。这是不正确的,因为“Devices”端点可以具有 “APPLE_VISION_PRO” 类型。

已关闭的反馈(已移除补丁)