Cubby

Release License Issues Downloads

Bitrise Codecov Codacy

Github

Cubby 是一个 Swift 封装,用于 JSONBin API,它提供了一个简单的接口,用于在云端存储、分类和获取 Swift 结构体。

API 支持

Cubby 提供对 JSONBin API v2 和 v3 的完整支持。

版本 2.0

版本 3.0

用法

Cubby 使用规范协议来指示每个 API 版本支持哪些端点。 根据您要调用的端点,使用 JSONBin.V2.APIJSONBin.V3.API 的适当实例化。(请注意,JSONBin API 的版本 2 计划于 2022 年 2 月 28 日弃用。)

Bin (容器)

创建、读取、更新或删除代表 Swift 结构体的容器 (bins)。 每个容器代表一个单独的 Swift 结构体,并具有隐私设置、可选名称以及其所属的可选集合。

public protocol JSONBinV2APIBinSpec: JSONBinV2APISpec {
    func createBin<Resource: Encodable>(named name: String?, with resource: Resource, inCollectionWith id: Collection.ID?, private: Bool?) -> Request<Creation<Resource>>
    func readBin<Resource: Decodable>(with id: ID, of type: Resource.Type, at version: Version?) -> Request<Resource>
    func updateBin<Resource: Encodable>(with id: ID, using resource: Resource, versioning: Bool?) -> Request<Update<Resource>>
    func deleteBin(with id: ID) -> Request<Deletion>
}

public protocol JSONBinV3APIBinSpec: JSONBinV3APISpec {
    func createBin<Resource: Encodable>(named name: String?, with resource: Resource, inCollectionWith id: Collection.ID?, private: Bool?) -> Request<Creation<Resource>>
    func readBin<Resource: Decodable>(with id: ID, of type: Resource.Type, at version: Version?, includingMetadata: Bool?, usingDotPath dotPath: String?) -> Request<Read<Resource>>
    func versionCount(ofBinWith id: ID) -> Request<VersionCount>
    func updateBin<Resource: Encodable>(with id: ID, using resource: Resource, versioning: Bool?) -> Request<Update<Resource>>
    func updateName(ofBinWith id: ID, toName name: String) -> Request<NameUpdate>
    func updatePrivacy(ofBinWith id: ID, toPrivate private: Bool) -> Request<PrivacyUpdate>
    func deleteBin(with id: ID) -> Request<Deletion>
    func deleteVersions(ofBinWith id: ID, preservingLatest: Bool?) -> Request<Deletion>
}
创建示例
var apple = Company(name: "Apple", remoteWorkPolicy: .hybrid)

let request = api.createBin(named: "Apple Computer", with: apple)
let creation = try await request.returnedResource
let id = creation.metadata.id

print(creation.resource) // Company(name: "Apple", remoteWorkPolicy: .hybrid)
读取示例
let request = api.readBin(with: id, of type: Company.self, at: .number(1), includingMetadata: false)
let company = try await request.returnedResource

print(company) // Company(name: "Apple Computer", remoteWorkPolicy: .hybrid)
更新示例
apple.remoteWorkPolicy = .disallowed

let request = api.updateBin(with: id, using: apple)
let update = try await request.returnedResource

print(update.resource) // Company(name: "Apple", remoteWorkPolicy: .disallowed)
更新名称示例
let request = api.updateName(ofBinWith: id, toName: "Apple Inc.")
let update = try await request.returnedResource

print(update.resource) // Company(name: "Apple", remoteWorkPolicy: .disallowed)
版本计数示例
let request = api.versionCount(ofBinWith: id)
let versionCount = try await request.returnedResource.metadata.versionCount

print(versionCount) // 1
删除版本示例
let request = api.deleteVersions(ofBinWithID: id, preservingLatest: true)
let deletion = try await request.returnedResource

