diff --git a/.github/workflows/prettier.yml b/.github/workflows/prettier.yml
index 8f36d889f4..b42c8cc6b8 100644
--- a/.github/workflows/prettier.yml
+++ b/.github/workflows/prettier.yml
@@ -21,8 +21,10 @@ jobs:
uses: actions/checkout@08eba0b27e820071cde6df949e0beb9ba4906955 # v4.3.0
with:
sparse-checkout: |
- apps
- patches
+ apps
+ packages
+ blocks
+ patches
- uses: pnpm/action-setup@41ff72655975bd51cab0327fa583b6e92b6d3061 # v4.2.0
name: Install pnpm
with:
diff --git a/apps/docs/content/guides/database/replication/replication-faq.mdx b/apps/docs/content/guides/database/replication/replication-faq.mdx
index 967c4022be..da6710c363 100644
--- a/apps/docs/content/guides/database/replication/replication-faq.mdx
+++ b/apps/docs/content/guides/database/replication/replication-faq.mdx
@@ -19,6 +19,7 @@ Replication currently supports **BigQuery** as the only managed destination. See
We are working on adding more destinations in the future. Availability may continue to vary based on the planned roll-out strategy.
{/* supa-mdx-lint-disable-next-line Rule001HeadingCase */}
+
## What happened to Analytics Buckets replication?
We are currently working on a new Supabase Warehouse product designed to address the limitations of the previous Analytics Buckets. Our goal is to build a solution we can confidently stand behind, rather than continuing to support an approach that does not meet the quality and flexibility we want for our users.
diff --git a/apps/docs/content/guides/functions/recursive-functions.mdx b/apps/docs/content/guides/functions/recursive-functions.mdx
index aca4a2bac6..e77c2f8d83 100644
--- a/apps/docs/content/guides/functions/recursive-functions.mdx
+++ b/apps/docs/content/guides/functions/recursive-functions.mdx
@@ -44,10 +44,7 @@ When the rate limit is exceeded, calling another Edge Function throws a `RateLim
```typescript
import { createClient } from 'jsr:@supabase/supabase-js@2'
-const supabase = createClient(
- Deno.env.get('SUPABASE_URL')!,
- Deno.env.get('SUPABASE_ANON_KEY')!
-)
+const supabase = createClient(Deno.env.get('SUPABASE_URL')!, Deno.env.get('SUPABASE_ANON_KEY')!)
Deno.serve(async (req) => {
try {
@@ -87,17 +84,14 @@ Deno.serve(async (req) => {
```typescript
Deno.serve(async (req) => {
try {
- const response = await fetch(
- `${Deno.env.get('SUPABASE_URL')}/functions/v1/other-function`,
- {
- method: 'POST',
- headers: {
- Authorization: `Bearer ${Deno.env.get('SUPABASE_ANON_KEY')}`,
- 'Content-Type': 'application/json',
- },
- body: JSON.stringify({ foo: 'bar' }),
- }
- )
+ const response = await fetch(`${Deno.env.get('SUPABASE_URL')}/functions/v1/other-function`, {
+ method: 'POST',
+ headers: {
+ Authorization: `Bearer ${Deno.env.get('SUPABASE_ANON_KEY')}`,
+ 'Content-Type': 'application/json',
+ },
+ body: JSON.stringify({ foo: 'bar' }),
+ })
return response
} catch (err) {
if (err instanceof Deno.errors.RateLimitError) {
@@ -136,16 +130,9 @@ You can also use `retryAfterMs` to implement automatic retries within your funct
```typescript
import { createClient } from 'jsr:@supabase/supabase-js@2'
-const supabase = createClient(
- Deno.env.get('SUPABASE_URL')!,
- Deno.env.get('SUPABASE_ANON_KEY')!
-)
+const supabase = createClient(Deno.env.get('SUPABASE_URL')!, Deno.env.get('SUPABASE_ANON_KEY')!)
-async function invokeWithRetry(
- functionName: string,
- payload: object,
- maxRetries = 3
-) {
+async function invokeWithRetry(functionName: string, payload: object, maxRetries = 3) {
for (let attempt = 0; attempt < maxRetries; attempt++) {
try {
const { data, error } = await supabase.functions.invoke(functionName, {
@@ -279,15 +266,15 @@ async function processWithDelay(items: any[]) {
## Common patterns and their impact
-| Pattern | Budget consumption | Recommendation |
-| --- | --- | --- |
-| Simple chain (A to B to C) | Low | Generally safe |
-| Fan-out (A to B, C, D, E) | Moderate | Limit concurrency |
-| Deep recursion (A to A to A...) | High | Set max depth |
-| Unbounded loops | Very high | Avoid, use queues |
+| Pattern | Budget consumption | Recommendation |
+| ------------------------------- | ------------------ | ----------------- |
+| Simple chain (A to B to C) | Low | Generally safe |
+| Fan-out (A to B, C, D, E) | Moderate | Limit concurrency |
+| Deep recursion (A to A to A...) | High | Set max depth |
+| Unbounded loops | Very high | Avoid, use queues |
## Increasing rate limits
Currently, all plans have the same rate limit budget. We are working on introducing custom limits for different use cases.
-If you need a higher rate limit for your project, [contact support](/dashboard/support/new) with details about your use case.
+If you need a higher rate limit for your project, [contact support](/dashboard/support/new) with details about your use case.
diff --git a/apps/ui-library/content/docs/nuxtjs/current-user-avatar.mdx b/apps/ui-library/content/docs/nuxtjs/current-user-avatar.mdx
index e6f1ca864e..29fe776f34 100644
--- a/apps/ui-library/content/docs/nuxtjs/current-user-avatar.mdx
+++ b/apps/ui-library/content/docs/nuxtjs/current-user-avatar.mdx
@@ -27,11 +27,11 @@ property which gets populated automatically by Supabase Auth if the user logged
The `CurrentUserAvatar` component is designed to be used anywhere in your app. Add the `` component to your page and it will render the avatar of the current user, with a fallback.
-```html
+```vue
diff --git a/apps/ui-library/content/docs/nuxtjs/dropzone.mdx b/apps/ui-library/content/docs/nuxtjs/dropzone.mdx
index 4aa0960307..e36e378e19 100644
--- a/apps/ui-library/content/docs/nuxtjs/dropzone.mdx
+++ b/apps/ui-library/content/docs/nuxtjs/dropzone.mdx
@@ -42,18 +42,18 @@ The File Upload component makes it easy to add file uploads to your app, with bu
- Simply add this `` component to your page and it will handle the rest.
-```html
+```vue
diff --git a/apps/ui-library/content/docs/nuxtjs/realtime-avatar-stack.mdx b/apps/ui-library/content/docs/nuxtjs/realtime-avatar-stack.mdx
index 1281107ea9..d66a06b482 100644
--- a/apps/ui-library/content/docs/nuxtjs/realtime-avatar-stack.mdx
+++ b/apps/ui-library/content/docs/nuxtjs/realtime-avatar-stack.mdx
@@ -22,9 +22,9 @@ This block assumes that you have already installed a Supabase client for Nuxt fr
The `RealtimeAvatarStack` component renders stacked avatars which are connected to Supabase Realtime. It uses the Presence feature of Supabase Realtime. You can use this to show currently online users in a chatroom, game session or collaborative app.
-```html
+```vue
diff --git a/apps/ui-library/content/docs/nuxtjs/realtime-cursor.mdx b/apps/ui-library/content/docs/nuxtjs/realtime-cursor.mdx
index e89d6da110..7374feacec 100644
--- a/apps/ui-library/content/docs/nuxtjs/realtime-cursor.mdx
+++ b/apps/ui-library/content/docs/nuxtjs/realtime-cursor.mdx
@@ -37,9 +37,9 @@ The Realtime Cursors component lets users share their cursor position with other
The Realtime Cursor component is designed to be used in a room. It can be used to build real-time collaborative applications. Add the `` component to your page and it will render realtime cursors from other users in the room.
-```html
+```vue
diff --git a/apps/ui-library/content/docs/vue/current-user-avatar.mdx b/apps/ui-library/content/docs/vue/current-user-avatar.mdx
index 280a6c05d0..d910c54510 100644
--- a/apps/ui-library/content/docs/vue/current-user-avatar.mdx
+++ b/apps/ui-library/content/docs/vue/current-user-avatar.mdx
@@ -24,11 +24,11 @@ property which gets populated automatically by Supabase Auth if the user logged
The `CurrentUserAvatar` component is designed to be used anywhere in your app. Add the `` component to your page and it will render the avatar of the current user, with a fallback.
-```html
+```vue
diff --git a/apps/ui-library/content/docs/vue/dropzone.mdx b/apps/ui-library/content/docs/vue/dropzone.mdx
index b8fbae786c..b32bae065b 100644
--- a/apps/ui-library/content/docs/vue/dropzone.mdx
+++ b/apps/ui-library/content/docs/vue/dropzone.mdx
@@ -42,18 +42,18 @@ The File Upload component makes it easy to add file uploads to your app, with bu
- Simply add this `` component to your page and it will handle the rest.
-```html
+```vue
diff --git a/apps/ui-library/content/docs/vue/realtime-avatar-stack.mdx b/apps/ui-library/content/docs/vue/realtime-avatar-stack.mdx
index 8ea06849e8..a7eb4bc40c 100644
--- a/apps/ui-library/content/docs/vue/realtime-avatar-stack.mdx
+++ b/apps/ui-library/content/docs/vue/realtime-avatar-stack.mdx
@@ -22,9 +22,9 @@ This block assumes that you have already installed a Supabase client for Vue fro
The `RealtimeAvatarStack` component renders stacked avatars which are connected to Supabase Realtime. It uses the Presence feature of Supabase Realtime. You can use this to show currently online users in a chatroom, game session or collaborative app.
-```html
+```vue
diff --git a/apps/ui-library/content/docs/vue/realtime-cursor.mdx b/apps/ui-library/content/docs/vue/realtime-cursor.mdx
index 281bfdd433..cc7780ce58 100644
--- a/apps/ui-library/content/docs/vue/realtime-cursor.mdx
+++ b/apps/ui-library/content/docs/vue/realtime-cursor.mdx
@@ -37,9 +37,9 @@ The Realtime Cursors component lets users share their cursor position with other
The Realtime Cursor component is designed to be used in a room. It can be used to build real-time collaborative applications. Add the `` component to your page and it will render realtime cursors from other users in the room.
-```html
+```vue
diff --git a/apps/ui-library/public/r/current-user-avatar-nuxtjs.json b/apps/ui-library/public/r/current-user-avatar-nuxtjs.json
index 7d4908ffd1..90bd95032d 100644
--- a/apps/ui-library/public/r/current-user-avatar-nuxtjs.json
+++ b/apps/ui-library/public/r/current-user-avatar-nuxtjs.json
@@ -19,13 +19,13 @@
},
{
"path": "registry/default/current-user-avatar/nuxtjs/app/composables/useCurrentUserName.ts",
- "content": "import { ref, onMounted } from 'vue'\n// @ts-ignore\nimport { createClient } from \"@/lib/supabase/client\"\n\nexport function useCurrentUserName() {\n const name = ref(null)\n\n const fetchProfileName = async () => {\n const { data, error } = await createClient().auth.getSession()\n\n if (error) {\n console.error(error)\n return\n }\n\n name.value = data.session?.user.user_metadata.full_name ?? '?'\n }\n\n onMounted(() => {\n fetchProfileName()\n })\n\n return {\n name,\n }\n}\n",
+ "content": "import { ref, onMounted } from 'vue'\n// @ts-ignore\nimport { createClient } from '@/lib/supabase/client'\n\nexport function useCurrentUserName() {\n const name = ref(null)\n\n const fetchProfileName = async () => {\n const { data, error } = await createClient().auth.getSession()\n\n if (error) {\n console.error(error)\n return\n }\n\n name.value = data.session?.user.user_metadata.full_name ?? '?'\n }\n\n onMounted(() => {\n fetchProfileName()\n })\n\n return {\n name,\n }\n}\n",
"type": "registry:component",
"target": "app/composables/useCurrentUserName.ts"
},
{
"path": "registry/default/current-user-avatar/nuxtjs/app/composables/useCurrentUserImage.ts",
- "content": "import { ref, onMounted } from 'vue'\n// @ts-ignore\nimport { createClient } from \"@/lib/supabase/client\"\n\nexport function useCurrentUserImage() {\n const image = ref(null)\n\n const fetchUserImage = async () => {\n const { data, error } = await createClient().auth.getSession()\n\n if (error) {\n console.error(error)\n return\n }\n\n image.value = data.session?.user.user_metadata.avatar_url ?? null\n }\n\n onMounted(() => {\n fetchUserImage()\n })\n\n return {\n image,\n }\n}\n",
+ "content": "import { ref, onMounted } from 'vue'\n// @ts-ignore\nimport { createClient } from '@/lib/supabase/client'\n\nexport function useCurrentUserImage() {\n const image = ref(null)\n\n const fetchUserImage = async () => {\n const { data, error } = await createClient().auth.getSession()\n\n if (error) {\n console.error(error)\n return\n }\n\n image.value = data.session?.user.user_metadata.avatar_url ?? null\n }\n\n onMounted(() => {\n fetchUserImage()\n })\n\n return {\n image,\n }\n}\n",
"type": "registry:component",
"target": "app/composables/useCurrentUserImage.ts"
}
diff --git a/apps/ui-library/public/r/current-user-avatar-vue.json b/apps/ui-library/public/r/current-user-avatar-vue.json
index b9e7dce2f3..11c0104e1b 100644
--- a/apps/ui-library/public/r/current-user-avatar-vue.json
+++ b/apps/ui-library/public/r/current-user-avatar-vue.json
@@ -19,13 +19,13 @@
},
{
"path": "registry/default/current-user-avatar/vue/composables/useCurrentUserName.ts",
- "content": "import { ref, onMounted } from 'vue'\n// @ts-ignore\nimport { createClient } from \"@/lib/supabase/client\"\n\nexport function useCurrentUserName() {\n const name = ref(null)\n\n const fetchProfileName = async () => {\n const { data, error } = await createClient().auth.getSession()\n\n if (error) {\n console.error(error)\n return\n }\n\n name.value = data.session?.user.user_metadata.full_name ?? '?'\n }\n\n onMounted(() => {\n fetchProfileName()\n })\n\n return {\n name,\n }\n}\n",
+ "content": "import { ref, onMounted } from 'vue'\n// @ts-ignore\nimport { createClient } from '@/lib/supabase/client'\n\nexport function useCurrentUserName() {\n const name = ref(null)\n\n const fetchProfileName = async () => {\n const { data, error } = await createClient().auth.getSession()\n\n if (error) {\n console.error(error)\n return\n }\n\n name.value = data.session?.user.user_metadata.full_name ?? '?'\n }\n\n onMounted(() => {\n fetchProfileName()\n })\n\n return {\n name,\n }\n}\n",
"type": "registry:component",
"target": "composables/useCurrentUserName.ts"
},
{
"path": "registry/default/current-user-avatar/vue/composables/useCurrentUserImage.ts",
- "content": "import { ref, onMounted } from 'vue'\n// @ts-ignore\nimport { createClient } from \"@/lib/supabase/client\"\n\nexport function useCurrentUserImage() {\n const image = ref(null)\n\n const fetchUserImage = async () => {\n const { data, error } = await createClient().auth.getSession()\n\n if (error) {\n console.error(error)\n return\n }\n\n image.value = data.session?.user.user_metadata.avatar_url ?? null\n }\n\n onMounted(() => {\n fetchUserImage()\n })\n\n return {\n image,\n }\n}\n",
+ "content": "import { ref, onMounted } from 'vue'\n// @ts-ignore\nimport { createClient } from '@/lib/supabase/client'\n\nexport function useCurrentUserImage() {\n const image = ref(null)\n\n const fetchUserImage = async () => {\n const { data, error } = await createClient().auth.getSession()\n\n if (error) {\n console.error(error)\n return\n }\n\n image.value = data.session?.user.user_metadata.avatar_url ?? null\n }\n\n onMounted(() => {\n fetchUserImage()\n })\n\n return {\n image,\n }\n}\n",
"type": "registry:component",
"target": "composables/useCurrentUserImage.ts"
}
diff --git a/apps/ui-library/public/r/realtime-avatar-stack-nuxtjs.json b/apps/ui-library/public/r/realtime-avatar-stack-nuxtjs.json
index f30c2151e7..4bd2326eea 100644
--- a/apps/ui-library/public/r/realtime-avatar-stack-nuxtjs.json
+++ b/apps/ui-library/public/r/realtime-avatar-stack-nuxtjs.json
@@ -26,19 +26,19 @@
},
{
"path": "registry/default/realtime-avatar-stack/nuxtjs/app/composables/useCurrentUserImage.ts",
- "content": "import { ref, onMounted } from 'vue'\n// @ts-ignore\nimport { createClient } from \"@/lib/supabase/client\"\n\nexport function useCurrentUserImage() {\n const image = ref(null)\n\n const fetchUserImage = async () => {\n const { data, error } = await createClient().auth.getSession()\n\n if (error) {\n console.error(error)\n return\n }\n\n image.value = data.session?.user.user_metadata.avatar_url ?? null\n }\n\n onMounted(() => {\n fetchUserImage()\n })\n\n return {\n image,\n }\n}\n",
+ "content": "import { ref, onMounted } from 'vue'\n// @ts-ignore\nimport { createClient } from '@/lib/supabase/client'\n\nexport function useCurrentUserImage() {\n const image = ref(null)\n\n const fetchUserImage = async () => {\n const { data, error } = await createClient().auth.getSession()\n\n if (error) {\n console.error(error)\n return\n }\n\n image.value = data.session?.user.user_metadata.avatar_url ?? null\n }\n\n onMounted(() => {\n fetchUserImage()\n })\n\n return {\n image,\n }\n}\n",
"type": "registry:component",
"target": "app/composables/useCurrentUserImage.ts"
},
{
"path": "registry/default/realtime-avatar-stack/nuxtjs/app/composables/useCurrentUserName.ts",
- "content": "import { ref, onMounted } from 'vue'\n// @ts-ignore\nimport { createClient } from \"@/lib/supabase/client\"\n\nexport function useCurrentUserName() {\n const name = ref(null)\n\n const fetchProfileName = async () => {\n const { data, error } = await createClient().auth.getSession()\n\n if (error) {\n console.error(error)\n return\n }\n\n name.value = data.session?.user.user_metadata.full_name ?? '?'\n }\n\n onMounted(() => {\n fetchProfileName()\n })\n\n return {\n name,\n }\n}\n",
+ "content": "import { ref, onMounted } from 'vue'\n// @ts-ignore\nimport { createClient } from '@/lib/supabase/client'\n\nexport function useCurrentUserName() {\n const name = ref(null)\n\n const fetchProfileName = async () => {\n const { data, error } = await createClient().auth.getSession()\n\n if (error) {\n console.error(error)\n return\n }\n\n name.value = data.session?.user.user_metadata.full_name ?? '?'\n }\n\n onMounted(() => {\n fetchProfileName()\n })\n\n return {\n name,\n }\n}\n",
"type": "registry:component",
"target": "app/composables/useCurrentUserName.ts"
},
{
"path": "registry/default/realtime-avatar-stack/nuxtjs/app/composables/useRealtimePresenceRoom.ts",
- "content": "import { ref, watch, onUnmounted } from 'vue'\nimport { REALTIME_SUBSCRIBE_STATES } from '@supabase/supabase-js'\n\nimport { useCurrentUserImage } from './useCurrentUserImage'\nimport { useCurrentUserName } from './useCurrentUserName'\n// @ts-ignore\nimport { createClient } from \"@/lib/supabase/client\"\n\nconst supabase = createClient()\n\nexport type RealtimeUser = {\n id: string\n name: string\n image: string\n}\n\nexport function useRealtimePresenceRoom(roomName: string) {\n const { image: currentUserImage } = useCurrentUserImage()\n const { name: currentUserName } = useCurrentUserName()\n\n const users = ref>({})\n\n let room: ReturnType | null = null\n\n function setupRoom() {\n if (!roomName) return\n\n room = supabase.channel(roomName)\n\n room\n .on('presence', { event: 'sync' }, () => {\n const newState =\n room?.presenceState<{ image: string; name: string }>() ?? {}\n\n const newUsers = Object.fromEntries(\n Object.entries(newState).map(([key, values]) => {\n const typedValues = values as Array<{ image: string; name: string }>\n return [\n key,\n {\n id: key,\n name: typedValues[0].name,\n image: typedValues[0].image,\n },\n ]\n })\n ) as Record\n\n users.value = newUsers\n })\n .subscribe(async (status: REALTIME_SUBSCRIBE_STATES) => {\n if (status === REALTIME_SUBSCRIBE_STATES.SUBSCRIBED && room) {\n await room.track({\n name: currentUserName.value,\n image: currentUserImage.value,\n })\n } else {\n users.value = {}\n }\n })\n }\n\n function cleanup() {\n if (room) {\n room.unsubscribe()\n room = null\n }\n }\n\n watch(\n [() => roomName, currentUserName, currentUserImage],\n () => {\n cleanup()\n setupRoom()\n },\n { immediate: true }\n )\n\n onUnmounted(() => {\n cleanup()\n })\n\n return { users }\n}\n",
+ "content": "import { ref, watch, onUnmounted } from 'vue'\nimport { REALTIME_SUBSCRIBE_STATES } from '@supabase/supabase-js'\n\nimport { useCurrentUserImage } from './useCurrentUserImage'\nimport { useCurrentUserName } from './useCurrentUserName'\n// @ts-ignore\nimport { createClient } from '@/lib/supabase/client'\n\nconst supabase = createClient()\n\nexport type RealtimeUser = {\n id: string\n name: string\n image: string\n}\n\nexport function useRealtimePresenceRoom(roomName: string) {\n const { image: currentUserImage } = useCurrentUserImage()\n const { name: currentUserName } = useCurrentUserName()\n\n const users = ref>({})\n\n let room: ReturnType | null = null\n\n function setupRoom() {\n if (!roomName) return\n\n room = supabase.channel(roomName)\n\n room\n .on('presence', { event: 'sync' }, () => {\n const newState = room?.presenceState<{ image: string; name: string }>() ?? {}\n\n const newUsers = Object.fromEntries(\n Object.entries(newState).map(([key, values]) => {\n const typedValues = values as Array<{ image: string; name: string }>\n return [\n key,\n {\n id: key,\n name: typedValues[0].name,\n image: typedValues[0].image,\n },\n ]\n })\n ) as Record\n\n users.value = newUsers\n })\n .subscribe(async (status: REALTIME_SUBSCRIBE_STATES) => {\n if (status === REALTIME_SUBSCRIBE_STATES.SUBSCRIBED && room) {\n await room.track({\n name: currentUserName.value,\n image: currentUserImage.value,\n })\n } else {\n users.value = {}\n }\n })\n }\n\n function cleanup() {\n if (room) {\n room.unsubscribe()\n room = null\n }\n }\n\n watch(\n [() => roomName, currentUserName, currentUserImage],\n () => {\n cleanup()\n setupRoom()\n },\n { immediate: true }\n )\n\n onUnmounted(() => {\n cleanup()\n })\n\n return { users }\n}\n",
"type": "registry:component",
"target": "app/composables/useRealtimePresenceRoom.ts"
}
diff --git a/apps/ui-library/public/r/realtime-avatar-stack-vue.json b/apps/ui-library/public/r/realtime-avatar-stack-vue.json
index 655c97194c..bee14d9f53 100644
--- a/apps/ui-library/public/r/realtime-avatar-stack-vue.json
+++ b/apps/ui-library/public/r/realtime-avatar-stack-vue.json
@@ -26,19 +26,19 @@
},
{
"path": "registry/default/realtime-avatar-stack/vue/composables/useCurrentUserImage.ts",
- "content": "import { ref, onMounted } from 'vue'\n// @ts-ignore\nimport { createClient } from \"@/lib/supabase/client\"\n\nexport function useCurrentUserImage() {\n const image = ref(null)\n\n const fetchUserImage = async () => {\n const { data, error } = await createClient().auth.getSession()\n\n if (error) {\n console.error(error)\n return\n }\n\n image.value = data.session?.user.user_metadata.avatar_url ?? null\n }\n\n onMounted(() => {\n fetchUserImage()\n })\n\n return {\n image,\n }\n}\n",
+ "content": "import { ref, onMounted } from 'vue'\n// @ts-ignore\nimport { createClient } from '@/lib/supabase/client'\n\nexport function useCurrentUserImage() {\n const image = ref(null)\n\n const fetchUserImage = async () => {\n const { data, error } = await createClient().auth.getSession()\n\n if (error) {\n console.error(error)\n return\n }\n\n image.value = data.session?.user.user_metadata.avatar_url ?? null\n }\n\n onMounted(() => {\n fetchUserImage()\n })\n\n return {\n image,\n }\n}\n",
"type": "registry:component",
"target": "composables/useCurrentUserImage.ts"
},
{
"path": "registry/default/realtime-avatar-stack/vue/composables/useCurrentUserName.ts",
- "content": "import { ref, onMounted } from 'vue'\n// @ts-ignore\nimport { createClient } from \"@/lib/supabase/client\"\n\nexport function useCurrentUserName() {\n const name = ref(null)\n\n const fetchProfileName = async () => {\n const { data, error } = await createClient().auth.getSession()\n\n if (error) {\n console.error(error)\n return\n }\n\n name.value = data.session?.user.user_metadata.full_name ?? '?'\n }\n\n onMounted(() => {\n fetchProfileName()\n })\n\n return {\n name,\n }\n}\n",
+ "content": "import { ref, onMounted } from 'vue'\n// @ts-ignore\nimport { createClient } from '@/lib/supabase/client'\n\nexport function useCurrentUserName() {\n const name = ref(null)\n\n const fetchProfileName = async () => {\n const { data, error } = await createClient().auth.getSession()\n\n if (error) {\n console.error(error)\n return\n }\n\n name.value = data.session?.user.user_metadata.full_name ?? '?'\n }\n\n onMounted(() => {\n fetchProfileName()\n })\n\n return {\n name,\n }\n}\n",
"type": "registry:component",
"target": "composables/useCurrentUserName.ts"
},
{
"path": "registry/default/realtime-avatar-stack/vue/composables/useRealtimePresenceRoom.ts",
- "content": "import { ref, watch, onUnmounted } from 'vue'\nimport { REALTIME_SUBSCRIBE_STATES } from '@supabase/supabase-js'\n\nimport { useCurrentUserImage } from './useCurrentUserImage'\nimport { useCurrentUserName } from './useCurrentUserName'\n// @ts-ignore\nimport { createClient } from \"@/lib/supabase/client\"\n\nconst supabase = createClient()\n\nexport type RealtimeUser = {\n id: string\n name: string\n image: string\n}\n\nexport function useRealtimePresenceRoom(roomName: string) {\n const { image: currentUserImage } = useCurrentUserImage()\n const { name: currentUserName } = useCurrentUserName()\n\n const users = ref>({})\n\n let room: ReturnType | null = null\n\n function setupRoom() {\n if (!roomName) return\n\n room = supabase.channel(roomName)\n\n room\n .on('presence', { event: 'sync' }, () => {\n const newState =\n room?.presenceState<{ image: string; name: string }>() ?? {}\n\n const newUsers = Object.fromEntries(\n Object.entries(newState).map(([key, values]) => {\n const typedValues = values as Array<{ image: string; name: string }>\n if (typedValues.length > 0) {\n return [\n key,\n {\n id: key,\n name: typedValues[0].name,\n image: typedValues[0].image,\n },\n ]\n } else {\n return [\n key,\n {\n id: key,\n name: '',\n image: '',\n },\n ]\n }\n })\n ) as Record\n\n users.value = newUsers\n })\n .subscribe(async (status: REALTIME_SUBSCRIBE_STATES) => {\n if (status === REALTIME_SUBSCRIBE_STATES.SUBSCRIBED && room) {\n await room.track({\n name: currentUserName.value,\n image: currentUserImage.value,\n })\n } else {\n users.value = {}\n }\n })\n }\n\n function cleanup() {\n if (room) {\n room.unsubscribe()\n room = null\n }\n }\n\n watch(\n [() => roomName, currentUserName, currentUserImage],\n () => {\n cleanup()\n setupRoom()\n },\n { immediate: true }\n )\n\n onUnmounted(() => {\n cleanup()\n })\n\n return { users }\n}\n",
+ "content": "import { ref, watch, onUnmounted } from 'vue'\nimport { REALTIME_SUBSCRIBE_STATES } from '@supabase/supabase-js'\n\nimport { useCurrentUserImage } from './useCurrentUserImage'\nimport { useCurrentUserName } from './useCurrentUserName'\n// @ts-ignore\nimport { createClient } from '@/lib/supabase/client'\n\nconst supabase = createClient()\n\nexport type RealtimeUser = {\n id: string\n name: string\n image: string\n}\n\nexport function useRealtimePresenceRoom(roomName: string) {\n const { image: currentUserImage } = useCurrentUserImage()\n const { name: currentUserName } = useCurrentUserName()\n\n const users = ref>({})\n\n let room: ReturnType | null = null\n\n function setupRoom() {\n if (!roomName) return\n\n room = supabase.channel(roomName)\n\n room\n .on('presence', { event: 'sync' }, () => {\n const newState = room?.presenceState<{ image: string; name: string }>() ?? {}\n\n const newUsers = Object.fromEntries(\n Object.entries(newState).map(([key, values]) => {\n const typedValues = values as Array<{ image: string; name: string }>\n if (typedValues.length > 0) {\n return [\n key,\n {\n id: key,\n name: typedValues[0].name,\n image: typedValues[0].image,\n },\n ]\n } else {\n return [\n key,\n {\n id: key,\n name: '',\n image: '',\n },\n ]\n }\n })\n ) as Record\n\n users.value = newUsers\n })\n .subscribe(async (status: REALTIME_SUBSCRIBE_STATES) => {\n if (status === REALTIME_SUBSCRIBE_STATES.SUBSCRIBED && room) {\n await room.track({\n name: currentUserName.value,\n image: currentUserImage.value,\n })\n } else {\n users.value = {}\n }\n })\n }\n\n function cleanup() {\n if (room) {\n room.unsubscribe()\n room = null\n }\n }\n\n watch(\n [() => roomName, currentUserName, currentUserImage],\n () => {\n cleanup()\n setupRoom()\n },\n { immediate: true }\n )\n\n onUnmounted(() => {\n cleanup()\n })\n\n return { users }\n}\n",
"type": "registry:component",
"target": "composables/useRealtimePresenceRoom.ts"
}
diff --git a/blocks/vue/registry/current-user-avatar.ts b/blocks/vue/registry/current-user-avatar.ts
index 09a7d3132c..24a5407e50 100644
--- a/blocks/vue/registry/current-user-avatar.ts
+++ b/blocks/vue/registry/current-user-avatar.ts
@@ -3,4 +3,4 @@ import { type RegistryItem } from 'shadcn/schema'
import nuxtjs from './default/current-user-avatar/nuxtjs/registry-item.json' with { type: 'json' }
import vue from './default/current-user-avatar/vue/registry-item.json' with { type: 'json' }
-export const currentUserAvatar = [nuxtjs, vue] as RegistryItem[]
\ No newline at end of file
+export const currentUserAvatar = [nuxtjs, vue] as RegistryItem[]
diff --git a/blocks/vue/registry/default/current-user-avatar/nuxtjs/app/composables/useCurrentUserImage.ts b/blocks/vue/registry/default/current-user-avatar/nuxtjs/app/composables/useCurrentUserImage.ts
index 4bb0f2c112..a1dd061e7e 100644
--- a/blocks/vue/registry/default/current-user-avatar/nuxtjs/app/composables/useCurrentUserImage.ts
+++ b/blocks/vue/registry/default/current-user-avatar/nuxtjs/app/composables/useCurrentUserImage.ts
@@ -1,6 +1,6 @@
import { ref, onMounted } from 'vue'
// @ts-ignore
-import { createClient } from "@/lib/supabase/client"
+import { createClient } from '@/lib/supabase/client'
export function useCurrentUserImage() {
const image = ref(null)
diff --git a/blocks/vue/registry/default/current-user-avatar/nuxtjs/app/composables/useCurrentUserName.ts b/blocks/vue/registry/default/current-user-avatar/nuxtjs/app/composables/useCurrentUserName.ts
index 98c29cac39..49c77872b3 100644
--- a/blocks/vue/registry/default/current-user-avatar/nuxtjs/app/composables/useCurrentUserName.ts
+++ b/blocks/vue/registry/default/current-user-avatar/nuxtjs/app/composables/useCurrentUserName.ts
@@ -1,6 +1,6 @@
import { ref, onMounted } from 'vue'
// @ts-ignore
-import { createClient } from "@/lib/supabase/client"
+import { createClient } from '@/lib/supabase/client'
export function useCurrentUserName() {
const name = ref(null)
diff --git a/blocks/vue/registry/default/current-user-avatar/nuxtjs/registry-item.json b/blocks/vue/registry/default/current-user-avatar/nuxtjs/registry-item.json
index 4f4aa89e24..f561f2d719 100644
--- a/blocks/vue/registry/default/current-user-avatar/nuxtjs/registry-item.json
+++ b/blocks/vue/registry/default/current-user-avatar/nuxtjs/registry-item.json
@@ -22,4 +22,4 @@
}
],
"dependencies": ["@supabase/supabase-js@latest"]
-}
\ No newline at end of file
+}
diff --git a/blocks/vue/registry/default/current-user-avatar/vue/composables/useCurrentUserImage.ts b/blocks/vue/registry/default/current-user-avatar/vue/composables/useCurrentUserImage.ts
index 4bb0f2c112..a1dd061e7e 100644
--- a/blocks/vue/registry/default/current-user-avatar/vue/composables/useCurrentUserImage.ts
+++ b/blocks/vue/registry/default/current-user-avatar/vue/composables/useCurrentUserImage.ts
@@ -1,6 +1,6 @@
import { ref, onMounted } from 'vue'
// @ts-ignore
-import { createClient } from "@/lib/supabase/client"
+import { createClient } from '@/lib/supabase/client'
export function useCurrentUserImage() {
const image = ref(null)
diff --git a/blocks/vue/registry/default/current-user-avatar/vue/composables/useCurrentUserName.ts b/blocks/vue/registry/default/current-user-avatar/vue/composables/useCurrentUserName.ts
index 98c29cac39..49c77872b3 100644
--- a/blocks/vue/registry/default/current-user-avatar/vue/composables/useCurrentUserName.ts
+++ b/blocks/vue/registry/default/current-user-avatar/vue/composables/useCurrentUserName.ts
@@ -1,6 +1,6 @@
import { ref, onMounted } from 'vue'
// @ts-ignore
-import { createClient } from "@/lib/supabase/client"
+import { createClient } from '@/lib/supabase/client'
export function useCurrentUserName() {
const name = ref(null)
diff --git a/blocks/vue/registry/default/current-user-avatar/vue/registry-item.json b/blocks/vue/registry/default/current-user-avatar/vue/registry-item.json
index 1aea814973..830fd5f31b 100644
--- a/blocks/vue/registry/default/current-user-avatar/vue/registry-item.json
+++ b/blocks/vue/registry/default/current-user-avatar/vue/registry-item.json
@@ -22,4 +22,4 @@
}
],
"dependencies": ["@supabase/supabase-js@latest"]
-}
\ No newline at end of file
+}
diff --git a/blocks/vue/registry/default/realtime-avatar-stack/nuxtjs/app/composables/useCurrentUserImage.ts b/blocks/vue/registry/default/realtime-avatar-stack/nuxtjs/app/composables/useCurrentUserImage.ts
index 4bb0f2c112..a1dd061e7e 100644
--- a/blocks/vue/registry/default/realtime-avatar-stack/nuxtjs/app/composables/useCurrentUserImage.ts
+++ b/blocks/vue/registry/default/realtime-avatar-stack/nuxtjs/app/composables/useCurrentUserImage.ts
@@ -1,6 +1,6 @@
import { ref, onMounted } from 'vue'
// @ts-ignore
-import { createClient } from "@/lib/supabase/client"
+import { createClient } from '@/lib/supabase/client'
export function useCurrentUserImage() {
const image = ref(null)
diff --git a/blocks/vue/registry/default/realtime-avatar-stack/nuxtjs/app/composables/useCurrentUserName.ts b/blocks/vue/registry/default/realtime-avatar-stack/nuxtjs/app/composables/useCurrentUserName.ts
index 98c29cac39..49c77872b3 100644
--- a/blocks/vue/registry/default/realtime-avatar-stack/nuxtjs/app/composables/useCurrentUserName.ts
+++ b/blocks/vue/registry/default/realtime-avatar-stack/nuxtjs/app/composables/useCurrentUserName.ts
@@ -1,6 +1,6 @@
import { ref, onMounted } from 'vue'
// @ts-ignore
-import { createClient } from "@/lib/supabase/client"
+import { createClient } from '@/lib/supabase/client'
export function useCurrentUserName() {
const name = ref(null)
diff --git a/blocks/vue/registry/default/realtime-avatar-stack/nuxtjs/app/composables/useRealtimePresenceRoom.ts b/blocks/vue/registry/default/realtime-avatar-stack/nuxtjs/app/composables/useRealtimePresenceRoom.ts
index a9b073b496..cecd19c79c 100644
--- a/blocks/vue/registry/default/realtime-avatar-stack/nuxtjs/app/composables/useRealtimePresenceRoom.ts
+++ b/blocks/vue/registry/default/realtime-avatar-stack/nuxtjs/app/composables/useRealtimePresenceRoom.ts
@@ -4,7 +4,7 @@ import { REALTIME_SUBSCRIBE_STATES } from '@supabase/supabase-js'
import { useCurrentUserImage } from './useCurrentUserImage'
import { useCurrentUserName } from './useCurrentUserName'
// @ts-ignore
-import { createClient } from "@/lib/supabase/client"
+import { createClient } from '@/lib/supabase/client'
const supabase = createClient()
@@ -29,8 +29,7 @@ export function useRealtimePresenceRoom(roomName: string) {
room
.on('presence', { event: 'sync' }, () => {
- const newState =
- room?.presenceState<{ image: string; name: string }>() ?? {}
+ const newState = room?.presenceState<{ image: string; name: string }>() ?? {}
const newUsers = Object.fromEntries(
Object.entries(newState).map(([key, values]) => {
diff --git a/blocks/vue/registry/default/realtime-avatar-stack/nuxtjs/registry-item.json b/blocks/vue/registry/default/realtime-avatar-stack/nuxtjs/registry-item.json
index 2a20c7e405..0055ca2963 100644
--- a/blocks/vue/registry/default/realtime-avatar-stack/nuxtjs/registry-item.json
+++ b/blocks/vue/registry/default/realtime-avatar-stack/nuxtjs/registry-item.json
@@ -32,4 +32,4 @@
}
],
"dependencies": ["@supabase/supabase-js@latest"]
-}
\ No newline at end of file
+}
diff --git a/blocks/vue/registry/default/realtime-avatar-stack/vue/composables/useCurrentUserImage.ts b/blocks/vue/registry/default/realtime-avatar-stack/vue/composables/useCurrentUserImage.ts
index 4bb0f2c112..a1dd061e7e 100644
--- a/blocks/vue/registry/default/realtime-avatar-stack/vue/composables/useCurrentUserImage.ts
+++ b/blocks/vue/registry/default/realtime-avatar-stack/vue/composables/useCurrentUserImage.ts
@@ -1,6 +1,6 @@
import { ref, onMounted } from 'vue'
// @ts-ignore
-import { createClient } from "@/lib/supabase/client"
+import { createClient } from '@/lib/supabase/client'
export function useCurrentUserImage() {
const image = ref(null)
diff --git a/blocks/vue/registry/default/realtime-avatar-stack/vue/composables/useCurrentUserName.ts b/blocks/vue/registry/default/realtime-avatar-stack/vue/composables/useCurrentUserName.ts
index 98c29cac39..49c77872b3 100644
--- a/blocks/vue/registry/default/realtime-avatar-stack/vue/composables/useCurrentUserName.ts
+++ b/blocks/vue/registry/default/realtime-avatar-stack/vue/composables/useCurrentUserName.ts
@@ -1,6 +1,6 @@
import { ref, onMounted } from 'vue'
// @ts-ignore
-import { createClient } from "@/lib/supabase/client"
+import { createClient } from '@/lib/supabase/client'
export function useCurrentUserName() {
const name = ref(null)
diff --git a/blocks/vue/registry/default/realtime-avatar-stack/vue/composables/useRealtimePresenceRoom.ts b/blocks/vue/registry/default/realtime-avatar-stack/vue/composables/useRealtimePresenceRoom.ts
index 51e2578dfa..b4a78f64e1 100644
--- a/blocks/vue/registry/default/realtime-avatar-stack/vue/composables/useRealtimePresenceRoom.ts
+++ b/blocks/vue/registry/default/realtime-avatar-stack/vue/composables/useRealtimePresenceRoom.ts
@@ -4,7 +4,7 @@ import { REALTIME_SUBSCRIBE_STATES } from '@supabase/supabase-js'
import { useCurrentUserImage } from './useCurrentUserImage'
import { useCurrentUserName } from './useCurrentUserName'
// @ts-ignore
-import { createClient } from "@/lib/supabase/client"
+import { createClient } from '@/lib/supabase/client'
const supabase = createClient()
@@ -29,8 +29,7 @@ export function useRealtimePresenceRoom(roomName: string) {
room
.on('presence', { event: 'sync' }, () => {
- const newState =
- room?.presenceState<{ image: string; name: string }>() ?? {}
+ const newState = room?.presenceState<{ image: string; name: string }>() ?? {}
const newUsers = Object.fromEntries(
Object.entries(newState).map(([key, values]) => {
diff --git a/blocks/vue/registry/default/realtime-avatar-stack/vue/registry-item.json b/blocks/vue/registry/default/realtime-avatar-stack/vue/registry-item.json
index 089b5d74d0..3a8fc209ee 100644
--- a/blocks/vue/registry/default/realtime-avatar-stack/vue/registry-item.json
+++ b/blocks/vue/registry/default/realtime-avatar-stack/vue/registry-item.json
@@ -32,4 +32,4 @@
}
],
"dependencies": ["@supabase/supabase-js@latest"]
-}
\ No newline at end of file
+}
diff --git a/blocks/vue/registry/index.ts b/blocks/vue/registry/index.ts
index e18885012c..5493d9b8a4 100644
--- a/blocks/vue/registry/index.ts
+++ b/blocks/vue/registry/index.ts
@@ -6,6 +6,14 @@ import { socialAuth } from './social-auth'
import { currentUserAvatar } from './current-user-avatar'
import { realtimeAvatarStack } from './realtime-avatar-stack'
-const blocks = [...clients, ...passwordBasedAuth, ...socialAuth, ...dropzone, ...realtimeCursor, ...currentUserAvatar, ...realtimeAvatarStack]
+const blocks = [
+ ...clients,
+ ...passwordBasedAuth,
+ ...socialAuth,
+ ...dropzone,
+ ...realtimeCursor,
+ ...currentUserAvatar,
+ ...realtimeAvatarStack,
+]
export { blocks }
diff --git a/blocks/vue/registry/realtime-avatar-stack.ts b/blocks/vue/registry/realtime-avatar-stack.ts
index 25ca43c8f5..d50e79874d 100644
--- a/blocks/vue/registry/realtime-avatar-stack.ts
+++ b/blocks/vue/registry/realtime-avatar-stack.ts
@@ -3,4 +3,4 @@ import { type RegistryItem } from 'shadcn/schema'
import nuxtjs from './default/realtime-avatar-stack/nuxtjs/registry-item.json' with { type: 'json' }
import vue from './default/realtime-avatar-stack/vue/registry-item.json' with { type: 'json' }
-export const realtimeAvatarStack = [nuxtjs, vue] as RegistryItem[]
\ No newline at end of file
+export const realtimeAvatarStack = [nuxtjs, vue] as RegistryItem[]