Skip to content

Commit

Permalink
feat(storage): use Codable types (#120)
Browse files Browse the repository at this point in the history
* Start Codable support on Storage

* wip

* Use Request type

* Use default parameter value

* Fix Storage tests

* Remove old code

* Remove commented code
  • Loading branch information
grdsdev authored Oct 18, 2023
1 parent 641c4c0 commit 04c9725
Show file tree
Hide file tree
Showing 23 changed files with 553 additions and 469 deletions.
6 changes: 4 additions & 2 deletions Package.swift
Original file line number Diff line number Diff line change
Expand Up @@ -28,12 +28,14 @@ var package = Package(
.package(url: "https://github.com/pointfreeco/swift-snapshot-testing", from: "1.8.1"),
],
targets: [
.target(name: "_Helpers"),
.target(name: "Functions"),
.testTarget(name: "FunctionsTests", dependencies: ["Functions"]),
.target(
name: "GoTrue",
dependencies: [
.product(name: "KeychainAccess", package: "KeychainAccess")
"_Helpers",
.product(name: "KeychainAccess", package: "KeychainAccess"),
]
),
.testTarget(
Expand All @@ -56,7 +58,7 @@ var package = Package(
.testTarget(name: "PostgRESTIntegrationTests", dependencies: ["PostgREST"]),
.target(name: "Realtime"),
.testTarget(name: "RealtimeTests", dependencies: ["Realtime"]),
.target(name: "Storage"),
.target(name: "Storage", dependencies: ["_Helpers"]),
.testTarget(name: "StorageTests", dependencies: ["Storage"]),
.target(
name: "Supabase",
Expand Down
3 changes: 3 additions & 0 deletions Sources/GoTrue/GoTrueClient.swift
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
import Combine
import Foundation
@_spi(Internal) import _Helpers

public typealias AnyJSON = _Helpers.AnyJSON

#if canImport(FoundationNetworking)
import FoundationNetworking
Expand Down
50 changes: 0 additions & 50 deletions Sources/GoTrue/Internal/Request.swift

This file was deleted.

53 changes: 0 additions & 53 deletions Sources/GoTrue/Types.swift
Original file line number Diff line number Diff line change
Expand Up @@ -9,59 +9,6 @@ public enum AuthChangeEvent: String, Sendable {
case userDeleted = "USER_DELETED"
}

public enum AnyJSON: Hashable, Codable, Sendable {
case string(String)
case number(Double)
case object([String: AnyJSON])
case array([AnyJSON])
case bool(Bool)
case null

public var value: Any? {
switch self {
case let .string(string): return string
case let .number(double): return double
case let .object(dictionary): return dictionary
case let .array(array): return array
case let .bool(bool): return bool
case .null: return nil
}
}

public func encode(to encoder: Encoder) throws {
var container = encoder.singleValueContainer()
switch self {
case let .array(array): try container.encode(array)
case let .object(object): try container.encode(object)
case let .string(string): try container.encode(string)
case let .number(number): try container.encode(number)
case let .bool(bool): try container.encode(bool)
case .null: try container.encodeNil()
}
}

public init(from decoder: Decoder) throws {
let container = try decoder.singleValueContainer()
if let object = try? container.decode([String: AnyJSON].self) {
self = .object(object)
} else if let array = try? container.decode([AnyJSON].self) {
self = .array(array)
} else if let string = try? container.decode(String.self) {
self = .string(string)
} else if let bool = try? container.decode(Bool.self) {
self = .bool(bool)
} else if let number = try? container.decode(Double.self) {
self = .number(number)
} else if container.decodeNil() {
self = .null
} else {
throw DecodingError.dataCorrupted(
.init(codingPath: decoder.codingPath, debugDescription: "Invalid JSON value.")
)
}
}
}

public struct UserCredentials: Codable, Hashable, Sendable {
public var email: String?
public var password: String?
Expand Down
40 changes: 25 additions & 15 deletions Sources/Storage/Bucket.swift
Original file line number Diff line number Diff line change
@@ -1,28 +1,38 @@
public struct Bucket: Hashable {
import Foundation

public struct Bucket: Identifiable, Hashable, Codable {
public var id: String
public var name: String
public var owner: String
public var isPublic: Bool
public var createdAt: String
public var updatedAt: String

init?(from dictionary: [String: Any]) {
guard
let id = dictionary["id"] as? String,
let name = dictionary["name"] as? String,
let owner = dictionary["owner"] as? String,
let createdAt = dictionary["created_at"] as? String,
let updatedAt = dictionary["updated_at"] as? String,
let isPublic = dictionary["public"] as? Bool
else {
return nil
}
public var createdAt: Date
public var updatedAt: Date
public var allowedMimeTypes: [String]?
public var fileSizeLimit: Int?

public init(
id: String, name: String, owner: String, isPublic: Bool, createdAt: Date, updatedAt: Date,
allowedMimeTypes: [String]?,
fileSizeLimit: Int?
) {
self.id = id
self.name = name
self.owner = owner
self.isPublic = isPublic
self.createdAt = createdAt
self.updatedAt = updatedAt
self.allowedMimeTypes = allowedMimeTypes
self.fileSizeLimit = fileSizeLimit
}

enum CodingKeys: String, CodingKey {
case id
case name
case owner
case isPublic = "public"
case createdAt = "created_at"
case updatedAt = "updated_at"
case allowedMimeTypes = "allowed_mime_types"
case fileSizeLimit = "file_size_limit"
}
}
36 changes: 36 additions & 0 deletions Sources/Storage/Codable.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
//
// File.swift
//
//
// Created by Guilherme Souza on 18/10/23.
//

import Foundation

extension JSONEncoder {
public static let defaultStorageEncoder: JSONEncoder = {
JSONEncoder()
}()
}

extension JSONDecoder {
public static let defaultStorageDecoder: JSONDecoder = {
let decoder = JSONDecoder()
let formatter = ISO8601DateFormatter()
formatter.formatOptions = [.withInternetDateTime, .withFractionalSeconds]

decoder.dateDecodingStrategy = .custom { decoder in
let container = try decoder.singleValueContainer()
let string = try container.decode(String.self)

if let date = formatter.date(from: string) {
return date
}

throw DecodingError.dataCorruptedError(
in: container, debugDescription: "Invalid date format: \(string)")
}

return decoder
}()
}
48 changes: 26 additions & 22 deletions Sources/Storage/FileObject.swift
Original file line number Diff line number Diff line change
@@ -1,37 +1,41 @@
public struct FileObject {
import Foundation
import _Helpers

public struct FileObject: Identifiable, Codable {
public var name: String
public var bucketId: String?
public var owner: String?
public var id: String
public var updatedAt: String
public var createdAt: String
public var lastAccessedAt: String
public var metadata: [String: Any]
public var updatedAt: Date
public var createdAt: Date
public var lastAccessedAt: Date
public var metadata: [String: AnyJSON]
public var buckets: Bucket?

public init?(from dictionary: [String: Any]) {
guard
let name = dictionary["name"] as? String,
let id = dictionary["id"] as? String,
let updatedAt = dictionary["updated_at"] as? String,
let createdAt = dictionary["created_at"] as? String,
let lastAccessedAt = dictionary["last_accessed_at"] as? String,
let metadata = dictionary["metadata"] as? [String: Any]
else {
return nil
}

public init(
name: String, bucketId: String? = nil, owner: String? = nil, id: String, updatedAt: Date,
createdAt: Date, lastAccessedAt: Date, metadata: [String: AnyJSON], buckets: Bucket? = nil
) {
self.name = name
self.bucketId = dictionary["bucket_id"] as? String
self.owner = dictionary["owner"] as? String
self.bucketId = bucketId
self.owner = owner
self.id = id
self.updatedAt = updatedAt
self.createdAt = createdAt
self.lastAccessedAt = lastAccessedAt
self.metadata = metadata
self.buckets = buckets
}

if let buckets = dictionary["buckets"] as? [String: Any] {
self.buckets = Bucket(from: buckets)
}
enum CodingKeys: String, CodingKey {
case name
case bucketId = "bucket_id"
case owner
case id
case updatedAt = "updated_at"
case createdAt = "created_at"
case lastAccessedAt = "last_accessed_at"
case metadata
case buckets
}
}
10 changes: 8 additions & 2 deletions Sources/Storage/SearchOptions.swift
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
public struct SearchOptions {
public struct SearchOptions: Encodable {
public let prefix: String

/// The number of files you want to be returned.
public var limit: Int?

Expand All @@ -11,7 +13,11 @@ public struct SearchOptions {
/// The search string to filter files by.
public var search: String?

public init(limit: Int? = nil, offset: Int? = nil, sortBy: SortBy? = nil, search: String? = nil) {
public init(
prefix: String = "", limit: Int? = nil, offset: Int? = nil, sortBy: SortBy? = nil,
search: String? = nil
) {
self.prefix = prefix
self.limit = limit
self.offset = offset
self.sortBy = sortBy
Expand Down
18 changes: 18 additions & 0 deletions Sources/Storage/SignedURL.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
import Foundation

public struct SignedURL: Decodable {
/// An optional error message.
public var error: String?

/// The signed url.
public var signedURL: URL

/// The path of the file.
public var path: String

public init(error: String? = nil, signedURL: URL, path: String) {
self.error = error
self.signedURL = signedURL
self.path = path
}
}
2 changes: 1 addition & 1 deletion Sources/Storage/SortBy.swift
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
public struct SortBy {
public struct SortBy: Encodable {
public var column: String?
public var order: String?

Expand Down
Loading

0 comments on commit 04c9725

Please sign in to comment.