print(deletion.message) // "Versions for the Bin are deleted successfully and latest version preserved on the base record."
删除示例
let request = api.deleteBin(with: id)
let deletion = try await request.returnedResource

print(deletion.message) // "Bin deleted successfully"

Collection (集合)

创建、从其中获取或更新包含 Swift 结构体的集合。 为了确保集合仅包含相同类型的结构体,请将代表该类型的架构文档(参见下文)附加到集合。 一旦附加,尝试在不同类型的集合中创建容器(即,无法通过架构验证的容器)将会失败。

public protocol JSONBinV2APICollectionSpec: JSONBinV2APISpec {
    func createCollection(named name: String) -> Request<Creation>
    func updateCollection(with id: ID, using action: Action) -> Request<Update>
}

public protocol JSONBinV3APICollectionSpec: JSONBinV3APISpec {
    func createCollection(named name: String) -> Request<Creation>
    func fetchBins(inCollectionWith id: ID, sortedBy sortOrder: Fetch.SortOrder?) -> Request<[Fetch.Result]>
    func fetchUncategorizedBins(sortedBy sortOrder: Fetch.SortOrder?) -> Request<[Fetch.Result]>
    func updateName(ofCollectionWith id: ID, toName name: String) -> Request<NameUpdate>
    func addSchemaDoc(with id: SchemaDoc.ID, toCollectionWith collectionID: ID) -> Request<Addition>
    func removeSchemaDoc(fromCollectionWith id: ID) -> Request<Removal>
}
创建示例
let request = api.createCollection(named: "WFH Companies")
let creation = try await request.returnedResource
let id = creation.metadata.id

print(creation.metadata.name) // "WFH Companies"
获取示例
let request = api.fetchBins(inCollectionWith: id)
let companies = try await request.returnedResource

print(companies) // [Company(name: "Twitter", remoteWorkPolicy: .allowed), Company(name: "GitHub", remoteWorkPolicy: .distributed)]
更新名称示例
let request = api.updateName(ofCollectionWith: id, toName: "Remote Companies")
let update = try await request.returnedResource

print(update.metadata.name) // "Remote Companies"
添加架构文档示例
let request = api.addSchemaDoc(with: schemaDocID, toCollectionWith: id)
request() // Adds a schema doc to the collection
移除架构文档示例
let request = api.removeSchemaDoc(fromCollectionWith: id)
request() // Removes the schema doc from the collection

Schema Doc (架构文档)

创建、读取或更新可以附加到集合的架构文档。

public protocol JSONBinV2APISchemaDocSpec: JSONBinV2APISpec {
    func createSchemaDoc<Resource>(for type: Resource.Type, named name: String) -> Request<Response<Resource>>
    func readSchemaDoc<Resource>(with id: ID, for type: Resource.Type) -> Request<Schema<Resource>>
    func updateSchemaDoc<Resource>(with id: ID, toSchemaFor type: Resource.Type) -> Request<Response<Resource>>
}

public protocol JSONBinV3APISchemaDocSpec: JSONBinV3APISpec {
    func createSchemaDoc<Resource>(for type: Resource.Type, named name: String) -> Request<Response<Resource>>
    func readSchemaDoc<Resource>(with id: ID, for type: Resource.Type) -> Request<Response<Resource>>
    func updateSchemaDoc<Resource>(with id: ID, toSchemaFor type: Resource.Type) -> Request<Update<Resource>>
    func updateName(ofSchemaDocWith id: ID, toName name: String) -> Request<NameUpdate>
}
创建示例
extension Company: SchemaAdhering {
    static var description: String? {
        "A company has both a name and a remote work policy."
    }

    static var properties: [CodingKeys: SchemaType] {
        [
            .name: .string,
            .remoteWorkPolicy: .string
        ]
    }
}

let request = api.createSchemaDoc(for: Company.self, named: "Company Schema Doc")
let creation = try await request.returnedResource
let id = creation.metadata.id

