supabase-client-dependency

CI

用于 supabase 集成的 swift-dependencies 客户端。

此依赖项包装了 supabase-swift 客户端、数据库和身份验证,为在基于 TCA 的应用中使用提供了便捷方法。

此包为数据库查询增加了一些便利功能,并持有一个 authentication 客户端。通常,您可以使用此包/依赖项来构建数据库客户端,以便在基于 swift-composable-architecture 的应用程序中使用。

安装

将此作为 swift 包安装到您的项目中。

import PackageDescription

let package = Package(
  ...
  dependencies: [
    .package(
      url: "https://github.com/m-housh/supabase-client-dependency.git",
      from: "0.4.0"
    )
  ],
  targets: [
    .target(
      name: "<My Target>",
      dependencies: [
        .product(name: "SupabaseDependencies", package: "supabase-client-dependency")
      ]
    )
  ]
)

基本用法

此包在依赖项上没有声明官方的 liveValue,因为其目的是在依赖于它的项目中设置 live value。它符合 TestDependencyKey 协议,并且有一个 unimplemented 版本,可以在测试中使用。

Todo 模型

一个基本的 todo 模型,作为文档的示例。

数据库模型的 SQL

create table if not exists todos (
  id uuid primary key default uuid_generate_v4(),
  description text not null,
  complete boolean not null default false,
  created_at timestamptz default (now() at time zone 'utc'::text) not null
);

swift 模型实现。

import Dependencies
import Foundation
import SupabaseDependencies

struct TodoModel: Codable, Equatable, Identifiable, Sendable {
  var id: UUID
  var createdAt: Date
  var description: String
  var isComplete: Bool = false
  
  enum CodingKeys: String, CodingKey {
    case id
    case createdAt = "created_at"
    case description
    case isComplete = "complete"
  }
}

Todo 路由集合

路由集合用于声明一组路由,通常用于数据库中的特定表。

@CasePathable
enum TodoRoute: RouteCollection {
  static var table: DatabaseRoute.Table { "todos" }

  case delete(id: TodoModel.ID)
  case fetch(filteredBy: [DatabaseRoute.Filter] = [], orderedBy: DatabaseRoute.Order? = nil)
  case fetchOne(id: TodoModel.ID)
  case save(TodoModel)

  // Provide the database route.
  public func route() async throws -> DatabaseRoute {
    switch self {
    case let .delete(id: id):
      return .delete(id: id, from: Self.table)

    case let .fetch(filters, order):
      return .fetch(from: Self.table, filters: filters, order: order)

    case let .fetchOne(id: id):
      return .fetchOne(id: id, from: Self.table)

    case let .save(todo):
      return try .upsert(todo, in: Self.table)
    }
  }

  static var fetch: Self { .fetch(filteredBy: [], orderedBy: nil) }

}

创建您的根数据库路由控制器。

一个路由集合,它持有所有您的单独路由集合,并且也符合 RouteCollection 协议。路由集合一致性是稍后在设置 live 依赖项时创建路由器所必需的。

@CasePathable
enum Routes: RouteCollection {

  case todos(TodoRoute)
  ...

  func route() async throws -> DatabaseRoute {
    switch self {
    case let .todos(todos):
      return try await todos.route()
    ...
    }
  }
}

设置 supabase 依赖项。

需要扩展 supabase 客户端依赖项以提供 live value。

extension DependencyValues {
  var supabase: SupabaseDependency<Routes> {
    get { self[SupabaseDependency<Routes>.self] }
    set { self[SupabaseDependency<Routes>.self] = newValue }
  }
}

extension SupabaseDependency<Routes>: DependencyKey {
  // Use the `.live(client:)` method with your supabase client configuration.
  static let liveValue: Self = .live(client: SupabaseClient(...))
}

使用 supabase 依赖项。

supabase 依赖项包含一个身份验证控制器,它提供了一些与 supabase 身份验证客户端交互的便捷方法。提供允许您覆盖当前用户、会话以及用户登录便捷方法的钩子。

func login(credentials: Credentials) async throws -> Session {
  @Dependency(\.supabase.auth) var auth
  return try await auth.login(credentials: credentials)
}

使用数据库路由器对数据库执行操作。

func fetchTodos() async throws -> [Todo] {
  @Dependency(\.supabase.router.todos)
  return try await todos(.fetch(orderBy: .descending("complete")))
}

func insertTodo(description: String, isComplete: Bool = false) -> Todo {
  @Dependency(\.supabase.router.todos)
  return try await todos(
    .save(
      TodoModel(
        createdAt: Date(),
        description: description,
        isComplete: isComplete
      )
    )
  )
}

请参阅 示例 项目以获取完整的可工作示例。

文档

完整的文档可以在这里查看

许可证

所有模块均在 MIT 许可证下发布。 有关详细信息,请参阅 LICENSE