Skip to content
Draft
Show file tree
Hide file tree
Changes from all 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
2 changes: 1 addition & 1 deletion .github/ISSUE_TEMPLATE/bug_report.yml
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ body:
attributes:
label: Swift Version
description: What version of Swift are you using?
placeholder: ex. 5.10
placeholder: ex. 6.0
validations:
required: true

Expand Down
36 changes: 1 addition & 35 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@ jobs:
name: xcodebuild (macOS latest)
runs-on: macos-15
strategy:
fail-fast: false
matrix:
command: [test, ""]
platform: [IOS, MACOS]
Expand Down Expand Up @@ -81,41 +82,6 @@ jobs:
github-token: ${{ secrets.GITHUB_TOKEN }}
file: lcov.info

macos-legacy:
name: xcodebuild (macOS legacy)
runs-on: macos-14
strategy:
matrix:
command: [test, ""]
platform: [IOS, MACOS, MAC_CATALYST]
xcode: ["15.4"]
include:
- { command: test, skip_release: 1 }
steps:
- uses: actions/checkout@v5
- name: Select Xcode ${{ matrix.xcode }}
run: sudo xcode-select -s /Applications/Xcode_${{ matrix.xcode }}.app
- name: List available devices
run: xcrun simctl list devices available
- name: Cache derived data
uses: actions/cache@v4
with:
path: |
~/.derivedData
key: |
deriveddata-xcodebuild-${{ matrix.platform }}-${{ matrix.xcode }}-${{ matrix.command }}-${{ hashFiles('**/Sources/**/*.swift', '**/Tests/**/*.swift') }}
restore-keys: |
deriveddata-xcodebuild-${{ matrix.platform }}-${{ matrix.xcode }}-${{ matrix.command }}-
- name: Set IgnoreFileSystemDeviceInodeChanges flag
run: defaults write com.apple.dt.XCBuild IgnoreFileSystemDeviceInodeChanges -bool YES
- name: Update mtime for incremental builds
uses: chetan/git-restore-mtime-action@v2
- name: Debug
run: make XCODEBUILD_ARGUMENT="${{ matrix.command }}" CONFIG=Debug PLATFORM="${{ matrix.platform }}" xcodebuild
- name: Release
if: matrix.skip_release != '1'
run: make XCODEBUILD_ARGUMENT="${{ matrix.command }}" CONFIG=Release PLATFORM="${{ matrix.platform }}" xcodebuild

