diff --git a/apps/docs/content/guides/api/quickstart.mdx b/apps/docs/content/guides/api/quickstart.mdx
index fbd141e9309..7ba5b9b8809 100644
--- a/apps/docs/content/guides/api/quickstart.mdx
+++ b/apps/docs/content/guides/api/quickstart.mdx
@@ -169,5 +169,12 @@ final data = await supabase.from('todos').select('*');
response = supabase.table('todos').select("*").execute()
```
+
+
+
+```swift
+let response = try await supabase.from("todos").select()
+```
+
diff --git a/apps/docs/content/guides/auth/auth-anonymous.mdx b/apps/docs/content/guides/auth/auth-anonymous.mdx
index 461bb45acec..a67c430ddb6 100644
--- a/apps/docs/content/guides/auth/auth-anonymous.mdx
+++ b/apps/docs/content/guides/auth/auth-anonymous.mdx
@@ -64,6 +64,15 @@ Call the [`signInAnonymously()`](/docs/reference/dart/auth-signinanonymously) me
await supabase.auth.signInAnonymously();
```
+
+
+
+Call the [`signInAnonymously()`](/docs/reference/swift/auth-signinanonymously) method:
+
+```swift
+let session = try await supabase.auth.signInAnonymously()
+```
+
@@ -106,6 +115,17 @@ You can use the [`updateUser()`](/docs/reference/dart/auth-updateuser) method to
await supabase.auth.updateUser(UserAttributes(email: 'example@email.com'));
```
+
+
+
+You can use the [`updateUser()`](/docs/reference/swift/auth-updateuser) method to link an email or phone identity to the anonymous user.
+
+```swift
+try await supabase.auth.updateUser(
+ user: UserAttributes(email: "example@email.com")
+)
+```
+
@@ -146,6 +166,15 @@ You can use the [`linkIdentity()`](/docs/reference/dart/auth-linkidentity) metho
await supabase.auth.linkIdentity(OAuthProvider.google);
```
+
+
+
+You can use the [`linkIdentity()`](/docs/reference/swift/auth-linkidentity) method to link an OAuth identity to the anonymous user.
+
+```swift
+try await supabase.auth.linkIdentity(provider: .google)
+```
+
diff --git a/apps/docs/content/guides/auth/auth-email.mdx b/apps/docs/content/guides/auth/auth-email.mdx
index 38eb93095c6..ab2636abfe6 100644
--- a/apps/docs/content/guides/auth/auth-email.mdx
+++ b/apps/docs/content/guides/auth/auth-email.mdx
@@ -57,6 +57,19 @@ Future signUpNewUser() async {
}
```
+
+
+
+To sign up the user, call [signUp()](/docs/reference/swift/auth-signup) with their email address and password:
+
+```swift
+let response = try await supabase.auth.signUp(
+ email: "example@email.com",
+ password: "example-password",
+ redirectTo: URL(string: "https://example.com/welcome")
+)
+```
+
@@ -110,6 +123,18 @@ Future signInWithEmail() async {
}
```
+
+
+
+When your user signs in, call [signIn(email:password:)](/docs/reference/swift/auth-signinwithpassword) with their email address and password:
+
+```swift
+try await supabase.auth.signIn(
+ email: "example@email.com",
+ password: "example-password"
+)
+```
+
@@ -157,6 +182,15 @@ Future signOut() async {
}
```
+
+
+
+When your user signs out, call [signOut()](/docs/reference/swift/auth-signout) to remove the session from the local storage:
+
+```swift
+try await supabase.auth.signOut()
+```
+
diff --git a/apps/docs/content/guides/auth/auth-identity-linking.mdx b/apps/docs/content/guides/auth/auth-identity-linking.mdx
index befba001809..112a2005a17 100644
--- a/apps/docs/content/guides/auth/auth-identity-linking.mdx
+++ b/apps/docs/content/guides/auth/auth-identity-linking.mdx
@@ -54,6 +54,15 @@ Supabase Auth allows a user to initiate identity linking with a different email
const { data, error } = await supabase.auth.linkIdentity({ provider: 'google' })
```
+
+
+
+Supabase Auth allows a user to initiate identity linking with a different email address when they are logged in. To link an OAuth identity to the user, call [`linkIdentity()`](/docs/reference/swift/auth-linkidentity):
+
+```swift
+try await supabase.auth.linkIdentity(provider: .google)
+```
+
@@ -94,6 +103,22 @@ const googleIdentity = identities.find((identity) => identity.provider === 'goog
const { data, error } = await supabase.auth.unlinkIdentity(googleIdentity)
```
+
+
+
+You can use [`getUserIdentities()`](/docs/reference/swift/auth-getuseridentities) to fetch all the identities linked to a user. Then, call [`unlinkIdentity()`](/docs/reference/swift/auth-unlinkidentity) to unlink the identity. The user needs to be logged in and have at least 2 linked identities in order to unlink an existing identity.
+
+```swift
+// retrieve all identities linked to a user
+let identities = try await supabase.auth.userIdentities()
+
+// find the google identity linked to the user
+let googleIdentity = identities.first { $0.provider == .google }
+
+// unlink the google identity from the user
+try await supabase.auth.unlinkIdentity(googleIdentity)
+```
+
diff --git a/apps/docs/content/guides/auth/enterprise-sso/auth-sso-saml.mdx b/apps/docs/content/guides/auth/enterprise-sso/auth-sso-saml.mdx
index 48a16a52779..aa87f390aa8 100644
--- a/apps/docs/content/guides/auth/enterprise-sso/auth-sso-saml.mdx
+++ b/apps/docs/content/guides/auth/enterprise-sso/auth-sso-saml.mdx
@@ -213,6 +213,17 @@ await supabase.auth.signInWithSSO(
Calling [`signInWithSSO`](/docs/reference/dart/auth-signinwithsso) starts the sign-in process using the identity provider registered for the `company.com` domain name. It is not required that identity providers be assigned one or multiple domain names, in which case you can use the provider's unique ID instead.
+
+
+
+```swift
+try await supabase.auth.signInWithSSO(
+ domain: "company.com"
+)
+```
+
+Calling [`signInWithSSO`](/docs/reference/swift/auth-signinwithsso) starts the sign-in process using the identity provider registered for the `company.com` domain name. It is not required that identity providers be assigned one or multiple domain names, in which case you can use the provider's unique ID instead.
+
diff --git a/apps/docs/content/guides/auth/managing-user-data.mdx b/apps/docs/content/guides/auth/managing-user-data.mdx
index dd73f0757ac..831f269bb20 100644
--- a/apps/docs/content/guides/auth/managing-user-data.mdx
+++ b/apps/docs/content/guides/auth/managing-user-data.mdx
@@ -107,6 +107,26 @@ const { data: profile } = await supabase
.select('id, username, avatar_url, website')
```
+
+
+
+```swift
+// This will return nothing while the user is logged out
+let profiles: [Profile] = try await supabase.from("profiles")
+ .select("id, username, avatar_url, website")
+ .execute()
+ .value
+
+// After the user is logged in, this will only return
+// the logged-in user's data - in this case a single row
+try await supabase.auth.signInWithOTP(email: email)
+let profile: Profile = try await supabase.from("profiles")
+ .select("id, username, avatar_url, website")
+ .single()
+ .execute()
+ .value
+```
+
@@ -163,6 +183,20 @@ const { data, error } = await supabase.auth.signUp({
})
```
+
+
+
+```swift
+try await supabase.auth.signUp(
+ email: "example@email.com",
+ password: "example-password",
+ data: [
+ "first_name": .string("John"),
+ "age": .integer(27),
+ ]
+)
+```
+
@@ -198,6 +232,14 @@ const {
let metadata = user.user_metadata
```
+
+
+
+```swift
+let user = try await supabase.auth.user()
+let metadata = user.userMetadata
+```
+
diff --git a/apps/docs/content/guides/auth/passwordless-login/auth-email-otp.mdx b/apps/docs/content/guides/auth/passwordless-login/auth-email-otp.mdx
index 820f70e4b5c..2605da556fc 100644
--- a/apps/docs/content/guides/auth/passwordless-login/auth-email-otp.mdx
+++ b/apps/docs/content/guides/auth/passwordless-login/auth-email-otp.mdx
@@ -54,6 +54,18 @@ Future signInWithEmailOtp() async {
}
```
+
+
+When your user signs in, call [signInWithOTP()](/docs/reference/swift/auth-signinwithotp) with their email address:
+
+```swift
+try await supabase.auth.signInWithOTP(
+ email: "example@email.com",
+ // set this to false if you do not want the user to be automatically signed up
+ shouldCreateUser: false
+)
+```
+
@@ -106,6 +118,19 @@ const {
})
```
+
+
+
+Provide an input field for the user to key in the one-time code. To verify the code and complete the user's sign in, call [verifyOTP()](/docs/reference/swift/auth-verifyotp) with their email address, the code, and `type: .email`:
+
+```swift
+try await supabase.auth.verifyOTP(
+ email: email,
+ token: "123456",
+ type: .email
+)
+```
+
diff --git a/apps/docs/content/guides/auth/passwordless-login/auth-magic-link.mdx b/apps/docs/content/guides/auth/passwordless-login/auth-magic-link.mdx
index 4b6ffdfdc87..001cab6c545 100644
--- a/apps/docs/content/guides/auth/passwordless-login/auth-magic-link.mdx
+++ b/apps/docs/content/guides/auth/passwordless-login/auth-magic-link.mdx
@@ -19,6 +19,8 @@ Set up Magic Link logins for your Supabase application.
When using Magic Links in [the PKCE Flow](/blog/supabase-auth-sso-pkce#introducing-pkce), keep in mind that links can only be opened from the same browser that they are sent from (as defined in the PKCE spec). Consequently, a magic link sent from Chrome on Desktop will be invalid if used on a Mobile Device.
+The same applies for Magic Links in mobile devices. Magic Links can only be opened on the device they are sent from.
+
signInWithEmail() async {
}
```
+
+
+When your user signs in, call [signInWithOTP()](/docs/reference/swift/auth-signinwithotp) with their email address:
+
+```swift
+try await supabase.auth.signInWithOTP(
+ email: "example@email.com",
+ redirectTo: URL(string: "https://example.com/welcome"),
+ // set this to false if you do not want the user to be automatically signed up
+ shouldCreateUser: false
+)
+```
+
@@ -119,6 +134,14 @@ Future signOut() async {
}
```
+
+
+When your user signs out, call [signOut()](/docs/reference/swift/auth-signout) to remove them from the local storage:
+
+```swift
+try await supabase.auth.signOut()
+```
+
diff --git a/apps/docs/content/guides/auth/passwords.mdx b/apps/docs/content/guides/auth/passwords.mdx
index 25877dad288..eb6a54ff65e 100644
--- a/apps/docs/content/guides/auth/passwords.mdx
+++ b/apps/docs/content/guides/auth/passwords.mdx
@@ -91,6 +91,18 @@ await supabase.auth.resetPasswordForEmail('hello@example.com', {
})
```
+
+
+
+Supabase provides a convenient method [`supabase.auth.resetPasswordForEmail`](/docs/reference/swift/auth-resetpasswordforemail) to reset a user password. This method takes a parameter of `redirectTo`, which is an absolute URL to the update password page. This URL must be saved in your allowed [Redirect URLs](https://supabase.com/dashboard/project/_/auth/url-configuration) list found at [Authentication > Redirect Configuration](https://supabase.com/dashboard/project/_/auth/url-configuration).
+
+```swift
+try await supabase.auth.resetPasswordForEmail(
+ "hello@example.com",
+ redirectTo: URL(string: "http://example.com/account/update-password")
+)
+```
+
@@ -125,6 +137,15 @@ To update the password, call the [`supabase.auth.updateUser`](/docs/reference/ja
await supabase.auth.updateUser({ password: new_password })
```
+
+
+
+To update the password, call the [`supabase.auth.updateUser`](/docs/reference/swift/auth-updateuser) method with the new password.
+
+```swift
+try await supabase.auth.updateUser(user: UserAttributes(password: newPassword))
+```
+
diff --git a/apps/docs/content/guides/auth/phone-login.mdx b/apps/docs/content/guides/auth/phone-login.mdx
index e35520a002a..0846897aaea 100644
--- a/apps/docs/content/guides/auth/phone-login.mdx
+++ b/apps/docs/content/guides/auth/phone-login.mdx
@@ -80,6 +80,16 @@ const { data, error } = await supabase.auth.signUp({
})
```
+
+
+
+```swift
+try await supabase.auth.signUp(
+ phone: "+13334445555",
+ password: "some-password"
+)
+```
+
@@ -126,6 +136,16 @@ const { user, error } = await supabase.auth.signInWithPassword({
})
```
+
+
+
+```swift
+try await supabase.auth.signIn(
+ phone: "+13334445555",
+ password: "some-password"
+)
+```
+
@@ -171,6 +191,15 @@ const { data, error } = await supabase.auth.signInWithOtp({
})
```
+
+
+
+```swift
+try await supabase.auth.signInWithOTP(
+ phone: "+13334445555"
+)
+```
+
@@ -216,6 +245,17 @@ const { data, error } = await supabase.auth.updateUser({
})
```
+
+
+
+```swift
+try await supabase.auth.updateUser(
+ user: UserAttributes(
+ phone: "123456789"
+ )
+)
+```
+
@@ -247,6 +287,19 @@ const {
})
```
+
+
+
+You should present a form to the user so they can input the 6 digit pin, then send it along with the phone number to `verifyOTP`:
+
+```swift
+try await supabase.auth.verifyOTP(
+ phone: "+13334445555",
+ token: "123456",
+ type: .sms
+)
+```
+
diff --git a/apps/docs/content/guides/database/arrays.mdx b/apps/docs/content/guides/database/arrays.mdx
index 63557ca992f..eb405bd293f 100644
--- a/apps/docs/content/guides/database/arrays.mdx
+++ b/apps/docs/content/guides/database/arrays.mdx
@@ -72,6 +72,30 @@ const { data, error } = await supabase
.insert([{ id: 2, textarray: ['one', 'two', 'three', 'four'] }])
```
+
+
+
+Insert a record from the Swift client:
+
+```swift
+struct ArrayTest: Encodable {
+ let id: Int
+ let textarray: [String]
+}
+
+try await supabase
+ .from("arraytest")
+ .insert(
+ [
+ ArrayTest(
+ id: 2,
+ textarray: ["one", "two", "three", "four"]
+ )
+ ]
+ )
+ .execute()
+```
+
@@ -156,6 +180,30 @@ returns:
]
```
+
+
+
+This returns the entire array field:
+
+```swift
+struct Response: Decodable {
+ let textarray: [String]
+}
+
+let response: [Response] = try await supabase.from("arraytest").select("textarray").execute().value
+dump(response)
+```
+
+returns:
+
+```
+[
+ Response(
+ textarray: ["Harry", "Larry", "Moe"],
+ )
+]
+```
+
diff --git a/apps/docs/content/guides/database/extensions/postgis.mdx b/apps/docs/content/guides/database/extensions/postgis.mdx
index 06c51beb308..83e4057a62f 100644
--- a/apps/docs/content/guides/database/extensions/postgis.mdx
+++ b/apps/docs/content/guides/database/extensions/postgis.mdx
@@ -139,6 +139,26 @@ await supabase.from('restaurants').insert([
]);
```
+
+
+
+```swift
+struct Restaurant: Codable {
+ let name: String
+ let location: String // You could also use a custom type with a custom `Encodable` conformance for convenience.
+}
+
+try await supabase.from("restaurants")
+ .insert(
+ [
+ Restaurant(name: "Supa Burger", location: "POINT(-73.946823 40.807416)"),
+ Restaurant(name: "Supa Pizza", location: "POINT(-73.94581 40.807475)"),
+ Restaurant(name: "Supa Taco", location: "POINT(-73.945826 40.80629)"),
+ ]
+ )
+ .execute()
+```
+
@@ -215,6 +235,34 @@ final data = await supabase.rpc('nearby_restaurants',params: {
});
```
+
+
+
+```swift
+struct Response: Codable {
+ let id: Int
+ let name: String
+ let lat: Double
+ let long: Double
+ let distance: Double
+
+ enum CodingKeys: String, CodingKey {
+ case id, name, lat, long
+ case distance = "dist_meters"
+ }
+}
+
+let response: Response = try await supabase.rpc(
+ "nearby_restaurants",
+ params: [
+ "lat": 40.807313,
+ "long": -73.946713
+ ]
+)
+.execute()
+.value
+```
+
@@ -314,6 +362,30 @@ final data = await supabase.rpc('restaurants_in_view', params: {
});
```
+
+
+
+```swift
+struct Response: Codable {
+ let id: Int
+ let name: String
+ let lat: Double
+ let long: Double
+}
+
+let response: Response = try await supabase.rpc(
+ "restaurants_in_view",
+ params: [
+ "min_lat": 40.807,
+ "min_long": -73.946,
+ "max_long": -73.945,
+ "max_lat": 40.808,
+ ]
+)
+.execute()
+.value
+```
+
diff --git a/apps/docs/content/guides/database/full-text-search.mdx b/apps/docs/content/guides/database/full-text-search.mdx
index 1f75efa7230..f84c5b2fe59 100644
--- a/apps/docs/content/guides/database/full-text-search.mdx
+++ b/apps/docs/content/guides/database/full-text-search.mdx
@@ -138,6 +138,16 @@ final result = await client
.eq('title', 'Harry');
```
+
+
+
+```swift
+let response = try await supabase.from("books")
+ .select()
+ .eq("title", value: "Harry")
+ .execute()
+```
+
@@ -187,6 +197,15 @@ final result = await client
.textSearch('title', "'Harry'");
```
+
+
+
+```swift
+let response = try await supabase.from("books")
+ .select()
+ .textSearch("title", value: "'Harry'")
+```
+
@@ -243,6 +262,16 @@ final result = await client
.textSearch('description', "'big'");
```
+
+
+
+```swift
+let response = await client.from("books")
+ .select()
+ .textSearch("description", value: "'big'")
+ .execute()
+```
+
@@ -326,6 +355,23 @@ final result = await client
.textSearch('title_description', "little")
```
+
+
+
+```sql
+create function title_description(books) returns text as $$
+ select $1.title || ' ' || $1.description;
+$$ language sql immutable;
+```
+
+```swift
+let response = try await client
+ .from("books")
+ .select()
+ .textSearch("title_description", value: "little")
+ .execute()
+```
+
@@ -401,6 +447,17 @@ final result = await client
.textSearch('description', "'little' & 'big'");
```
+
+
+
+```swift
+let response = try await client
+ .from("books")
+ .select()
+ .textSearch("description", value: "'little' & 'big'");
+ .execute()
+```
+
@@ -469,6 +526,17 @@ final result = await client
.textSearch('description', "'little' | 'big'");
```
+
+
+
+```swift
+let response = try await client
+ .from("books")
+ .select()
+ .textSearch("description", value: "'little' | 'big'")
+ .execute()
+```
+
@@ -548,6 +616,17 @@ const { data, error } = await supabase.rpc('search_books_by_title_prefix', { pre
final data = await supabase.rpc('search_books_by_title_prefix', params: { 'prefix': 'Lit' });
```
+
+
+
+```swift
+let response = try await supabase.rpc(
+ "search_books_by_title_prefix",
+ params: ["prefix": "Lit"]
+)
+.execute()
+```
+
@@ -660,6 +739,17 @@ final result = await client
.textSearch('fts', "'little' & 'big'");
```
+
+
+
+```swift
+let response = try await client
+ .from("books")
+ .select()
+ .textSearch("fts", value: "'little' & 'big'")
+ .execute()
+```
+
@@ -733,6 +823,17 @@ final result = await client
.textSearch('description', "'big' <-> 'dreams'");
```
+
+
+
+```swift
+let response = try await client
+ .from("books")
+ .select()
+ .textSearch("description", value: "'big' <-> 'dreams'")
+ .execute()
+```
+
@@ -787,6 +888,17 @@ final result = await client
.textSearch('description', "'year' <2> 'school'");
```
+
+
+
+```swift
+let response = try await supabase
+ .from("books")
+ .select()
+ .textSearch("description", value: "'year' <2> 'school'")
+ .execute()
+```
+
@@ -844,6 +956,17 @@ final result = await client
.textSearch('description', "'big' & !'little'");
```
+
+
+
+```swift
+let response = try await client
+ .from("books")
+ .select()
+ .textSearch("description", value: "'big' & !'little'")
+ .execute()
+```
+
diff --git a/apps/docs/content/guides/database/functions.mdx b/apps/docs/content/guides/database/functions.mdx
index cdb910df794..6e7664054af 100644
--- a/apps/docs/content/guides/database/functions.mdx
+++ b/apps/docs/content/guides/database/functions.mdx
@@ -94,6 +94,15 @@ final data = await supabase
Reference: [rpc()](../../reference/dart/rpc)
+
+
+
+```swift
+try await supabase.rpc("hello_world").execute()
+```
+
+Reference: [rpc()](../../reference/swift/rpc)
+
@@ -216,6 +225,13 @@ final data = await supabase
.eq('id', 1);
```
+
+
+
+```swift
+let response = try await supabase.rpc("get_planets").eq("id", value: 1).execute()
+```
+
@@ -281,6 +297,33 @@ final data = await supabase
.rpc('add_planet', params: { 'name': 'Jakku' });
```
+
+
+
+Using `Encodable` type:
+
+```swift
+struct Planet: Encodable {
+ let name: String
+}
+
+try await supabase.rpc(
+ "add_planet",
+ params: Planet(name: "Jakku")
+)
+.execute()
+```
+
+Using `AnyJSON` convenience` type:
+
+```swift
+try await supabase.rpc(
+ "add_planet",
+ params: ["name": AnyJSON.string("Jakku")]
+)
+.execute()
+```
+
diff --git a/apps/docs/content/guides/database/joins-and-nesting.mdx b/apps/docs/content/guides/database/joins-and-nesting.mdx
index 997dc5935f7..18584fded25 100644
--- a/apps/docs/content/guides/database/joins-and-nesting.mdx
+++ b/apps/docs/content/guides/database/joins-and-nesting.mdx
@@ -135,6 +135,28 @@ const countriesWithCities: CountriesWithCities = data
final data = await supabase.from('countries').select('id, name, cities(id, name)');
```
+
+
+
+```swift
+struct Country: Codable {
+ let id: Int
+ let name: String
+ let cities: [City]
+
+ struct City: Codable {
+ let id: Int
+ let name: String
+ }
+}
+
+let countries: [Country] = try await supabase
+ .from("countries")
+ .select("id, name, cities(id, name)")
+ .execute()
+ .value
+```
+
@@ -222,6 +244,38 @@ const { data, error } = await supabase.from('teams').select(`
final data = await supabase.from('teams').select('id, team_name, users(id, name)');
```
+
+
+
+```swift
+struct Team: Codable {
+ let id: Int
+ let name: String
+ let users: [User]
+
+ struct User: Codable {
+ let id: Int
+ let name: String
+ }
+
+ enum CodingKeys: String, CodingKey {
+ case id, users
+ case name = "team_name"
+ }
+}
+let teams [Team] = try await supabase
+ .from("teams")
+ .select(
+ """
+ id,
+ team_name,
+ users ( id, name )
+ """
+ )
+ .execute()
+ .value
+```
+
@@ -315,5 +369,51 @@ const { data, error } = await supabase.from('shifts').select(
)
```
+
+
+
+```swift
+struct Shift: Codable {
+ let id: Int
+ let userId: Int
+ let attendanceStatus: String?
+
+ let scans: [Scan]
+
+ struct Scan: Codable {
+ let id: Int
+ let userId: Int
+ let badgeScanTime: TimeInterval
+
+ enum CodingKeys: String, CodingKey {
+ case id
+ case userId = "user_id"
+ case badgeScanTime = "badge_scan_time"
+ }
+ }
+
+ enum CodingKeys: String, CodingKey {
+ case id
+ case userId = "user_id"
+ case attendanceStatus = "attendance_status"
+ }
+}
+
+let shifts: [Shift] = try await supabase
+ .from("shifts")
+ .select(
+ """
+ *,
+ scans:scan_id_start (
+ id,
+ user_id,
+ badge_scan_time
+ )
+ """
+ )
+ .execute()
+ .value
+```
+
diff --git a/apps/docs/content/guides/database/json.mdx b/apps/docs/content/guides/database/json.mdx
index 6f2cd0c1771..97e7a8d3f0d 100644
--- a/apps/docs/content/guides/database/json.mdx
+++ b/apps/docs/content/guides/database/json.mdx
@@ -177,6 +177,70 @@ const { data, error } = await supabase.from('books').insert([
])
```
+
+
+
+Supabase Swift provides a convenience `AnyJSON` type.
+
+```swift
+struct Book {
+ val title: String,
+ val author: String,
+ val metadata: [String: AnyJSON]
+}
+
+try await supabase.from("books")
+ .insert(
+ [
+ Book(
+ title: "The Poky Little Puppy",
+ author: "Janette Sebring Lowrey",
+ metadata: [
+ "description": "Puppy is slower than other, bigger animals.",
+ "price": 5.95,
+ "ages": [3, 6]
+ ]
+ ),
+ Book(
+ title: "Tale of Peter Rabbit",
+ author: "Beatrix Potter",
+ metadata: [
+ "description": "Rabbit eats some vegetables.",
+ "price": 4.49,
+ "ages": [2, 5]
+ ]
+ ),
+ Book(
+ title: "Tootle",
+ author: "Gertrude Crampton",
+ metadata: [
+ "description": "Little toy train has big dreams.",
+ "price": 3.99,
+ "ages": [2, 5]
+ ]
+ ),
+ Book(
+ title: "Green Eggs and Ham",
+ author: "Dr. Seuss",
+ metadata: [
+ "description": "Sam has changing food preferences and eats unusually colored food.",
+ "price": 7.49,
+ "ages": [4, 8]
+ ]
+ ),
+ Book(
+ title: "Harry Potter and the Goblet of Fire",
+ author: "J.K. Rowling",
+ metadata: [
+ "description": "Fourth year of school starts, big drama ensues.",
+ "price": 24.95,
+ "ages": [10, 99]
+ ]
+ )
+ ]
+ )
+```
+
@@ -247,6 +311,24 @@ const { data, error } = await supabase.from('books').select(`
`)
```
+
+
+
+```swift
+try await supabase
+ .from("books")
+ .select(
+ """
+ title,
+ description: metadata->description,
+ price: metadata->price,
+ low_age: metadata->ages->0,
+ high_age: metadata->ages->1
+ """
+ )
+ .execute()
+```
+
diff --git a/apps/docs/content/guides/database/tables.mdx b/apps/docs/content/guides/database/tables.mdx
index 328740a09fa..54945eef4ea 100644
--- a/apps/docs/content/guides/database/tables.mdx
+++ b/apps/docs/content/guides/database/tables.mdx
@@ -230,6 +230,28 @@ await supabase
}]);
```
+
+
+
+```swift
+try await supabase.from("movies")
+ .insert(
+ [
+ [
+ "name": "The Empire Strikes Back",
+ "description":
+ "After the Rebels are brutally overpowered by the Empire on the ice planet Hoth, Luke Skywalker begins Jedi training with Yoda.",
+ ],
+ [
+ "name": "Return of the Jedi",
+ "description":
+ "After a daring mission to rescue Han Solo from Jabba the Hutt, the Rebels dispatch to Endor to destroy the second Death Star.",
+ ],
+ ]
+ )
+ .execute()
+```
+
diff --git a/apps/docs/content/guides/realtime.mdx b/apps/docs/content/guides/realtime.mdx
index dee6cf6766f..8bf656ed6ba 100644
--- a/apps/docs/content/guides/realtime.mdx
+++ b/apps/docs/content/guides/realtime.mdx
@@ -110,6 +110,33 @@ supabase
.subscribe();
```
+
+
+
+```swift
+// Initialize the Swift client
+import Supabase
+
+let supabase = SupabaseClient(supabaseURL: SUPABASE_URL, supabaseKey: SUPABASE_ANON_KEY)
+
+// Create channel
+let channel = await supabase.realtime.channel("todos")
+
+// Create the observations before subscribing
+let insertions = await channel.postgresChanges(
+ InsertAction.self,
+ schema: "public",
+ table: "todos"
+)
+
+await channel.subscribe()
+
+for await insertion in insertions {
+ let todo = try insertion.decoded(as: Todo.self)
+ print("Todo inserted", todo)
+}
+```
+
diff --git a/apps/docs/content/guides/realtime/broadcast.mdx b/apps/docs/content/guides/realtime/broadcast.mdx
index ea497c0c89e..ae0ef21f32a 100644
--- a/apps/docs/content/guides/realtime/broadcast.mdx
+++ b/apps/docs/content/guides/realtime/broadcast.mdx
@@ -49,6 +49,18 @@ Go to your Supabase project's [API Settings](https://supabase.com/dashboard/proj
final supabase = Supabase.instance.client;
```
+
+
+
+ ```swift
+ import Supabase
+
+ let SUPABASE_URL = "https://.supabase.co"
+ let SUPABASE_KEY = ""
+
+ let client = SupabaseClient(supabaseURL: URL(string: SUPABASE_URL)!, supabaseKey: SUPABASE_KEY)
+ ```
+
@@ -112,6 +124,22 @@ You can provide a callback for the `broadcast` channel to receive message. In th
.subscribe();
```
+
+
+
+ ```swift
+ let channelA = await clientA.channel("room-1")
+
+ // Listen for broadcast messages
+ let broadcastStream = await channelA.broadcast(event: "test")
+
+ await channelA.subscribe()
+
+ for await event in broadcastStream {
+ print(event)
+ }
+ ```
+
@@ -185,6 +213,22 @@ You can provide a callback for the `broadcast` channel to receive message. In th
});
```
+
+
+
+ We can send Broadcast messages using `channelB.broadcast()`. Let's set up another client to send messages.
+
+ ```swift
+ let channelB = await clientA.channel("room-1")
+
+ await channelB.subscribe()
+
+ try await channelB.broadcast(
+ event: "test",
+ message: YourMessage(message: "hello, world!")
+ )
+ ```
+
@@ -273,6 +317,28 @@ You can pass configuration options while initializing the Supabase Client.
});
```
+
+
+
+ By default, broadcast messages are only sent to other clients. You can broadcast messages back to the sender by setting Broadcast's `receiveOwnBroadcasts` parameter to `true`.
+
+ ```swift
+ let myChannel = await supabase.channel("room-2") {
+ $0.broadcast.receiveOwnBroadcasts = true
+ }
+
+ let broadcastStream = await myChannel.broadcast(event: "test-my-messages")
+
+ await myChannel.subscribe()
+
+ try await myChannel.broadcast(
+ event: "test-my-messages",
+ payload: YourMessage(
+ message: "talking to myself"
+ )
+ )
+ ```
+
@@ -361,6 +427,21 @@ You can pass configuration options while initializing the Supabase Client.
});
```
+
+
+
+ You can confirm that Realtime received your message by setting Broadcast's `acknowledgeBroadcasts` config to `true`.
+
+ ```swift
+ let myChannel = await clientD.channel("room-3") {
+ $0.broadcast.acknowledgeBroadcasts = true
+ }
+
+ await myChannel.subscribe()
+
+ await myChannel.broadcast(event: "acknowledge", message: [:])
+ ```
+
@@ -435,6 +516,18 @@ You can also send a Broadcast message by making an HTTP request to Realtime serv
print(res);
```
+
+
+ ```swift
+ let myChannel = await supabase.channel("room-2") {
+ $0.broadcast.acknowledgeBroadcasts = true
+ }
+
+ // No need to subscribe to channel
+
+ await myChannel.broadcast(event: "test", message: ["message": "HI"])
+ ```
+
```kotlin
diff --git a/apps/docs/content/guides/realtime/postgres-changes.mdx b/apps/docs/content/guides/realtime/postgres-changes.mdx
index 252e79330e5..134ca62edd1 100644
--- a/apps/docs/content/guides/realtime/postgres-changes.mdx
+++ b/apps/docs/content/guides/realtime/postgres-changes.mdx
@@ -236,6 +236,26 @@ supabase
.subscribe();
```
+
+
+
+```swift
+let myChannel = await supabase.channel("schema-db-changes")
+
+let changes = await myChannel.postgresChange(AnyAction.self, schema: "public")
+
+await myChannel.subscribe()
+
+for await change in changes {
+ switch change {
+ case .insert(let action): print(action)
+ case .update(let action): print(action)
+ case .delete(let action): print(action)
+ case .select(let action): print(action)
+ }
+}
+```
+
@@ -302,6 +322,23 @@ final changes = supabase
.subscribe();
```
+
+
+
+Use `InsertAction.self` as type to listen only to database `INSERT`s:
+
+```swift
+let myChannel = await supabase.channel("schema-db-changes")
+
+let changes = await myChannel.postgresChange(InsertAction.self, schema: "public")
+
+await myChannel.subscribe()
+
+for await change in changes {
+ print(change.record)
+}
+```
+
@@ -366,6 +403,23 @@ supabase
.subscribe();
```
+
+
+
+Use `UpdateAction.self` as type to listen only to database `UPDATE`s:
+
+```swift
+let myChannel = await supabase.channel("schema-db-changes")
+
+let changes = await myChannel.postgresChange(UpdateAction.self, schema: "public")
+
+await myChannel.subscribe()
+
+for await change in changes {
+ print(change.oldRecord, change.record)
+}
+```
+
@@ -430,6 +484,23 @@ supabase
.subscribe();
```
+
+
+
+Use `DeleteAction.self` as type to listen only to database `DELETE`s:
+
+```swift
+let myChannel = await supabase.channel("schema-db-changes")
+
+let changes = await myChannel.postgresChange(DeleteAction.self, schema: "public")
+
+await myChannel.subscribe()
+
+for await change in changes {
+ print(change.oldRecord)
+}
+```
+
@@ -496,6 +567,26 @@ supabase
.subscribe();
```
+
+
+
+```swift
+let myChannel = await supabase.channel("db-changes")
+
+let changes = await myChannel.postgresChange(AnyAction.self, schema: "public", table: "todos")
+
+await myChannel.subscribe()
+
+for await change in changes {
+ switch change {
+ case .insert(let action): print(action)
+ case .update(let action): print(action)
+ case .delete(let action): print(action)
+ case .select(let action): print(action)
+ }
+}
+```
+
@@ -576,6 +667,18 @@ supabase
.subscribe();
```
+
+
+
+```swift
+let myChannel = await supabase.channel("db-changes")
+
+let messageChanges = await myChannel.postgresChange(AnyAction.self, schema: "public", table: "messages")
+let userChanges = await myChannel.postgresChange(InsertAction.self, schema: "public", table: "users")
+
+await myChannel.subscribe()
+```
+
@@ -641,6 +744,26 @@ const changes = client
.subscribe();
```
+
+
+
+```swift
+let myChannel = await supabase.channel("db-changes")
+
+let changes = await myChannel.postgresChange(
+ InsertAction.self,
+ schema: "public",
+ table: "todos",
+ filter: "id=eq.1"
+)
+
+await myChannel.subscribe()
+
+for await change in changes {
+ print(change.record)
+}
+```
+
@@ -716,6 +839,26 @@ supabase
.subscribe();
```
+
+
+
+```swift
+let myChannel = await supabase.channel("db-changes")
+
+let changes = await myChannel.postgresChange(
+ UpdateAction.self,
+ schema: "public",
+ table: "messages",
+ filter: "body=eq.hey"
+)
+
+await myChannel.subscribe()
+
+for await change in changes {
+ print(change.record)
+}
+```
+
@@ -789,6 +932,26 @@ supabase
.subscribe();
```
+
+
+
+```swift
+let myChannel = await supabase.channel("db-changes")
+
+let changes = await myChannel.postgresChange(
+ UpdateAction.self,
+ schema: "public",
+ table: "messages",
+ filter: "body=neq.hey"
+)
+
+await myChannel.subscribe()
+
+for await change in changes {
+ print(change.record)
+}
+```
+
@@ -863,6 +1026,26 @@ supabase
.subscribe();
```
+
+
+
+```swift
+let myChannel = await supabase.channel("db-changes")
+
+let changes = await myChannel.postgresChange(
+ InsertAction.self,
+ schema: "public",
+ table: "profiles",
+ filter: "age=lt.65"
+)
+
+await myChannel.subscribe()
+
+for await change in changes {
+ print(change.record)
+}
+```
+
@@ -936,6 +1119,26 @@ supabase
.subscribe();
```
+
+
+
+```swift
+let myChannel = await supabase.channel("db-changes")
+
+let changes = await myChannel.postgresChange(
+ InsertAction.self,
+ schema: "public",
+ table: "profiles",
+ filter: "age=lte.65"
+)
+
+await myChannel.subscribe()
+
+for await change in changes {
+ print(change.record)
+}
+```
+
@@ -1009,6 +1212,26 @@ supabase
.subscribe();
```
+
+
+
+```swift
+let myChannel = await supabase.channel("db-changes")
+
+let changes = await myChannel.postgresChange(
+ InsertAction.self,
+ schema: "public",
+ table: "products",
+ filter: "quantity=gt.10"
+)
+
+await myChannel.subscribe()
+
+for await change in changes {
+ print(change.record)
+}
+```
+
@@ -1082,6 +1305,26 @@ supabase
.subscribe();
```
+
+
+
+```swift
+let myChannel = await supabase.channel("db-changes")
+
+let changes = await myChannel.postgresChange(
+ InsertAction.self,
+ schema: "public",
+ table: "products",
+ filter: "quantity=gte.10"
+)
+
+await myChannel.subscribe()
+
+for await change in changes {
+ print(change.record)
+}
+```
+
@@ -1155,6 +1398,26 @@ supabase
.subscribe();
```
+
+
+
+```swift
+let myChannel = await supabase.channel("db-changes")
+
+let changes = await myChannel.postgresChange(
+ InsertAction.self,
+ schema: "public",
+ table: "products",
+ filter: "name=in.(red, blue, yellow)"
+)
+
+await myChannel.subscribe()
+
+for await change in changes {
+ print(change.record)
+}
+```
+
@@ -1277,6 +1540,28 @@ supabase
.subscribe();
```
+
+
+
+```swift
+await supabase.realtime.setAuth("your-custom-jwt")
+
+let myChannel = await supabase.channel("db-changes")
+
+let changes = await myChannel.postgresChange(
+ UpdateAction.self,
+ schema: "public",
+ table: "products",
+ filter: "name=in.(red, blue, yellow)"
+)
+
+await myChannel.subscribe()
+
+for await change in changes {
+ print(change.record)
+}
+```
+
@@ -1333,6 +1618,13 @@ supabase.realtime.setAuth('fresh-token')
supabase.realtime.setAuth('fresh-token');
```
+
+
+
+```swift
+await supabase.realtime.setAuth("fresh-token")
+```
+
diff --git a/apps/docs/content/guides/realtime/presence.mdx b/apps/docs/content/guides/realtime/presence.mdx
index d9712186d3b..02c6cf182ad 100644
--- a/apps/docs/content/guides/realtime/presence.mdx
+++ b/apps/docs/content/guides/realtime/presence.mdx
@@ -48,6 +48,17 @@ void main() {
final supabase = Supabase.instance.client;
```
+
+
+
+```swift
+let supabaseURL = "https://.supabase.co"
+let supabaseKey = ""
+let supabase = SupabaseClient(supabaseURL: URL(string: supabaseURL)!, supabaseKey: supabaseKey)
+
+let realtime = supabase.realtime
+```
+
@@ -110,6 +121,23 @@ roomOne.onPresenceSync((_) {
}).subscribe();
```
+
+
+
+Listen to the presence change stream, emitting a new `PresenceAction` whenever someone joins or leaves:
+
+```swift
+let roomOne = await supabase.channel("room_01")
+let presenceStream = await roomOne.presenceChange()
+
+await roomOne.subscribe()
+
+for await presence in presenceStream {
+ print(presence.join) // You can also use presence.decodeJoins(as: MyType.self)
+ print(presence.leaves) // You can also use presence.decodeLeaves(as: MyType.self)
+}
+```
+
@@ -180,6 +208,31 @@ roomOne.subscribe((status, error) async {
});
```
+
+
+
+```swift
+let roomOne = await supabase.channel("room_01")
+
+// Using a custom type
+let userStatus = UserStatus(
+ user: "user-1",
+ onlineAt: Date().timeIntervalSince1970
+)
+
+await roomOne.subscribe()
+
+try await roomOne.track(userStatus)
+
+// Or using a raw JSONObject.
+await roomOne.track(
+ [
+ "user": .string("user-1"),
+ "onlineAt": .double(Date().timeIntervalSince1970)
+ ]
+)
+```
+
@@ -237,6 +290,13 @@ untrackPresence() async {
untrackPresence();
```
+
+
+
+```swift
+await roomOne.untrack()
+```
+
@@ -290,6 +350,15 @@ final channelC = supabase.channel(
);
```
+
+
+
+```swift
+let channelC = await supabase.channel("test") {
+ $0.presence.key = "userId-123"
+}
+```
+
diff --git a/apps/docs/content/guides/storage/serving/image-transformations.mdx b/apps/docs/content/guides/storage/serving/image-transformations.mdx
index d60dc23a173..deab689297c 100644
--- a/apps/docs/content/guides/storage/serving/image-transformations.mdx
+++ b/apps/docs/content/guides/storage/serving/image-transformations.mdx
@@ -37,6 +37,17 @@ supabase.storage.from('bucket').getPublicUrl('image.jpg', {
})
```
+
+
+
+```swift
+let url = try await supabase.storage.from("bucket")
+ .getPublicURL(
+ path: "image.jpg"
+ options: TransformOptions(with: 500, height: 600)
+ )
+```
+
@@ -75,6 +86,21 @@ supabase.storage.from('bucket').createSignedUrl('image.jpg', 60000, {
})
```
+
+
+
+```swift
+let url = try await supabase.storage.from("bucket")
+ .createSignedURL(
+ path: "image.jpg",
+ expiresIn: 60,
+ transform: TransformOptions(
+ width: 200,
+ height: 200
+ )
+ )
+```
+
@@ -111,6 +137,20 @@ supabase.storage.from('bucket').download('image.jpg', {
})
```
+
+
+
+```swift
+let data = try await supabase.storage.from("bucket")
+ .download(
+ path: "image.jpg",
+ options: TransformOptions(
+ width: 800,
+ height: 300
+ )
+ )
+```
+
@@ -164,6 +204,21 @@ await storage.from('bucket').download('image.jpeg', {
})
```
+
+
+
+```swift
+let data = try await supabase.storage.from("bucket")
+ .download(
+ path: "image.jpg",
+ options: TransformOptions(
+ width: 200,
+ height: 200,
+ format: "origin"
+ )
+ )
+```
+
@@ -248,6 +303,19 @@ supabase.storage.from('bucket').download('image.jpg', {
})
```
+
+
+
+```swift
+let data = try await supabase.storage.from("bucket")
+ .download(
+ path: "image.jpg",
+ options: TransformOptions(
+ quality: 50
+ )
+ )
+```
+
@@ -303,6 +371,21 @@ supabase.storage.from('bucket').download('image.jpg', {
})
```
+
+
+
+```swift
+let data = try await supabase.storage.from("bucket")
+ .download(
+ path: "image.jpg",
+ options: TransformOptions(
+ width: 800,
+ height: 300,
+ resize: "contain" // "cover" | "fill"
+ )
+ )
+```
+
diff --git a/apps/docs/content/guides/storage/uploads/standard-uploads.mdx b/apps/docs/content/guides/storage/uploads/standard-uploads.mdx
index 90f219f5726..a38a23e2691 100644
--- a/apps/docs/content/guides/storage/uploads/standard-uploads.mdx
+++ b/apps/docs/content/guides/storage/uploads/standard-uploads.mdx
@@ -44,6 +44,18 @@ async function uploadFile(file) {
}
```
+
+
+
+```swift
+import Supabase
+
+// Create Supabase client
+let supabase = SupabaseClient(supabaseURL: URL(string: "your_project_url")!, supabaseKey: "your_supabase_api_key")
+
+try await supabase.storage.from("bucket_name").upload(path: "file_path", file: file)
+```
+
@@ -88,6 +100,25 @@ await supabase.storage.from('bucket_name').upload('file_path', file, {
})
```
+
+
+
+```swift
+import Supabase
+
+// Create Supabase client
+let supabase = SupabaseClient(supabaseURL: URL(string: "your_project_url")!, supabaseKey: "your_supabase_api_key")
+
+try await supabase.storage.from("bucket_name")
+ .upload(
+ path: "file_path",
+ file: file,
+ options: FileOptions(
+ upsert: true
+ )
+ )
+```
+
@@ -116,6 +147,25 @@ await supabase.storage.from('bucket_name').upload('file_path', file, {
})
```
+
+
+
+```swift
+import Supabase
+
+// Create Supabase client
+let supabase = SupabaseClient(supabaseURL: URL(string: "your_project_url")!, supabaseKey: "your_supabase_api_key")
+
+try await supabase.storage.from("bucket_name")
+ .upload(
+ path: "file_path",
+ file: file,
+ options: FileOptions(
+ contentType: "image/jpeg"
+ )
+ )
+```
+
diff --git a/apps/www/data/Footer.ts b/apps/www/data/Footer.ts
index 1ac455ff534..a4c785d1758 100644
--- a/apps/www/data/Footer.ts
+++ b/apps/www/data/Footer.ts
@@ -96,7 +96,7 @@ const footerData = [
},
{
text: 'Contributing',
- url: '/docs/handbook/contributing',
+ url: 'https://github.com/supabase/supabase/blob/master/CONTRIBUTING.md',
},
{
text: 'Open Source',
diff --git a/examples/ai/llamaindex/llamaindex.ipynb b/examples/ai/llamaindex/llamaindex.ipynb
index 6f1a26b0d65..435b13cd01c 100644
--- a/examples/ai/llamaindex/llamaindex.ipynb
+++ b/examples/ai/llamaindex/llamaindex.ipynb
@@ -53,10 +53,10 @@
"# logging.basicConfig(stream=sys.stdout, level=logging.DEBUG)\n",
"# logging.getLogger().addHandler(logging.StreamHandler(stream=sys.stdout))\n",
"\n",
- "from llama_index.storage import StorageContext\n",
+ "from llama_index.core.storage import StorageContext\n",
"from llama_index.readers.web import SimpleWebPageReader\n",
"from llama_index.indices.vector_store import VectorStoreIndex\n",
- "from llama_index.vector_stores import SupabaseVectorStore\n",
+ "from llama_index.vector_stores.supabase import SupabaseVectorStore\n",
"import textwrap\n",
"import html2text"
]