Ferno 🔥

Ferno 使您可以轻松地将您的 Vapor 项目与您的 Firebase 实时数据库连接起来。它是使用全新的 Vapor 4 构建的。它为您提供了一个简洁明了的界面来与 Firebase Realtime REST API 交互。它将自动将响应转换为您的类/结构!

先决条件

您将需要

安装

在您的 Package.swift 文件中,添加以下行

.package(url: "https://github.com/vapor-community/ferno.git", from: "0.6.0")

同时确保您添加 Ferno 作为依赖项

dependencies: [
  .product(name: "Ferno", package: "ferno")
]

设置

旧版设置

  1. Ferno 使用访问令牌来读取和写入您的数据库。首先,我们需要获取您的服务帐户信息。

    • 登录 Firebase 控制台
    • 点击 项目概览 旁边的设置齿轮
    • 选择 项目设置
    • 选择 服务帐号 选项卡
    • 点击底部的 生成新的私钥 按钮
    • 这将下载一个 .json 文件。您现在将有权访问电子邮件和私钥。您将在下一步的初始化过程中传入这些信息。
  2. Ferno 注册为 Provider 并导入 Ferno。这通常在 configure.swift 中完成

FirebaseSDK 设置

  1. 登录 Firebase 控制台
  2. 点击 项目概览 旁边的设置齿轮
  3. 选择 项目设置
  4. 选择 服务帐号 选项卡
  5. 选择 Firebase Admin SDK 选项
  6. 点击 生成新的私钥 按钮以下载 json 文件。

Ferno 设置

您可以使用 json 文件信息的内容来填写 FernoDefaultConfiguration,或者使用 json 文件来准备 FernoServiceJsonConfiguration

import Ferno

let fernoConfiguration = FernoDefaultConfiguration(
    basePath: "database-url", 
    email: "service-account-email", 
    privateKey: "private-key"
)
app.ferno.use(.default(fernoConfiguration))

如果您更喜欢使用 Firebase ServiceAccount.json,请按照下面的示例操作。

import Ferno

// option 1
let fernoConfiguration = try FernoServiceJsonConfiguration(json: Data)

// option 2
let fernoConfiguration = try FernoServiceJsonConfiguration(path: URL)

// option 3
let fernoConfiguration = FernoServiceJsonConfiguration(
                type: String,
                projectId: String,
                privateKeyId: String,
                privateKey: String,
                clientEmail: String,
                clientId: String,
                authUri: String,
                tokenUri: String,
                authProviderX509CertUrl: String,
                clientX509CertUrl: String,
                universeDomain: String
)

app.ferno.use(.serviceAccountKey(fernoConfiguration))

参数

有一些自定义参数可以传递到函数中。我想介绍一下您需要了解的所有参数。

[FernoQuery]

在 GET 请求中,您可能想要查询您的数据。这就是 [FernoQuery] 的用途。

FernoQuery 是一个枚举,包含

  1. case shallow(Bool)
  2. case orderBy(FernoValue)
  3. case limitToFirst(FernoValue)
  4. case limitToLast(FernoValue)
  5. case startAt(FernoValue)
  6. case endAt(FernoValue)
  7. case equalTo(FernoValue)

这些是 Firebase 上允许的所有可能的查询,根据 文档

[FernoQuery] 的注意事项

FernoValue

您会注意到 FernoQuery 中的大多数 case 都具有 FernoValue 值。FernoValue 只是 Bool, String, Int, Double, Float 的包装器。所以您可以直接执行 .startAt(5),一切都会正常工作。

[FernoQuery] 的示例

仅使用 shallow

[.shallow(true)]

过滤数据以仅返回与 "age": 21 匹配的数据

[.orderBy("age"), .equalTo(21)]

仅 orderBy(按升序返回数据)

[.orderBy("age")]

用法

有 6 个函数允许您与您的 Firebase 实时数据库进行交互。

GET

有四个函数允许您获取数据。

app.ferno.retrieve(_ path: [String], queryItems: [FernoQuery] = [])
app.ferno.retrieve(_ path: String..., queryItems: [FernoQuery] = [])
app.ferno.retrieveMany(_ path: [String], queryItems: [FernoQuery] = [])
app.ferno.retrieveMany(_ path: String..., queryItems: [FernoQuery] = [])

retrieveretrieveMany 之间唯一的区别是返回类型。

示例

  1. 定义您希望数据转换成的类型。
struct Developer: Content {
   var name: String
   var favLanguage: String
   var age: Int
}
  1. 发出请求。确保您设置了响应的类型,以便 Ferno 知道要转换成什么类型。
let developers: [String: Developer] = try await app.ferno.retrieveMany("developers")
let developer: Developer = try await app.ferno.retrieve(["developers", "dev1"])

POST

用于在您的数据库中创建新条目

app.ferno.create(_ path: [String], body: T) try await -> FernoChild
app.ferno.create(_ path: String..., body: T) try await -> FernoChild
struct FernoChild: Content {
  var name: String
}

示例

let newDeveloper = Developer(name: "Elon", favLanguage: "Python", age: 46) // conforms to Content
let newDeveloperKey: FernoChild = try await app.ferno.create("developers", body: newDeveloper)

DELETE

用于删除数据库中的条目

app.ferno.delete(_ path: [String]) try await -> Bool
app.ferno.delete(_ path: String...) try await -> Bool

示例

let successfulDelete: Bool = try await app.ferno.delete(["developers", "dev-1"])

PATCH

更新特定位置的值,但省略的值不会被删除

app.ferno.update(_ path: [String], body: T) try await -> T
app.ferno.update(_ path: String..., body: T) try await -> T

示例

struct UpdateDeveloperName: Content {
  var name: String
}

let newDeveloperName = UpdateDeveloperName(name: "Kimbal") //conforms to Content
let updatedDeveloperName: UpdateDeveloperName = try await app.ferno.update(["developers", newDeveloperKey.name], body: newDeveloper) //newDeveloperKey.name comes from the create method

PUT

使用您传入的数据覆盖当前位置

client.ferno.overwrite(_ path: [String], body: T) try await -> T
client.ferno.overwrite(_ path: String..., body: T) try await -> T

示例

struct LeadDeveloper: Content {
  var name: String
  var company: String
  var age: Int
}

let leadDeveloper = LeadDeveloper(name: "Ashley", company: "Bio-Fit", age: 20)
let leadDevResponse: LeadDeveloper = try await app.ferno.overwrite(["developers", newDeveloperKey.name], body: leadDeveloper)

测试

目前,测试是使用实际的虚拟 Firebase 实时数据库编写的。如果您想运行所有测试,您将需要创建一个虚拟 Firebase 实时数据库。

测试设置

您需要转到 Application+Testing.swift 并根据您的 Firebase 服务帐户填写缺失的值。然后您就可以运行测试了。

作者

许可

本项目根据 MIT 许可证获得许可 - 有关详细信息,请参阅 LICENSE.md 文件

致谢