diff --git a/README.md b/README.md
index a3cd29f08a3..d63f425b65d 100644
--- a/README.md
+++ b/README.md
@@ -111,6 +111,15 @@ Our approach for client libraries is modular. Each sub-library is a standalone i
| Godot Engine (GDScript) |
supabase-gdscript |
diff --git a/apps/docs/components/Navigation/NavigationMenu/NavigationMenu.constants.ts b/apps/docs/components/Navigation/NavigationMenu/NavigationMenu.constants.ts
index b80ebbd89e3..62ed67d0656 100644
--- a/apps/docs/components/Navigation/NavigationMenu/NavigationMenu.constants.ts
+++ b/apps/docs/components/Navigation/NavigationMenu/NavigationMenu.constants.ts
@@ -112,6 +112,12 @@ export const HOMEPAGE_MENU_ITEMS: HomepageMenuItems = [
href: '/reference/dart/introduction',
level: 'reference_dart',
},
+ {
+ label: 'Swift',
+ icon: 'reference-swift',
+ href: '/reference/swift/introduction',
+ level: 'reference_swift',
+ },
{
label: 'Python',
icon: 'reference-python',
@@ -126,13 +132,6 @@ export const HOMEPAGE_MENU_ITEMS: HomepageMenuItems = [
level: 'reference_csharp',
community: true,
},
- {
- label: 'Swift',
- icon: 'reference-swift',
- href: '/reference/swift/introduction',
- level: 'reference_swift',
- community: true,
- },
{
label: 'Kotlin',
icon: 'reference-kotlin',
diff --git a/apps/docs/content/guides/api/rest/client-libs.mdx b/apps/docs/content/guides/api/rest/client-libs.mdx
index f14d2f49bbd..15f03b0d442 100644
--- a/apps/docs/content/guides/api/rest/client-libs.mdx
+++ b/apps/docs/content/guides/api/rest/client-libs.mdx
@@ -13,6 +13,7 @@ Supabase provides client libraries for the REST and Realtime APIs. Some librarie
| --------------------- | ---------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------- |
| Javascript/Typescript | [supabase-js](https://github.com/supabase/supabase-js) | [Docs](https://supabase.com/docs/reference/javascript/introduction) |
| Dart/Flutter | [supabase-flutter](https://github.com/supabase/supabase-flutter/tree/main/packages/supabase_flutter) | [Docs](https://supabase.com/docs/reference/dart/introduction) |
+| Swift | [supabase-swift](https://github.com/supabase/supabase-swift) | [Docs](https://supabase.com/docs/reference/swift/introduction) |
## Community libraries
@@ -23,5 +24,4 @@ Supabase provides client libraries for the REST and Realtime APIs. Some librarie
| Kotlin | [supabase-kt](https://github.com/supabase-community/supabase-kt) | [Docs](https://supabase.com/docs/reference/kotlin/introduction) |
| Python | [supabase-py](https://github.com/supabase-community/supabase-py) | [Docs](https://supabase.com/docs/reference/python/initializing) |
| Ruby | [supabase-rb](https://github.com/supabase-community/supabase-rb) | |
-| Swift | [supabase-swift](https://github.com/supabase-community/supabase-swift) | [Docs](https://supabase.com/docs/reference/swift/introduction) |
| Godot Engine (GDScript) | [supabase-gdscript](https://github.com/supabase-community/godot-engine.supabase) | |
diff --git a/apps/docs/content/guides/getting-started/tutorials/with-swift.mdx b/apps/docs/content/guides/getting-started/tutorials/with-swift.mdx
index 6c110b51b6e..e26045321ce 100644
--- a/apps/docs/content/guides/getting-started/tutorials/with-swift.mdx
+++ b/apps/docs/content/guides/getting-started/tutorials/with-swift.mdx
@@ -23,9 +23,9 @@ Let's start building the SwiftUI app from scratch.
Open Xcode and create a new SwiftUI project.
-Add the [supabase-swift](https://github.com/supabase-community/supabase-swift) dependency.
+Add the [supabase-swift](https://github.com/supabase/supabase-swift) dependency.
-Add the `https://github.com/supabase-community/supabase-swift` package to your app. For instructions, see the [Apple tutorial on adding package dependencies](https://developer.apple.com/documentation/xcode/adding-package-dependencies-to-your-app).
+Add the `https://github.com/supabase/supabase-swift` package to your app. For instructions, see the [Apple tutorial on adding package dependencies](https://developer.apple.com/documentation/xcode/adding-package-dependencies-to-your-app).
Create a helper file to initialize the Supabase client.
You need the API URL and the `anon` key that you copied [earlier](#get-the-api-keys).
diff --git a/apps/docs/docs/ref/swift/installing.mdx b/apps/docs/docs/ref/swift/installing.mdx
new file mode 100644
index 00000000000..cbc57f06a7b
--- /dev/null
+++ b/apps/docs/docs/ref/swift/installing.mdx
@@ -0,0 +1,63 @@
+---
+id: installing
+title: 'Installing'
+slug: installing
+custom_edit_url: https://github.com/supabase/supabase/edit/master/web/spec/supabase.yml
+---
+
+### Install using Swift Package Manager
+
+
+
+
+ You can install Supabase package using Swift Package Manager.
+
+ The package exposes multiple libraries, you can choose between adding all of them using Supabase, or some of:
+
+ - `Auth`
+ - `Realtime`
+ - `Postgrest`
+ - `Functions`
+ - `Storage`
+
+
+
+
+
+
+
+
+ ```swift
+ let package = Package(
+ ...
+ dependencies: [
+ ...
+ .package(
+ url: "https://github.com/supabase/supabase-swift.git",
+ from: "2.0.0"
+ ),
+ ],
+ targets: [
+ .target(
+ name: "YourTargetName",
+ dependencies: [
+ .product(
+ name: "Supabase", // Auth, Realtime, Postgrest, Functions, or Storage
+ package: "supabase-swift"
+ ),
+ ]
+ )
+ ]
+ )
+ ```
+
+
+
+
+
+
diff --git a/apps/docs/docs/ref/swift/introduction.mdx b/apps/docs/docs/ref/swift/introduction.mdx
index 07f405736fe..dadc4490275 100644
--- a/apps/docs/docs/ref/swift/introduction.mdx
+++ b/apps/docs/docs/ref/swift/introduction.mdx
@@ -8,25 +8,13 @@ hideTitle: true
Swift Client Library
-
- @supabase-community/supabase-swift
-
+ @supabase/supabase-swift
{/* prettier-ignore */}
- This reference documents every object and method available in Supabase's Swift library, [supabase-swift](https://github.com/supabase-community/supabase-swift). You can use supabase-swift to interact with your Postgres database, listen to database changes, invoke Deno Edge Functions, build login and user management functionality, and manage large files.
-
- We also provide a [supabase](https://pub.dev/packages/supabase) package for non-Swift projects.
-
-
-
-{/* prettier-ignore */}
-
-The Swift client library is created and maintained by the Supabase community, and is not an official library. Please be tolerant of areas where the library is still being developed, and β as with all the libraries β feel free to contribute wherever you find issues.
-
-Huge thanks to official maintainers, [Guilherme](https://github.com/grdsdev) and [Maail](https://github.com/maail).
+ This reference documents every object and method available in Supabase's Swift library, [supabase-swift](https://github.com/supabase/supabase-swift). You can use supabase-swift to interact with your Postgres database, listen to database changes, invoke Deno Edge Functions, build login and user management functionality, and manage large files.
diff --git a/apps/docs/spec/common-client-libs-sections.json b/apps/docs/spec/common-client-libs-sections.json
index 5ee520ce08a..6a44fb3c877 100644
--- a/apps/docs/spec/common-client-libs-sections.json
+++ b/apps/docs/spec/common-client-libs-sections.json
@@ -33,6 +33,7 @@
"reference_python_v2",
"reference_csharp_v0",
"reference_swift_v1",
+ "reference_swift_v2",
"reference_kotlin_v1",
"reference_kotlin_v2"
]
@@ -48,6 +49,7 @@
"reference_python_v2",
"reference_csharp_v0",
"reference_swift_v1",
+ "reference_swift_v2",
"reference_kotlin_v1",
"reference_kotlin_v2"
]
@@ -986,6 +988,7 @@
"reference_python_v2",
"reference_csharp_v0",
"reference_swift_v1",
+ "reference_swift_v2",
"reference_kotlin_v1",
"reference_kotlin_v2"
],
diff --git a/apps/docs/spec/supabase_swift_v2.yml b/apps/docs/spec/supabase_swift_v2.yml
index 5cfd133983b..43fd69fb404 100644
--- a/apps/docs/spec/supabase_swift_v2.yml
+++ b/apps/docs/spec/supabase_swift_v2.yml
@@ -92,7 +92,7 @@ functions:
- To fetch the currently logged-in user, refer to [`getUser()`](/docs/reference/swift/get-user).
examples:
- id: sign-up
- name: Sign up
+ name: Sign up with email and password
isSpotlight: true
code: |
```swift
@@ -101,6 +101,30 @@ functions:
password: "example-password"
)
```
+ - id: sign-up-phone
+ name: Sign up with a phone number and password (SMS)
+ isSpotlight: true
+ code: |
+ ```swift
+ try await supabase.auth.signUp(
+ phone: "123456789",
+ password: "example-password",
+ channel: "sms"
+ )
+ ```
+ - id: sign-up-phone-whatsapp
+ name: Sign up with a phone number and password (whatsapp)
+ isSpotlight: true
+ description: |
+ The user will be sent a WhatsApp message which contains a OTP. By default, a given user can only request a OTP once every 60 seconds. Note that a user will need to have a valid WhatsApp account that is linked to Twilio in order to use this feature.
+ code: |
+ ```swift
+ try await supabase.auth.signUp(
+ phone: "123456789",
+ password: "example-password",
+ channel: "whatsapp"
+ )
+ ```
- id: sign-up-with-additional-user-metadata
name: Sign up with additional user metadata
isSpotlight: false
@@ -120,6 +144,7 @@ functions:
- id: sign-up-with-redirect
name: Sign up with a redirect URL
description: |
+ - You can provide a default redirect URL when initializing the client.
- See [redirect URLs and wildcards](/docs/guides/auth/overview#redirect-urls-and-wildcards) to add additional redirect URLs to your project.
code: |
```swift
@@ -129,6 +154,69 @@ functions:
redirectTo: URL(string: "https://example.com/welcome")!
)
```
+ - id: on-auth-state-change
+ title: "onAuthStateChange()"
+ notes: |
+ - Subscribes to important events occurring on the user's session.
+ - Emitted events:
+ - `INITIAL_SESSION`
+ - Emitted right after the Supabase client is constructed and the initial session from storage is loaded.
+ - `SIGNED_IN`
+ - Emitted each time a user session is confirmed or re-established, including on user sign in.
+ - Avoid making assumptions as to when this event is fired, this may occur even when the user is already signed in. Instead, check the user object attached to the event to see if a new user has signed in and update your application's UI.
+ - `SIGNED_OUT`
+ - Emitted when the user signs out. This can be after:
+ - A call to `supabase.auth.signOut()`.
+ - After the user's session has expired for any reason:
+ - User has signed out on another device.
+ - The session has reached its timebox limit or inactivity timeout.
+ - User has signed in on another device with single session per user enabled.
+ - Check the [User Sessions](/docs/guides/auth/sessions) docs for more information.
+ - Use this to clean up any local storage your application has associated with the user.
+ - `TOKEN_REFRESHED`
+ - Emitted each time a new access and refresh token are fetched for the signed in user.
+ - It's best practice and highly recommended to extract the access token (JWT) and store it in memory for further use in your application.
+ - Avoid frequent calls to `supabase.auth.session` for the same purpose.
+ - There is a background process that keeps track of when the session should be refreshed so you will always receive valid tokens by listening to this event.
+ - The frequency of this event is related to the JWT expiry limit configured on your project.
+ - `USER_UPDATED`
+ - Emitted each time the `supabase.auth.update(user:)` method finishes successfully. Listen to it to update your application's UI based on new profile information.
+ - `PASSWORD_RECOVERY`
+ - Emitted instead of the `SIGNED_IN` event when the user lands on a page that includes a password recovery link in the URL.
+ - Use it to show a UI to the user where they can [reset their password](/docs/guides/auth/passwords#resetting-a-users-password-forgot-password).
+
+ examples:
+ - id: listen-to-auth-changes
+ name: Listen to auth changes
+ isSpotlight: true
+ code: |
+ ```swift
+
+ // Using AsyncStream
+ for await (event, session) in await supabase.auth.authStateChanges {
+ print(event, session)
+ }
+
+ // Using Closure
+ let subscription = await supabase.auth.onAuthStateChange { event, session in
+ print(event, session)
+ }
+
+ // call remove() to remove subscription
+ subscription.remove()
+ ```
+ description: |
+ - When using closure based, remember to call `remove()` on the returned subscription.
+ - When using AsyncStream, it automatically removes the subscription when AsyncStream is canceled, or finishes.
+ - id: list-to-a-specific-event
+ name: Listen to a specific event
+ code: |
+ ```swift
+ for await (_, session) in await supabase.auth.authStateChanges
+ .filter({ $0.event == .signedIn }) {
+ // handle signIn event.
+ }
+ ```
- id: sign-in-anonymously
title: "signInAnonymously()"
notes: |
@@ -187,14 +275,14 @@ functions:
- id: sign-in-with-otp
title: "signInWithOTP()"
notes: |
+ - Requires either an email or phone number.
- This method is used for passwordless sign-ins where a OTP is sent to the user's email or phone number.
- - If the user doesn't exist, `signInWithOTP()` will signup the user instead. To restrict this behavior, you can set `shouldCreateUser` to `false`.
+ - If the user doesn't exist, `signInWithOTP()` will signup the user instead. To restrict this behavior, you can set `shouldCreateUser` to `false``.
- If you're using an email, you can configure whether you want the user to receive a magiclink or a OTP.
- If you're using phone, you can configure whether you want the user to receive a OTP.
- The magic link's destination URL is determined by the [`SITE_URL`](/docs/guides/auth/concepts/redirect-urls).
- See [redirect URLs and wildcards](/docs/guides/auth#redirect-urls-and-wildcards) to add additional redirect URLs to your project.
- Magic links and OTPs share the same implementation. To send users a one-time code instead of a magic link, [modify the magic link email template](/dashboard/project/_/auth/templates) to include `{{ .Token }}` instead of `{{ .ConfirmationURL }}`.
- - When using magic links, specify a `redirectTo` that matches a configured url scheme in your iOS app, so Supabase can correctly redirect back to your app.
- See our [Twilio Phone Auth Guide](/docs/guides/auth/phone-login/twilio) for details about configuring WhatsApp sign in.
examples:
- id: sign-in-with-email
@@ -216,13 +304,55 @@ functions:
```swift
try await supabase.auth.signInWithOTP(phone: "+13334445555")
```
+ - id: sign-in-with-whatsapp-otp
+ name: Sign in with WhatsApp OTP
+ isSpotlight: false
+ description: The user will be sent a WhatsApp message which contains a OTP. By default, a given user can only request a OTP once every 60 seconds. Note that a user will need to have a valid WhatsApp account that is linked to Twilio in order to use this feature.
+ code: |
+ ```swift
+ try await supabase.auth.signInWithOTP(
+ phone: "+13334445555",
+ channel: "whatsapp"
+ )
+ ```
- id: sign-in-with-oauth
- title: "getOAuthSignInURL()"
+ title: "signInWithOAuth()"
notes: |
- This method is used for signing in using a third-party provider.
- Supabase supports many different [third-party providers](https://supabase.com/docs/guides/auth#providers).
examples:
- - id: sign-in-using-a-third-party-provider
+ - id: sign-in-using-ASWebAuthenticationSession
+ name: Sign in with OAuth using ASWebAuthenticationSession
+ isSpotlight: true
+ description: |
+ - Use `configure` parameter to customize the `ASWebAuthenticationSession`
+ code: |
+ ```swift
+ let session = try await supabase.auth.signInWithOAuth(
+ provider: .github
+ ) { (session: ASWebAuthenticationSession) in
+ // customize session
+ }
+ ```
+
+ - id: sign-in-using-generic-flow
+ name: Sign in with OAuth and customize flow
+ isSpotlight: true
+ description: |
+ - Use `launchFlow` parameter to customize the flow.
+ code: |
+ ```swift
+ let session = try await supabase.auth.signInWithOAuth(
+ provider: .github
+ ) { url in
+ // use url to start OAuth flow
+ // and return a result url that contains the OAuth token.
+ // ...
+ return resultURL
+ }
+ ```
+
+ - id: sign-in-using-manual-implementation
name: Sign in using a third-party provider
isSpotlight: true
description: |
@@ -231,7 +361,7 @@ functions:
- When using `ASWebAuthenticationSession` or any other implementation, use the returning URL as input to `session(from:)` method.
code: |
```swift
- let url = try await supabase.auth.getOAuthSignInURL(provider: .github)
+ let url = try await supabase.auth.getOAuthSignInURL(provider: .github, redirectTo: URL(string: "my-app-scheme://"))
let session = ASWebAuthenticationSession(url: url, callbackURLScheme: "my-app-scheme") { url, error in
guard let url else { return }
@@ -246,21 +376,6 @@ functions:
session.start()
```
- - id: sign-in-using-a-third-party-provider-with-redirect
- name: Sign in using a third-party provider with redirect
- isSpotlight: false
- description: |
- - When the third-party provider successfully authenticates the user, the provider redirects the user to the URL specified in the `redirectTo` parameter. This parameter defaults to the [`SITE_URL`](/docs/guides/auth/concepts/redirect-urls). It does not redirect the user immediately after invoking this method.
- - See [redirect URLs and wildcards](/docs/guides/auth/overview#redirect-urls-and-wildcards) to add additional redirect URLs to your project.
- - getOAuthSignInURL() provides the URL which needs to be opened in a SFSafariViewController instance.
- - The redirectTo URL needs to be setup correctly in your project under Authentication -> URL Configuration -> Redirect URLs.
- code: |
- ```swift
- let url = try await supabase.auth.getOAuthSignInURL(
- provider: .google,
- redirectTo: URL(string: "https://example.com/welcome")!
- )
- ```
- id: sign-in-with-scopes
name: Sign in with scopes
isSpotlight: false
@@ -269,7 +384,7 @@ functions:
You may also need to specify the scopes in the provider's OAuth app settings, depending on the provider. The list of scopes will be documented by the third-party provider you are using and specifying scopes will enable you to use the OAuth provider token to call additional APIs supported by the third-party provider to get more information.
code: |
```swift
- let url = try await supabase.auth.getOAuthSignInURL(
+ let url = try await supabase.auth.signInWithOAuth(
provider: .github,
scopes: "repo gist notifications"
)
@@ -290,6 +405,45 @@ functions:
)
)
```
+ - id: sign-in-with-sso
+ title: 'signInWithSSO()'
+ notes: |
+ - Before you can call this method you need to [establish a connection](/docs/guides/auth/sso/auth-sso-saml#managing-saml-20-connections) to an identity provider. Use the [CLI commands](/docs/reference/cli/supabase-sso) to do this.
+ - If you've associated an email domain to the identity provider, you can use the `domain` property to start a sign-in flow.
+ - In case you need to use a different way to start the authentication flow with an identity provider, you can use the `providerId` property. For example:
+ - Mapping specific user email addresses with an identity provider.
+ - Using different hints to identity the identity provider to be used by the user, like a company-specific page, IP address or other tracking information.
+ examples:
+ - id: sign-in-with-domain
+ name: Sign in with email domain
+ isSpotlight: true
+ code: |
+ ```swift
+ // You can extract the user's email domain and use it to trigger the
+ // authentication flow with the correct identity provider.
+
+ let url = try await await supabase.auth.signInWithSSO{
+ domain: "company.com"
+ }
+
+ // Open the URL using your preferred method to complete sign-in process.
+ UIApplication.shared.open(url)
+ ```
+ - id: sign-in-with-provider-uuid
+ name: Sign in with provider UUID
+ isSpotlight: true
+ code: |
+ ```swift
+ // Useful when you need to map a user's sign in request according
+ // to different rules that can't use email domains.
+
+ let url = try await supabase.auth.signInWithSSO{
+ providerId: "21648a9d-8d5a-4555-a9d1-d6375dc14e92"
+ }
+
+ // Open the URL using your preferred method to complete sign-in process.
+ UIApplication.shared.open(url)
+ ```
- id: sign-out
title: "signOut()"
notes: |
@@ -410,6 +564,30 @@ functions:
```swift
let identities = try await supabase.auth.userIdentities()
```
+ - id: unlink-identity
+ title: 'unlinkIdentity()'
+ notes: |
+ - The **Enable Manual Linking** option must be enabled from your [project's authentication settings](/dashboard/project/_/settings/auth).
+ - The user needs to be signed in to call `unlinkIdentity()`.
+ - The user must have at least 2 identities in order to unlink an identity.
+ - The identity to be unlinked must belong to the user.
+ examples:
+ - id: unlink-identity
+ name: Unlink an identity
+ isSpotlight: true
+ code: |
+ ```swift
+ // retrieve all identites linked to a user
+ let identities = try await supabase.auth.userIdentities()
+
+ // find the google identity
+ let googleIdentity = identities.first {
+ $0.provider == .google
+ }
+
+ // unlink the google identity
+ try await supabase.auth.unlinkIdentity(googleIdentity)
+ ```
- id: send-password-reauthentication
title: "reauthenticate()"
notes: |
@@ -512,29 +690,7 @@ functions:
```swift
let session = try await supabase.auth.refreshSession(refreshToken: "custom-refresh-token")
```
- - id: on-auth-state-change
- title: "authStateChanges"
- notes: |
- - Types of auth events: `INITIAL_SESSION`, `SIGNED_IN`, `SIGNED_OUT`, `TOKEN_REFRESHED`, `USER_UPDATED`, `PASSWORD_RECOVERY`, `MFA_CHALLENGE_VERIFIED`
- - The `INITIAL_SESSION` can be used to allow you to invoke the callback function when `authStateChanges` is first called.
- examples:
- - id: listen-to-auth-changes
- name: Listen to auth changes
- isSpotlight: true
- code: |
- ```swift
- for await (event, session) in await supabase.auth.authStateChanges {
- print(event, session)
- }
- ```
- - id: list-to-a-specific-event
- name: Listen to a specific event
- code: |
- ```swift
- for await (_, session) in await supabase.auth.authStateChanges.filter({ $0.event == .signedIn }) {
- // handle signIn event.
- }
- ```
+
- id: exchange-code-for-session
title: "exchangeCodeForSession()"
notes: |
@@ -679,6 +835,41 @@ functions:
```swift
let factors = try await supabase.auth.mfa.listFactors()
```
+ - id: admin-api
+ title: 'Overview'
+ notes: |
+ - Any method under the `supabase.auth.admin` namespace requires a `service_role` key.
+ - These methods are considered admin methods and should be called on a trusted server. Never expose your `service_role` key in the browser.
+ examples:
+ - id: create-auth-admin-client
+ name: Create server-side auth client
+ isSpotlight: true
+ code: |
+ ```swift
+ import Supabase
+
+ let supabase = SupabaseClient(
+ supabaseURL: supabaseURL,
+ supabaseKey: serviceRoleKey
+ )
+
+ // Access auth admin api
+ let adminAuthClient = supabase.auth.admin
+ ```
+ - id: delete-user
+ title: 'deleteUser()'
+ notes: |
+ - The `deleteUser()` method requires the user's ID, which maps to the `auth.users.id` column.
+ examples:
+ - id: removes-a-user
+ name: Removes a user
+ isSpotlight: true
+ code: |
+ ```swift
+ try await supabase.auth.admin.deleteUser(
+ id: "715ed5db-f090-4b8c-a067-640ecee36aa0"
+ )
+ ```
- id: select
title: "Fetch data: select()"
notes: |
@@ -2899,133 +3090,140 @@ functions:
isSpotlight: true
code: |
```swift
- let channel = supabase
- .realtime
- .channel("room1")
+ let channel = await supabase.channel("room1")
- channel
- .on("broadcast", filter: ChannelFilter(event: "cursor-pos")) { message in
- print("Cursor position received!", message.payload)
- }
- .subscribe { status, error in
- if status == .subscribed {
- Task {
- await channel.send(
- type: .broadcast,
- event: "cursor-pos",
- payload: ["x": Double.random(in: 0...1), "y": Double.random(in: 0...1)]
- )
- }
- }
+ let broadcastStream = await channel.broadcastStream(event: "cursor-pos")
+
+ await channel.subscribe()
+
+ Task {
+ for await message in broadcastMessage {
+ print("Cursor position received", message.payload)
}
+ }
+
+ Task {
+ await channel.broadcast(
+ event: "cursor-pos",
+ message: [
+ "x": .double(.random(in: 0...1)),
+ "y": .double(.random(in: 0...1))
+ ]
+ )
+ }
```
- - id: listen-to-presence-sync
- name: Listen to presence sync
- isSpotlight: true
+
+ - id: listen-to-presence-updates
+ name: Listen to presence updates
code: |
```swift
- let channel = supabase.realtime.channel("room1")
- channel
- .on("presence", filter: ChannelFilter(event: "sync")) { _ in
- print("Synced presence state: ", channel.presenceState())
+ struct PresenceState: Codable {
+ let username: String
+ }
+
+ let channel = await supabase.channel("channelId")
+
+ let presenceChange = await channel.presenceChange()
+
+ await channel.subscribe()
+
+ Task {
+ for await presence in presenceChange {
+ let joins = try presence.decodeJoins(as: PresenceState.self)
+ let leaves = try presence.decodeLeaves(as: PresenceState.self)
}
- .subscribe { status, error in
- if status == .subscribed {
- Task {
- await channel.track(["online_at": Date().ISO8601Format()])
- }
- }
- }
- ```
- - id: listen-to-presence-join
- name: Listen to presence join
- isSpotlight: true
- code: |
- ```swift
- let channel = supabase.realtime.channel("room1")
- channel
- .on("presence", filter: ChannelFilter(event: "join")) { message in
- print("Newly joined presences: ", message.payload)
- }
- .subscribe { status, error in
- if status == .subscribed {
- Task {
- await channel.track(["online_at": Date().ISO8601Format()])
- }
- }
- }
- ```
- - id: listen-to-presence-leave
- name: Listen to presence leave
- isSpotlight: true
- code: |
- ```swift
- let channel = supabase.realtime.channel("room1")
- channel
- .on("presence", filter: ChannelFilter(event: "leave")) { message in
- print("Newly left presences: ", message.payload)
- }
- .subscribe { status, error in
- if status == .subscribed {
- Task {
- await channel.track(["online_at": Date().ISO8601Format()])
- await channel.untrack()
- }
- }
- }
- ```
+ }
+
+ // Send your own state
+ Task {
+ try await channel.track(PresenceState(username: "John"))
+ }
+
- id: listen-to-all-database-changes
name: Listen to all database changes
- isSpotlight: true
code: |
```swift
- supabase.realtime
- .channel("room1")
- .on("postgres_changes", filter: ChannelFilter(event: "*", schema: "*")) { message in
- print("Change received!", message.payload)
+ let channel = await supabase.channel("channelId")
+
+ let changeStream = await channel.postgresChange(AnyAction.self, schema: "public")
+
+ await channel.subscribe()
+
+ for await change in changeStream {
+ switch change {
+ case .delete(let action): print("Deleted: \(action.oldRecord)")
+ case .insert(let action): print("Inserted: \(action.record)")
+ case .select(let action): print("Selected: \(action.record)")
+ case .update(let action): print("Updated": \(action.oldRecord) with \(action.record)")
}
- .subscribe()
+ }
```
- id: listen-to-a-specific-table
name: Listen to a specific table
code: |
```swift
- supabase.realtime
- .channel("room1")
- .on("postgres_changes", filter: ChannelFilter(event: "*", schema: "public", table: "countries")) { message in
- print("Change received!", message.payload)
+ let channel = await supabase.channel("channelId")
+
+ let changeStream = await channel.postgresChange(
+ AnyAction.self,
+ schema: "public",
+ table: "users"
+ )
+
+ await channel.subscribe()
+
+ for await change in changeStream {
+ switch change {
+ case .delete(let action): print("Deleted: \(action.oldRecord)")
+ case .insert(let action): print("Inserted: \(action.record)")
+ case .select(let action): print("Selected: \(action.record)")
+ case .update(let action): print("Updated": \(action.oldRecord) with \(action.record)")
}
- .subscribe()
+ }
```
- id: listen-to-inserts
name: Listen to inserts
code: |
```swift
- supabase.realtime
- .channel("room1")
- .on("postgres_changes", filter: ChannelFilter(event: "INSERT", schema: "public", table: "countries")) { message in
- print("Change received!", message.payload)
- }
- .subscribe()
+ let channel = await supabase.channel("channelId")
+
+ let insertions = await channel.postgresChange(
+ InsertAction.self,
+ schema: "public",
+ table: "users"
+ )
+
+ await channel.subscribe()
+
+ for await insert in insertions {
+ print("Inserted: \(insert.record)")
+ }
```
- id: listen-to-updates
name: Listen to updates
description: |
By default, Supabase will send only the updated record. If you want to receive the previous values as well you can
- enable full replication for the table you are listening to:
+ enable full replication for the table you are listening too:
```sql
alter table "your_table" replica identity full;
```
code: |
```swift
- supabase.realtime
- .channel("room1")
- .on("postgres_changes", filter: ChannelFilter(event: "UPDATE", schema: "public", table: "countries")) { message in
- print("Change received!", message.payload)
- }
- .subscribe()
- ```
+ let channel = await supabase.channel("channelId")
+
+ let updates = await channel.postgresChange(
+ UpdateAction.self,
+ schema: "public",
+ table: "users"
+ )
+
+ await channel.subscribe()
+
+ for await update in updates {
+ print("Updated: \(update.oldRecord) with \(update.record)")
+ }
+ ```
- id: listen-to-deletes
name: Listen to deletes
description: |
@@ -3037,131 +3235,96 @@ functions:
```
code: |
```swift
- supabase.realtime
- .channel("room1")
- .on("postgres_changes", filter: ChannelFilter(event: "DELETE", schema: "public", table: "countries")) { message in
- print("Change received!", message.payload)
- }
- .subscribe()
- ```
- - id: listen-to-multiple-events
- name: Listen to multiple events
- description: You can chain listeners if you want to listen to multiple events for each table.
- code: |
- ```swift
- supabase.realtime
- .channel("room1")
- .on("postgres_changes", filter: ChannelFilter(event: "INSERT", schema: "public", table: "countries"), handler: handleRecordInserted)
- .on("postgres_changes", filter: ChannelFilter(event: "DELETE", schema: "public", table: "countries"), handler: handleRecordDeleted)
- .subscribe()
+ let channel = await supabase.channel("channelId")
- func handleRecordInserted(_ message: Message) {
- // handle message
- }
+ let deletions = await channel.postgresChange(
+ DeleteAction.self,
+ schema: "public",
+ table: "users"
+ )
- func handleRecordDeleted(_ message: Message) {
- // handle message
+ await channel.subscribe()
+
+ for await deletion in deletions {
+ print("Deleted: \(deletion.oldRecord)")
}
```
- id: listening-to-row-level-changes
name: Listen to row level changes
- description: You can listen to individual rows using the format `{table}:{col}=eq.{val}` - where `{col}` is the column name, and `{val}` is the value which you want to match.
- notes: |
- - ``eq`` filter works with all database types as under the hood, it's casting both the filter value and the database value to the correct type and then comparing them.
code: |
```swift
- supabase.realtime
- .channel("room1")
- .on(
- "postgres_changes",
- filter: ChannelFilter(
- event: "INSERT",
- schema: "public",
- table: "countries",
- filter: "id=eq.200"
- ),
- handler: handleRecordInserted
- )
- .subscribe()
+ let channel = await supabase.channel("channelId")
- func handleRecordInserted(_ message: Message) {
- // handle message
- }
- ```
- - id: broadcast-message
- title: broadcastMessage()
- description: |
- Broadcast a message to all connected clients to a channel.
- notes: |
- - When using REST you don't need to subscribe to the channel
- examples:
- - id: send-a-message
- name: Send a message via websocket
- isSpotlight: true
- code: |
- ```swift
- supabase.realtime
- .channel("room1")
- .subscribe { status, error in
- if status == .subscribed {
- Task {
- await channel.send(
- type: "broadcast",
- event: "cursor-pos",
- payload: ["x": Double.random(in: 0...1), "y": Double.random(in: 0...1)]
- )
- }
- }
- }
- ```
- - id: send-a-message-via-rest
- name: Send a message via REST
- isSpotlight: true
- code: |
- ```swift
- await supabase.realtime
- .channel("room1")
- .send(
- type: "broadcast",
- event: "cursor-pos",
- payload: ["x": Double.random(in: 0...1), "y": Double.random(in: 0...1)]
- )
- ```
- - id: get-channels
- title: channels
- examples:
- - id: get-all-channels
- name: Get all channels
- isSpotlight: true
- code: |
- ```swift
- let channels = supabase.realtime.channels
+ let deletions = await channel.postgresChange(
+ DeleteAction.self,
+ schema: "public",
+ table: "users",
+ filter: "id=eq.1"
+ )
+
+ await channel.subscribe()
+
+ for await deletion in deletions {
+ print("Deleted: \(deletion.oldRecord)")
+ }
```
- id: remove-channel
- title: removeChannel()
+ description: |
+ Unsubscribes and removes Realtime channel from Realtime client.
+ title: "removeChannel()"
notes: |
- - Removing a channel is a great way to maintain the performance of your project's Realtime service as well as your database if you're listening to Postgres changes. Supabase will automatically handle cleanup 30 seconds after a client is disconnected, but unused channels may cause degradation as more clients are simultaneously subscribed.
+ - Removing a channel is a great way to maintain the performance of your project's Realtime service as well as your database if you're listening to Postgres changes.
+ - Supabase will automatically handle cleanup 30 seconds after a client is disconnected, but unused channels may cause degradation as more clients are simultaneously subscribed.
+ - If you removed all channels, the client automatically disconnects from the Realtime websocket. This can be disabled in the Realtime config by setting `disconnectOnNoSubscriptions` to false.
examples:
- id: removes-a-channel
- name: Removes a channel
+ name: Remove a channel
isSpotlight: true
code: |
```swift
- supabase.realtime.remove(myChannel)
- ```
+ let channel = await supabase.channel("channelId")
+ //...
+ await supabase.removeChannel(channel)
+ ```
+ - id: unsubscribe-channel
+ name: Unsubscribe from a channel
+ isSpotlight: true
+ code: |
+ ```swift
+ let channel = await supabase.channel("channelId")
+
+ //...
+ await channel.unsubscribe()
+ ```
- id: remove-all-channels
title: removeAllChannels()
+ $ref: "@supabase/supabase-js.index.SupabaseClient.removeAllChannels"
notes: |
+ Unsubscribes and removes all Realtime channels from Realtime client.
- Removing channels is a great way to maintain the performance of your project's Realtime service as well as your database if you're listening to Postgres changes. Supabase will automatically handle cleanup 30 seconds after a client is disconnected, but unused channels may cause degradation as more clients are simultaneously subscribed.
+ - If you removed all channels, the client automatically disconnects from the Realtime websocket. This can be disabled in the Realtime config by setting `disconnectOnNoSubscriptions` to false.
examples:
- id: remove-all-channels
name: Remove all channels
isSpotlight: true
code: |
```swift
- supabase.realtime.removeAllChannels()
+ await supabase.removeAllChannels()
+ ```
+ - id: get-channels
+ title: getChannels()
+ $ref: "@supabase/supabase-js.index.SupabaseClient.getChannels"
+ notes: |
+ Returns all Realtime channels.
+ examples:
+ - id: get-all-channels
+ name: Get all channels
+ isSpotlight: true
+ code: |
+ ```swift
+ let channels = await supabase.channels
```
- id: list-buckets
diff --git a/apps/studio/components/interfaces/Home/Home.constants.ts b/apps/studio/components/interfaces/Home/Home.constants.ts
index 7d6ba1254e4..ee33d1b4140 100644
--- a/apps/studio/components/interfaces/Home/Home.constants.ts
+++ b/apps/studio/components/interfaces/Home/Home.constants.ts
@@ -30,10 +30,10 @@ export const CLIENT_LIBRARIES = [
},
{
language: 'Swift',
- officialSupport: false,
+ officialSupport: true,
releaseState: undefined,
docsUrl: 'https://supabase.com/docs/reference/swift/initializing',
- gitUrl: 'https://github.com/supabase-community/supabase-swift',
+ gitUrl: 'https://github.com/supabase/supabase-swift',
},
{
language: 'Kotlin',
diff --git a/apps/www/_blog/2023-04-14-launch-week-7-community-highlights.mdx b/apps/www/_blog/2023-04-14-launch-week-7-community-highlights.mdx
index 5bb4d6cacb3..0fbd8124bba 100644
--- a/apps/www/_blog/2023-04-14-launch-week-7-community-highlights.mdx
+++ b/apps/www/_blog/2023-04-14-launch-week-7-community-highlights.mdx
@@ -148,7 +148,7 @@ Itβs becoming easier to build applications with any language.
In the past few months, the community has rallied and shipped 3 new client libraries, complete with Docs:
- Swift:
- - [Documentation](/docs/reference/swift/introduction) | [Source Code](https://github.com/supabase-community/supabase-swift)
+ - [Documentation](/docs/reference/swift/introduction) | [Source Code](https://github.com/supabase/supabase-swift)
- Shout-out to: [grsouza](https://github.com/grsouza) & [@maail](https://github.com/maail)
- Python:
- [Documentation](/docs/reference/python/initializing) | [Source Code](https://github.com/supabase-community/supabase-py)
diff --git a/examples/user-management/swift-user-management/swift-user-management.xcodeproj/project.pbxproj b/examples/user-management/swift-user-management/swift-user-management.xcodeproj/project.pbxproj
index 6d55da3c2ad..c811ec841c7 100644
--- a/examples/user-management/swift-user-management/swift-user-management.xcodeproj/project.pbxproj
+++ b/examples/user-management/swift-user-management/swift-user-management.xcodeproj/project.pbxproj
@@ -412,7 +412,7 @@
/* Begin XCRemoteSwiftPackageReference section */
79A039C42B2B8EC20031D573 /* XCRemoteSwiftPackageReference "supabase-swift" */ = {
isa = XCRemoteSwiftPackageReference;
- repositoryURL = "https://github.com/supabase-community/supabase-swift";
+ repositoryURL = "https://github.com/supabase/supabase-swift";
requirement = {
kind = upToNextMajorVersion;
minimumVersion = 2.0.0;
diff --git a/examples/user-management/swift-user-management/swift-user-management.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved b/examples/user-management/swift-user-management/swift-user-management.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved
index 9921469c9c0..ba7785ae87a 100644
--- a/examples/user-management/swift-user-management/swift-user-management.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved
+++ b/examples/user-management/swift-user-management/swift-user-management.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved
@@ -13,7 +13,7 @@
{
"identity" : "supabase-swift",
"kind" : "remoteSourceControl",
- "location" : "https://github.com/supabase-community/supabase-swift",
+ "location" : "https://github.com/supabase/supabase-swift",
"state" : {
"revision" : "1a7dad006f94749923e764343aaaeadbe74f0352",
"version" : "2.6.0"
diff --git a/packages/common/constants/client-libraries.ts b/packages/common/constants/client-libraries.ts
index 6749e1100eb..fcd1d53613e 100644
--- a/packages/common/constants/client-libraries.ts
+++ b/packages/common/constants/client-libraries.ts
@@ -217,7 +217,7 @@ export const CLIENT_LIBRARIES = [
libraries: [
{
name: 'supabase-swift',
- url: 'https://github.com/supabase-community/supabase-swift',
+ url: 'https://github.com/supabase/supabase-swift',
},
{
name: 'postgrest-swift',