Skip to content
Merged
Show file tree
Hide file tree
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions Package.swift
Original file line number Diff line number Diff line change
Expand Up @@ -181,6 +181,7 @@ let package = Package(
name: "SupabaseTests",
dependencies: [
.product(name: "CustomDump", package: "swift-custom-dump"),
.product(name: "InlineSnapshotTesting", package: "swift-snapshot-testing"),
"Supabase",
]
),
Expand Down
59 changes: 59 additions & 0 deletions Sources/Helpers/Version.swift
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import Foundation
import XCTestDynamicOverlay

private let _version = "2.27.0" // {x-release-please-version}
Expand All @@ -7,3 +8,61 @@ private let _version = "2.27.0" // {x-release-please-version}
#else
package let version = _version
#endif

private let _platform: String? = {
#if os(macOS)
return "macOS"
#elseif os(visionOS)
return "visionOS"
#elseif os(iOS)
#if targetEnvironment(macCatalyst)
return "macCatalyst"
#else
if #available(iOS 14.0, *), ProcessInfo.processInfo.isiOSAppOnMac {
return "iOSAppOnMac"
}
return "iOS"
#endif
#elseif os(watchOS)
return "watchOS"
#elseif os(tvOS)
return "tvOS"
#elseif os(Android)
return "Android"
#elseif os(Linux)
return "Linux"
#elseif os(Windows)
return "Windows"
#else
return nil
#endif
}()

private let _platformVersion: String? = {
#if os(macOS) || os(iOS) || os(tvOS) || os(watchOS) || os(Windows)
let majorVersion = ProcessInfo.processInfo.operatingSystemVersion.majorVersion
let minorVersion = ProcessInfo.processInfo.operatingSystemVersion.minorVersion
let patchVersion = ProcessInfo.processInfo.operatingSystemVersion.patchVersion
return "\(majorVersion).\(minorVersion).\(patchVersion)"
#elseif os(Linux) || os(Android)
if let version = try? String(contentsOfFile: "/proc/version") {
version.trimmingCharacters(in: .whitespacesAndNewlines)
} else {
nil
}
#else
nil
#endif
}()

#if DEBUG
package let platform = isTesting ? "macOS" : _platform
#else
package let platform = _platform
#endif

#if DEBUG
package let platformVersion = isTesting ? "0.0.0" : _platformVersion
#else
package let platformVersion = _platformVersion
#endif
25 changes: 25 additions & 0 deletions Sources/Supabase/Constants.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
//
// Constants.swift
// Supabase
//
// Created by Guilherme Souza on 06/03/25.
//

import Foundation
import Helpers

let defaultHeaders: [String: String] = {
var headers = [
"X-Client-Info": "supabase-swift/\(version)"
]

if let platform {
headers["X-Supabase-Client-Platform"] = platform
}

if let platformVersion {
headers["X-Supabase-Client-Platform-Version"] = platformVersion
}

return headers
}()
18 changes: 10 additions & 8 deletions Sources/Supabase/SupabaseClient.swift
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,6 @@ public typealias SupabaseLogger = Helpers.SupabaseLogger
public typealias SupabaseLogLevel = Helpers.SupabaseLogLevel
public typealias SupabaseLogMessage = Helpers.SupabaseLogMessage

let version = Helpers.version

/// Supabase Client.
public final class SupabaseClient: Sendable {
let options: SupabaseClientOptions
Expand Down Expand Up @@ -163,12 +161,16 @@ public final class SupabaseClient: Sendable {
databaseURL = supabaseURL.appendingPathComponent("/rest/v1")
functionsURL = supabaseURL.appendingPathComponent("/functions/v1")

_headers = HTTPFields([
"X-Client-Info": "supabase-swift/\(version)",
"Authorization": "Bearer \(supabaseKey)",
"Apikey": supabaseKey,
])
.merging(with: HTTPFields(options.global.headers))
_headers = HTTPFields(defaultHeaders)
.merging(
with: HTTPFields(
[
"Authorization": "Bearer \(supabaseKey)",
"Apikey": supabaseKey,
]
)
)
.merging(with: HTTPFields(options.global.headers))

// default storage key uses the supabase project ref as a namespace
let defaultStorageKey = "sb-\(supabaseURL.host!.split(separator: ".")[0])-auth-token"
Expand Down
30 changes: 20 additions & 10 deletions Tests/SupabaseTests/SupabaseClientTests.swift
Original file line number Diff line number Diff line change
@@ -1,10 +1,13 @@
@testable import Auth
import CustomDump
@testable import Functions
import InlineSnapshotTesting
import IssueReporting
import SnapshotTestingCustomDump
import XCTest

@testable import Auth
@testable import Functions
@testable import Realtime
@testable import Supabase
import XCTest

final class AuthLocalStorageMock: AuthLocalStorage {
func store(key _: String, value _: Data) throws {}
Expand Down Expand Up @@ -61,16 +64,22 @@ final class SupabaseClientTests: XCTestCase {
"https://project-ref.supabase.co/functions/v1"
)

XCTAssertEqual(
client.headers,
assertInlineSnapshot(of: client.headers, as: .customDump) {
"""
[
"X-Client-Info": "supabase-swift/\(Supabase.version)",
"Apikey": "ANON_KEY",
"header_field": "header_value",
"Authorization": "Bearer ANON_KEY",
"X-Client-Info": "supabase-swift/0.0.0",
"X-Supabase-Client-Platform": "macOS",
"X-Supabase-Client-Platform-Version": "0.0.0",
"header_field": "header_value"
]
)
expectNoDifference(client._headers.dictionary, client.headers)
"""
}
expectNoDifference(client.headers, client.auth.configuration.headers)
expectNoDifference(client.headers, client.functions.headers.dictionary)
expectNoDifference(client.headers, client.storage.configuration.headers)
expectNoDifference(client.headers, client.rest.configuration.headers)

XCTAssertEqual(client.functions.region, "ap-northeast-1")

Expand All @@ -79,7 +88,8 @@ final class SupabaseClientTests: XCTestCase {

let realtimeOptions = client.realtimeV2.options
let expectedRealtimeHeader = client._headers.merging(with: [
.init("custom_realtime_header_key")!: "custom_realtime_header_value"]
.init("custom_realtime_header_key")!: "custom_realtime_header_value"
]
)
expectNoDifference(realtimeOptions.headers, expectedRealtimeHeader)
XCTAssertIdentical(realtimeOptions.logger as? Logger, logger)
Expand Down
Loading