spm:
runs-on: macos-15
strategy:
Expand Down
34 changes: 16 additions & 18 deletions Examples/Examples/Profile/UserIdentityList.swift
Original file line number Diff line number Diff line change
Expand Up @@ -237,30 +237,28 @@ struct UserIdentityList: View {
}
.id(id)
.navigationTitle("Linked Identities")
#if swift(>=5.10)
.toolbar {
ToolbarItem(placement: .primaryAction) {
if !providers.isEmpty {
Menu {
ForEach(providers) { provider in
Button {
Task {
await linkProvider(provider)
}
} label: {
Label(
provider.rawValue.capitalized,
systemImage: iconForProvider(provider.rawValue)
)
.toolbar {
ToolbarItem(placement: .primaryAction) {
if !providers.isEmpty {
Menu {
ForEach(providers) { provider in
Button {
Task {
await linkProvider(provider)
}
} label: {
Label(
provider.rawValue.capitalized,
systemImage: iconForProvider(provider.rawValue)
)
}
} label: {
Label("Link Account", systemImage: "plus")
}
} label: {
Label("Link Account", systemImage: "plus")
}
}
}
#endif
}
}

private func iconForProvider(_ provider: String) -> String {
Expand Down
2 changes: 1 addition & 1 deletion Examples/Package.swift
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// swift-tools-version:5.7
// swift-tools-version:6.0
// The swift-tools-version declares the minimum version of Swift required to build this package.

import Foundation
Expand Down
2 changes: 1 addition & 1 deletion Examples/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -171,7 +171,7 @@ Features:

## Prerequisites

- Xcode 15.0 or later
- Xcode 16.0 or later
- iOS 17.0+ / macOS 14.0+ or later
- [Supabase CLI](https://supabase.com/docs/guides/cli) installed

Expand Down
15 changes: 8 additions & 7 deletions Package.swift
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// swift-tools-version:5.10
// swift-tools-version:6.0
// The swift-tools-version declares the minimum version of Swift required to build this package.

import Foundation
Expand All @@ -7,11 +7,11 @@ import PackageDescription
let package = Package(
name: "Supabase",
platforms: [
.iOS(.v13),
.macCatalyst(.v13),
.macOS(.v10_15),
.watchOS(.v6),
.tvOS(.v13),
.iOS(.v16),
.macCatalyst(.v16),
.macOS(.v13),
.watchOS(.v9),
.tvOS(.v16),
],
products: [
.library(name: "Auth", targets: ["Auth"]),
Expand Down Expand Up @@ -204,7 +204,8 @@ let package = Package(
"Mocker",
]
),
]
],
swiftLanguageModes: [.v6]
)

for target in package.targets where !target.isTest {
Expand Down
12 changes: 6 additions & 6 deletions Package@swift-6.1.swift
Original file line number Diff line number Diff line change
Expand Up @@ -7,11 +7,11 @@ import PackageDescription
let package = Package(
name: "Supabase",
platforms: [
.iOS(.v13),
.macCatalyst(.v13),
.macOS(.v10_15),
.watchOS(.v6),
.tvOS(.v13),
.iOS(.v16),
.macCatalyst(.v16),
.macOS(.v13),
.watchOS(.v9),
.tvOS(.v16),
],
products: [
.library(name: "Auth", targets: ["Auth"]),
Expand Down Expand Up @@ -204,7 +204,7 @@ let package = Package(
]
),
],
swiftLanguageModes: [.v5]
swiftLanguageModes: [.v6]
)

for target in package.targets where !target.isTest {
Expand Down
6 changes: 3 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,9 +10,9 @@ Supabase SDK for Swift. Mirrors the design of [supabase-js](https://github.com/s
## Usage

### Requirements
- iOS 13.0+ / macOS 10.15+ / tvOS 13+ / watchOS 6+ / visionOS 1+
- Xcode 15.3+
- Swift 5.10+
- iOS 16.0+ / macOS 13+ / tvOS 16+ / watchOS 9+ / visionOS 1+
- Xcode 16.0+
- Swift 6.0+

> [!IMPORTANT]
> Check the [Support Policy](#support-policy) to learn when dropping Xcode, Swift, and platform versions will not be considered a **breaking change**.
Expand Down
6 changes: 2 additions & 4 deletions Sources/Auth/AuthClient.swift
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,7 @@ private actor GlobalJWKSCache {
private let globalJWKSCache = GlobalJWKSCache()

public actor AuthClient {
static var globalClientID = 0
static let globalClientID = LockIsolated(0)
nonisolated let clientID: AuthClientID

nonisolated private var api: APIClient { Dependencies[clientID].api }
Expand Down Expand Up @@ -122,8 +122,7 @@ public actor AuthClient {
/// - Parameters:
/// - configuration: The client configuration.
public init(configuration: Configuration) {
AuthClient.globalClientID += 1
clientID = AuthClient.globalClientID
clientID = AuthClient.globalClientID.withValue { $0 += 1; return $0 }

Dependencies[clientID] = Dependencies(
configuration: configuration,
Expand Down Expand Up @@ -702,7 +701,6 @@ public actor AuthClient {
/// - Note: This method support the PKCE flow.
/// - Warning: Do not call `start()` on the `ASWebAuthenticationSession` object inside the
/// `configure` closure, as the method implementation calls it already.
@available(watchOS 6.2, tvOS 16.0, *)
@discardableResult
public func signInWithOAuth(
provider: Provider,
Expand Down
130 changes: 0 additions & 130 deletions Sources/Auth/AuthError.swift
Original file line number Diff line number Diff line change
Expand Up @@ -118,129 +118,6 @@ extension ErrorCode {
}

public enum AuthError: LocalizedError, Equatable {
@available(
*,
deprecated,
message:
"Error used to be thrown when no exp claim was found in JWT during setSession(accessToken:refreshToken:) method."
)
case missingExpClaim

@available(
*,
deprecated,
message:
"Error used to be thrown when provided JWT wasn't valid during setSession(accessToken:refreshToken:) method."
)
case malformedJWT

@available(*, deprecated, renamed: "sessionMissing")
public static var sessionNotFound: AuthError { .sessionMissing }

/// Error thrown during PKCE flow.
@available(
*,
deprecated,
renamed: "pkceGrantCodeExchange",
message: "Error was grouped in `pkceGrantCodeExchange`, please use it instead of `pkce`."
)
public static func pkce(_ reason: PKCEFailureReason) -> AuthError {
switch reason {
case .codeVerifierNotFound:
.pkceGrantCodeExchange(message: "A code verifier wasn't found in PKCE flow.")
case .invalidPKCEFlowURL:
.pkceGrantCodeExchange(message: "Not a valid PKCE flow url.")
}
}

@available(*, deprecated, message: "Use `pkceGrantCodeExchange` instead.")
public enum PKCEFailureReason: Sendable {
/// Code verifier not found in the URL.
case codeVerifierNotFound

/// Not a valid PKCE flow URL.
case invalidPKCEFlowURL
}

@available(*, deprecated, renamed: "implicitGrantRedirect")
public static var invalidImplicitGrantFlowURL: AuthError {
.implicitGrantRedirect(message: "Not a valid implicit grant flow url.")
}

@available(
*,
deprecated,
message:
"This error is never thrown, if you depend on it, you can remove the logic as it never happens."
)
case missingURL

@available(
*,
deprecated,
message:
"Error used to be thrown on methods which required a valid redirect scheme, such as signInWithOAuth. This is now considered a programming error an a assertion is triggered in case redirect scheme isn't provided."
)
case invalidRedirectScheme

@available(
*,
deprecated,
renamed: "api(message:errorCode:underlyingData:underlyingResponse:)"
)
public static func api(_ error: APIError) -> AuthError {
let message = error.msg ?? error.error ?? error.errorDescription ?? "Unexpected API error."
if let weakPassword = error.weakPassword {
return .weakPassword(message: message, reasons: weakPassword.reasons)
}

return .api(
message: message,
errorCode: .unknown,
underlyingData: (try? AuthClient.Configuration.jsonEncoder.encode(error)) ?? Data(),
underlyingResponse: HTTPURLResponse(
url: defaultAuthURL,
statusCode: error.code ?? 500,
httpVersion: nil,
headerFields: nil
)!
)
}

/// An error returned by the API.
@available(
*,
deprecated,
renamed: "api(message:errorCode:underlyingData:underlyingResponse:)"
)
public struct APIError: Error, Codable, Sendable, Equatable {
/// A basic message describing the problem with the request. Usually missing if
/// ``AuthError/APIError/error`` is present.
public var msg: String?

/// The HTTP status code. Usually missing if ``AuthError/APIError/error`` is present.
public var code: Int?

/// Certain responses will contain this property with the provided values.
///
/// Usually one of these:
/// - `invalid_request`
/// - `unauthorized_client`
/// - `access_denied`
/// - `server_error`
/// - `temporarily_unavailable`
/// - `unsupported_otp_type`
public var error: String?

/// Certain responses that have an ``AuthError/APIError/error`` property may have this property
/// which describes the error.
public var errorDescription: String?

/// Only returned when signing up if the password used is too weak. Inspect the
/// ``WeakPassword/reasons`` and ``AuthError/APIError/msg`` property to identify the causes.
public var weakPassword: WeakPassword?
}

/// Error thrown when a session is required to proceed, but none was found, either thrown by the client, or returned by the server.
case sessionMissing

Expand Down Expand Up @@ -274,11 +151,6 @@ public enum AuthError: LocalizedError, Equatable {
let .implicitGrantRedirect(message),
let .jwtVerificationFailed(message):
message
// Deprecated cases
case .missingExpClaim: "Missing expiration claim in the access token."
case .malformedJWT: "A malformed JWT received."
case .invalidRedirectScheme: "Invalid redirect scheme."
case .missingURL: "Missing URL."
}
}

Expand All @@ -289,8 +161,6 @@ public enum AuthError: LocalizedError, Equatable {
case let .api(_, errorCode, _, _): errorCode
case .pkceGrantCodeExchange, .implicitGrantRedirect: .unknown
case .jwtVerificationFailed: .invalidJWT
// Deprecated cases
case .missingExpClaim, .malformedJWT, .invalidRedirectScheme, .missingURL: .unknown
}
}

Expand Down
Loading
Loading