print(creation.metadata.name) // "Company Schema Doc"
print(creation.schema.title) // "Company"
print(creation.schema.description) // "A company has both a name and a remote work policy."
print(creation.schema.properties) // [.name: .string, .remoteWorkPolicy: .string]
读取示例
let request = api.readSchemaDoc(with: id)
let read = try await request.returnedResource

print(read.metadata.name) // "Company Schema Doc"
print(read.schema.title) // "Company"
print(read.schema.description) // "A company has both a name and a remote work policy."
print(read.schema.properties) // [.name: .string, .remoteWorkPolicy: .string]
更新示例
extension Company: SchemaAdhering {
    static var description: String? {
        "A company has both a name, a remote work policy, and a number of employees."
    }

    static var properties: [CodingKeys: SchemaType] {
        [
            .name: .string,
            .remoteWorkPolicy: .string,
            .employeeCount: .integer
        ]
    }
}

let request = api.updateSchemaDoc(with: id, toSchemaFor: Company.self)
let update = request.returnedResource

print(update.metadata.name) // "Company Schema Doc"
print(update.schema.title) // "Company"
print(update.schema.description) // "A company has, a name, a remote work policy, and a number of employees."
print(update.schema.properties) // [.name: .string, .remoteWorkPolicy: .string, .employeeCount: .integer]
更新名称示例
let request = api.updateName(ofSchemaDocWith: id, toName: "Company Schema Document")
let update = try await request.returnedResource

print(update.metadata.name) // "Company Schema Document"

Geolocation (地理位置)

查找 IP 地址的地理位置数据。

public protocol JSONBinV2APIGeoIPSpec: JSONBinV2APISpec {
    func lookUpGeolocation(for ipAddress: IPAddress) -> Request<Lookup>
}
查找地理位置示例
let ipAddress = IPAddress("141.158.45.225")
let request = api.lookUpGeolocation(for: ipAddress)
let lookupData = await request.returnedResource.data

print(lookupData.range) // 2375953408..<2375953919
print(lookupData.countryCode) // "US"
print(lookupData.regiounCode) // "PA"
print(lookupData.timeZone) // "America/New_York"
print(lookupData.city) // "Philadelphia"
print(lookupData.coordinates.latitude) // 39.934
print(lookupData.coordinates.longitude) // -75.16
print(lookupData.metroCode) // 504
print(lookupData.accuracyRadius) // 1

实验性

获取此帐户剩余的请求数。

public protocol JSONBinV2APIExperimentalSpec: JSONBinV2APISpec {
    func requestCount() -> Request<Count>
}
请求计数示例
let request = api.requestCount()
let count = try await request.returnedResource

print(count.value) // 1000000

其他

列出此帐户的使用日志,或下载特定的使用日志。

public protocol JSONBinV3APIOtherSpec: JSONBinV3APISpec {
    func listUsageLogs() -> Request<UsageLog.List>
    func downloadUsageLog(named name: String) -> Request<UsageLog>
}
列出使用日志示例
let ipAddress = IPAddress("141.158.45.225")
let request = api.listUsageLogs
let list = await request.returnedResource

print(list.logNames) // ["12-31-2022", "01-01-2022", "01-02-2022"]
下载使用日志示例
let ipAddress = IPAddress("141.158.45.225")
let request = api.downloadUsageLog(named: "01-01-2022")
let usageLog = await request.returnedResource

print(usageLog.compressed) // ZIP data of log contents

安装

Cubby 使用 Swift Package Manager 分发。 要将其安装到项目中,只需将其作为依赖项添加到您的 Package.swift 清单中

let package = Package(
    ...
    dependencies: [
        .package(url: "https://github.com/Fleuronic/Cubby", from: "1.0.0")
    ],
    ...
)

然后在您想要使用它的任何地方导入 Cubby

import Cubby

有关如何使用 Swift Package Manager 的更多信息,请查看这篇文章,或其官方文档