Skip to content

Commit

Permalink
feat(storage): add metadata, info and exists method
Browse files Browse the repository at this point in the history
  • Loading branch information
grdsdev committed Aug 22, 2024
1 parent 42460a0 commit 58ef375
Show file tree
Hide file tree
Showing 2 changed files with 60 additions and 6 deletions.
5 changes: 4 additions & 1 deletion Sources/Storage/StorageApi.swift
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,10 @@ public class StorageApi: @unchecked Sendable {
let response = try await http.send(request)

guard (200 ..< 300).contains(response.statusCode) else {
if let error = try? configuration.decoder.decode(StorageError.self, from: response.data) {
if let error = try? configuration.decoder.decode(
StorageError.self,
from: response.data
) {
throw error
}

Expand Down
61 changes: 56 additions & 5 deletions Sources/Storage/StorageFileApi.swift
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,12 @@ let DEFAULT_SEARCH_OPTIONS = SearchOptions(
)
)

private let defaultFileOptions = FileOptions(
cacheControl: "3600",
contentType: "text/plain;charset=UTF-8",
upsert: false
)

/// Supabase Storage File API
public class StorageFileApi: StorageApi, @unchecked Sendable {
/// The bucket id to operate on.
Expand All @@ -33,20 +39,37 @@ public class StorageFileApi: StorageApi, @unchecked Sendable {
let signedURL: URL
}

private func encodeMetadata(_ metadata: JSONObject) -> Data {
let encoder = AnyJSON.encoder
return (try? encoder.encode(metadata)) ?? "{}".data(using: .utf8)!
}

func uploadOrUpdate(
method: HTTPMethod,
path: String,
formData: MultipartFormData,
options: FileOptions
options: FileOptions?
) async throws -> FileUploadResponse {
var headers = HTTPHeaders()

let options = options ?? defaultFileOptions
let metadata = options.metadata

if method == .post {
headers.update(name: "x-upsert", value: "\(options.upsert)")
}

headers["duplex"] = options.duplex

if let metadata {
formData.append(encodeMetadata(metadata), withName: "metadata")
}

formData.append(
options.cacheControl.data(using: .utf8)!,
withName: "cacheControl"
)

struct UploadResponse: Decodable {
let Key: String
let Id: String
Expand Down Expand Up @@ -404,6 +427,27 @@ public class StorageFileApi: StorageApi, @unchecked Sendable {
.decoded(decoder: configuration.decoder)
}

/// Checks the existence of file.
public func exists(path: String) async throws -> Bool {
do {
let response = try await execute(
HTTPRequest(
url: configuration.url.appendingPathComponent("object/\(bucketId)/\(path)"),
method: .head
)
)
return true
} catch {
if let error = error as? StorageError, let statusCode = error.statusCode,
["400", "404"].contains(statusCode)
{
return false
}

throw error
}
}

/// Returns a public url for an asset.
/// - Parameters:
/// - path: The file path to the asset. For example `folder/image.png`.
Expand Down Expand Up @@ -517,13 +561,13 @@ public class StorageFileApi: StorageApi, @unchecked Sendable {
_ path: String,
token: String,
data: Data,
options: FileOptions = FileOptions()
options: FileOptions? = nil
) async throws -> SignedURLUploadResponse {
let formData = MultipartFormData()
formData.append(
data,
withName: path.fileName,
mimeType: options.contentType ?? mimeType(forPathExtension: path.pathExtension)
mimeType: options?.contentType ?? mimeType(forPathExtension: path.pathExtension)
)
return try await _uploadToSignedURL(
path: path,
Expand All @@ -545,7 +589,7 @@ public class StorageFileApi: StorageApi, @unchecked Sendable {
_ path: String,
token: String,
fileURL: Data,
options: FileOptions = FileOptions()
options: FileOptions? = nil
) async throws -> SignedURLUploadResponse {
let formData = MultipartFormData()
formData.append(fileURL, withName: path.fileName)
Expand All @@ -561,13 +605,20 @@ public class StorageFileApi: StorageApi, @unchecked Sendable {
path: String,
token: String,
formData: MultipartFormData,
options: FileOptions
options: FileOptions?
) async throws -> SignedURLUploadResponse {
let options = options ?? defaultFileOptions
var headers = HTTPHeaders([
"x-upsert": "\(options.upsert)",
])
headers["duplex"] = options.duplex

if let metadata = options.metadata {
formData.append(encodeMetadata(metadata), withName: "metadata")
}

formData.append(options.cacheControl.data(using: .utf8)!, withName: "cacheControl")

struct UploadResponse: Decodable {
let Key: String
}
Expand Down

0 comments on commit 58ef375

Please sign in to comment.